为何将按钮点击事件放入函数后,我的Simon游戏JS代码出错?
Simon游戏按钮点击事件绑定问题排查与修复
你把按钮点击事件放到nextSequence里的做法会导致重复绑定事件处理器——每次调用nextSequence(比如每升一级),就会给所有.btn多绑一次点击回调。这意味着当用户点击按钮时,同一个逻辑会被执行多次:比如到Level 3时,按钮已经被绑定了3次点击事件,点击一次会往userClickedPattern里push3次相同颜色,直接导致checkAnswer判断出错,程序逻辑混乱。
另外,游戏结束后(gameStarted=false),之前绑定的所有点击事件依然存在,用户点击按钮还是会触发回调,这也不符合你“仅游戏开始后按钮才可点击”的需求。
方案一:绑定事件+状态判断(最简单)
保留点击事件的外部绑定,在回调开头加入gameStarted状态判断,只有游戏启动后才执行后续逻辑。这样既实现了“未开始时点击无效”的需求,又不会出现重复绑定的问题:
var buttonColours = ["red", "blue", "green", "yellow"]; var gamePattern = []; var userClickedPattern = []; var gameStarted = false; var level = 0; $(document).on("keydown", function (e){ if (gameStarted===false) { gameStarted = true; level = 0; // 去掉原代码中的var,避免局部变量覆盖全局level $("#level-title").text("Level " + level); nextSequence(); } }); // 点击事件保留在外部,加入状态判断 $(".btn").on("click", function () { // 游戏未开始时直接返回,不执行任何逻辑 if (!gameStarted) return; var userChosenColour = $(this).attr("id"); userClickedPattern.push(userChosenColour); playSound(userChosenColour); animatePress(userChosenColour); checkAnswer(userClickedPattern.length - 1); }); function nextSequence() { userClickedPattern = []; level++; $("#level-title").text("Level " + level); var randomNumber = Math.floor(Math.random() * 4); var randomChosenColour = buttonColours[randomNumber]; gamePattern.push(randomChosenColour); $("#" + randomChosenColour).fadeOut(100).fadeIn(100).fadeOut(100).fadeIn(100); playSound(randomChosenColour); } function playSound(name) { var playAudio = new Audio("./sounds/"+name+".mp3"); playAudio.play(); } function animatePress(currentColour) { $("#" + currentColour).addClass("pressed"); setTimeout(function() { $("#" + currentColour).removeClass("pressed")}, 100); } function checkAnswer(currentLevel) { if(gamePattern[currentLevel] === userClickedPattern[currentLevel]) { if (currentLevel === level - 1) { setTimeout(function () { nextSequence();}, 600); } } else { $("body").addClass("game-over") setTimeout(function() { $("body").removeClass("game-over"); }, 200); var wrongAudio = new Audio("./sounds/wrong.mp3"); wrongAudio.play(); $("#level-title").text("Game Over, Press Any Key to Restart"); level = 0; gamePattern = []; gameStarted = false; } }
方案二:动态绑定/解绑事件
如果一定要通过动态绑定事件来实现,可以在游戏开始时绑定点击事件,游戏结束时解绑;同时注意每次绑定前先解绑,避免重复绑定:
var buttonColours = ["red", "blue", "green", "yellow"]; var gamePattern = []; var userClickedPattern = []; var gameStarted = false; var level = 0; $(document).on("keydown", function (e){ if (gameStarted===false) { gameStarted = true; level = 0; $("#level-title").text("Level " + level); // 游戏开始时绑定点击事件 bindButtonClicks(); nextSequence(); } }); function bindButtonClicks() { // 先解绑之前的事件,避免重复绑定 $(".btn").off("click"); $(".btn").on("click", function () { var userChosenColour = $(this).attr("id"); userClickedPattern.push(userChosenColour); playSound(userChosenColour); animatePress(userChosenColour); checkAnswer(userClickedPattern.length - 1); }); } function nextSequence() { userClickedPattern = []; level++; $("#level-title").text("Level " + level); var randomNumber = Math.floor(Math.random() * 4); var randomChosenColour = buttonColours[randomNumber]; gamePattern.push(randomChosenColour); $("#" + randomChosenColour).fadeOut(100).fadeIn(100).fadeOut(100).fadeIn(100); playSound(randomChosenColour); } function checkAnswer(currentLevel) { if(gamePattern[currentLevel] === userClickedPattern[currentLevel]) { if (currentLevel === level - 1) { setTimeout(function () { nextSequence();}, 600); } } else { $("body").addClass("game-over") setTimeout(function() { $("body").removeClass("game-over"); }, 200); var wrongAudio = new Audio("./sounds/wrong.mp3"); wrongAudio.play(); $("#level-title").text("Game Over, Press Any Key to Restart"); level = 0; gamePattern = []; gameStarted = false; // 游戏结束时解绑按钮点击事件 $(".btn").off("click"); } } function playSound(name) { var playAudio = new Audio("./sounds/"+name+".mp3"); playAudio.play(); } function animatePress(currentColour) { $("#" + currentColour).addClass("pressed"); setTimeout(function() { $("#" + currentColour).removeClass("pressed")}, 100); }
内容的提问来源于stack exchange,提问作者Kanaris
相关产品推荐
相关产品推荐

