You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

猜颜色游戏点击Play Again后无法触发获胜条件求助

猜颜色游戏Play Again后无法触发获胜条件问题排查

我是编程新手,听说这里是提问的最佳平台!以下是我的问题:

我开发了一款猜颜色JavaScript游戏,首次运行正常,选择正确颜色会显示"You Win 🎉";但点击Play Again按钮重置游戏后,无论选择正确选项都无法触发获胜条件。原本使用全局变量pickedColor时功能正常,为精简代码减少全局变量后出现该问题,恳请帮忙排查。

游戏代码如下:

'use strict'

//DOM Elements declaration.
const square = document.getElementById("color1")
const guesses = document.getElementsByClassName("guess");
const guessArr = [...guesses]
const playAgain = document.querySelector(".play-again");
const title = document.getElementById("title")

var playing = true;

init();


function init() {
    let pickedColor = createColor();
    console.log(pickedColor);
    title.innerHTML = "GUESS THE COLOUR!"
    square.style.backgroundColor = pickedColor;
    playing = true;
    updateGuesses(pickedColor);
    guess(pickedColor);
}

//Setting the playing field.
function createColor () {
    let r = Math.floor(Math.random() * 255);
    let g = Math.floor(Math.random() * 255);
    let b = Math.floor(Math.random() * 255); 
    let color = `rgb(${r}, ${g}, ${b})`
    return color
}

function updateGuesses (pickedColor) {
    for (let i=0; i < 3; i++){
        guesses[i].textContent = createColor() // Button[0] = rgb(random, random, random)...
    }
    //Pick a random button at runtime and make it the right guess.
    let correct = guesses[Math.floor(Math.random() * 3)];
    correct.textContent = pickedColor 
}

//Playing the game
function guess(pickedColor){
    guessArr.forEach((guess) => {
        guess.addEventListener("click", ()=>{
            console.log(guess.textContent);
            if (playing){
                if (guess.textContent == pickedColor){
                    title.innerHTML = "You Win 🎉"
                    playing = false;
                    document.querySelector("body").style.backgroundColor = pickedColor;
                } else {
                    title.innerHTML = "YOU LOSE ❌"
                    playing = false;
                }
            } 
        })
    });
}

playAgain.addEventListener("click", init)

问题根源

核心问题是每次调用init()时都会给按钮重复添加点击事件监听器:

  • 第一次游戏运行时,按钮绑定了对应第一局pickedColor的点击事件;
  • 点击Play Again后,init()再次调用guess(),又给按钮绑定了新的点击事件(对应新的pickedColor);
  • 此时按钮上同时存在多轮游戏的事件监听器,点击按钮时会先触发旧事件——旧事件里的pickedColor是第一局的颜色,和当前按钮的文本(新的正确颜色)不匹配,直接触发YOU LOSE ❌并把playing设为false,后续新事件因为playing为false无法执行。

解决方案

方案1:移除旧事件监听器后再绑定新事件

把点击处理函数抽成独立函数,方便移除和重新绑定:

'use strict'

//DOM Elements declaration.
const square = document.getElementById("color1")
const guesses = document.getElementsByClassName("guess");
const guessArr = [...guesses]
const playAgain = document.querySelector(".play-again");
const title = document.getElementById("title")

var playing = true;
// 声明全局点击处理函数,用于后续移除旧监听器
let clickHandler;

init();


function init() {
    let pickedColor = createColor();
    console.log(pickedColor);
    title.innerHTML = "GUESS THE COLOUR!"
    square.style.backgroundColor = pickedColor;
    playing = true;
    updateGuesses(pickedColor);
    guess(pickedColor);
}

function createColor () {
    let r = Math.floor(Math.random() * 255);
    let g = Math.floor(Math.random() * 255);
    let b = Math.floor(Math.random() * 255); 
    let color = `rgb(${r}, ${g}, ${b})`
    return color
}

function updateGuesses (pickedColor) {
    for (let i=0; i < 3; i++){
        guesses[i].textContent = createColor()
    }
    let correct = guesses[Math.floor(Math.random() * 3)];
    correct.textContent = pickedColor 
}

function guess(pickedColor){
    // 先移除所有按钮的旧监听器
    guessArr.forEach((guess) => {
        if (clickHandler) {
            guess.removeEventListener("click", clickHandler);
        }
    });
    // 定义当前游戏的点击处理逻辑
    clickHandler = function() {
        console.log(this.textContent);
        if (playing){
            if (this.textContent === pickedColor){
                title.innerHTML = "You Win 🎉"
                playing = false;
                document.querySelector("body").style.backgroundColor = pickedColor;
            } else {
                title.innerHTML = "YOU LOSE ❌"
                playing = false;
            }
        } 
    };
    // 绑定新的监听器
    guessArr.forEach((guess) => {
        guess.addEventListener("click", clickHandler);
    });
}

playAgain.addEventListener("click", init)

方案2:使用事件委托(推荐)

只在父元素上绑定一次事件,通过事件冒泡判断点击目标,避免重复绑定的问题:

'use strict'

//DOM Elements declaration.
const square = document.getElementById("color1")
// 假设按钮有统一的父容器,若无则可用document.body
const guessesContainer = document.querySelector(".guesses-container"); 
const playAgain = document.querySelector(".play-again");
const title = document.getElementById("title")

var playing = true;
// 用变量存储当前游戏的正确颜色
let currentPickedColor;

init();


function init() {
    currentPickedColor = createColor();
    console.log(currentPickedColor);
    title.innerHTML = "GUESS THE COLOUR!"
    square.style.backgroundColor = currentPickedColor;
    playing = true;
    updateGuesses(currentPickedColor);
}

function createColor () {
    let r = Math.floor(Math.random() * 255);
    let g = Math.floor(Math.random() * 255);
    let b = Math.floor(Math.random() * 255); 
    let color = `rgb(${r}, ${g}, ${b})`
    return color
}

function updateGuesses (pickedColor) {
    const guesses = document.getElementsByClassName("guess");
    for (let i=0; i < 3; i++){
        guesses[i].textContent = createColor()
    }
    let correct = guesses[Math.floor(Math.random() * 3)];
    correct.textContent = pickedColor 
}

// 仅绑定一次事件委托
guessesContainer.addEventListener("click", function(e) {
    // 判断点击目标是猜色按钮且游戏正在进行
    if (e.target.classList.contains("guess") && playing) {
        const clickedText = e.target.textContent;
        console.log(clickedText);
        if (clickedText === currentPickedColor){
            title.innerHTML = "You Win 🎉"
            playing = false;
            document.querySelector("body").style.backgroundColor = currentPickedColor;
        } else {
            title.innerHTML = "YOU LOSE ❌"
            playing = false;
        }
    }
});

playAgain.addEventListener("click", init)

内容的提问来源于stack exchange,提问作者Remel Crowe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 17:50:34