Simon游戏重启后点击事件异常:调用函数时重复触发逻辑
Simon游戏重启后异常问题解决
问题现象
Simon游戏复刻项目,首次运行完全正常,但首次失败重启后,第二次游戏出现异常:
- 按下正确按钮时,嵌套if条件均满足,但
setTimeout(nextRandomSequence,1500)未执行目标函数 - 按钮点击逻辑被重复触发,
gamePattern变量被重复添加元素,最终userClickedPattern与gamePattern数组无法匹配,游戏误判失败
问题根源
- 重复绑定点击事件:每次通过按键启动游戏时,都会给按钮元素添加新的
click事件监听器,重启游戏后旧的监听器并未被移除,导致按钮被点击时多个监听器同时执行,重复向gamePattern添加元素。 - 启动逻辑无状态控制:没有标记游戏是否处于运行状态,按键事件可被多次触发,叠加启动流程。
修复步骤
1. 分离事件绑定,避免重复绑定
将按钮的click事件监听器移到按键启动事件外部,确保页面加载后只绑定一次,同时通过状态变量控制监听器内的逻辑是否执行。
2. 添加游戏状态标记
新增gameStarted变量,标记游戏是否正在运行,防止重复启动和无效的点击逻辑触发。
3. 修正层级更新逻辑
原nextRandomSequence中level++的位置导致标题显示的层级与实际进度不符,调整为更新标题后再递增层级。
修复后的完整JavaScript代码
let userClickedPattern = []; let gamePattern = []; let buttonColors = ["green", "red", "yellow", "blue"]; let level = 1; let gameStarted = false; // 新增游戏状态标记 // 页面加载后只绑定一次点击事件 $("div[type='button']").click(function(e) { if (!gameStarted) return; // 游戏未启动时不响应点击 let userChosenColor = e.target.id; console.log("user chosen color: " + userChosenColor); pressButtonAnimation(userChosenColor); playSound(userChosenColor); userClickedPattern.push(userChosenColor); console.log("compare arrays userClicked/gamePattern " + userClickedPattern + " " + gamePattern); if (userClickedPattern[userClickedPattern.length - 1] === gamePattern[userClickedPattern.length - 1]) { if (userClickedPattern.length === gamePattern.length) { $("#level-title").text("Level " + level); console.log(level); console.log("----- continue ---------"); setTimeout(nextRandomSequence, 1500); } } else { console.log("----- game over ---------"); playSound("wrong"); gameOverAnimation(userChosenColor); $("#level-title").text("GAME OVER, your arrived to level " + level + " press any key to start"); restartGame(); console.log(level); } }); // 按键启动游戏逻辑 $(document).keypress(function() { if (gameStarted) return; // 游戏已启动时不重复触发 gameStarted = true; $("#level-title").text("Level " + level); nextRandomSequence(); }); function nextRandomSequence() { console.log("--------- inside nextRandomSequence -------------") userClickedPattern = []; const randomNumber = Math.floor(Math.random() * 4); const randomChosenColor = buttonColors[randomNumber]; gamePattern.push(randomChosenColor); $("#" + randomChosenColor).fadeIn(300).fadeOut(300).fadeIn(300); playSound(randomChosenColor); $("#level-title").text("Level " + level); // 先更新标题 level++; // 再递增层级 console.log("random chosen color " + randomChosenColor); } function playSound(name) { var audio = new Audio("sounds/" + name + ".mp3"); audio.play(); } function pressButtonAnimation(colorPressed) { $("#" + colorPressed).addClass("pressed"); setTimeout(function() { $("#" + colorPressed).removeClass("pressed"); }, 100); } function gameOverAnimation(colorPressed) { $("body").addClass("game-over"); setTimeout(function() { $("body").removeClass("game-over"); }, 200); } function restartGame() { level = 1; gamePattern = []; gameStarted = false; // 重置游戏状态 }
说明
- 原CSS和HTML代码无需修改,仅调整JavaScript部分即可解决问题
- 新增的
gameStarted变量有效控制了游戏启动状态和点击逻辑的有效性 - 点击事件只绑定一次,彻底解决了重复触发逻辑的问题
内容的提问来源于stack exchange,提问作者adrian
相关产品推荐
相关产品推荐

