FreeCodeCamp Simon游戏重置后点击监听器触发两次问题
Hey there! Let's dig into why clicking color pads is adding two entries to your guessingColors array after restarting the game. This is a super common issue with interactive games, and it almost always boils down to repeated event listeners or missing state resets. Let's break it down step by step:
The Most Likely Culprit: Duplicate Event Listeners
Chances are, every time you start a new game, you're re-binding click event listeners to your color pads—without removing the old ones first. So after a reset and restart, each pad has two (or more) listeners attached. When you click, both listeners fire, pushing the color twice into guessingColors.
How to Fix It
There are a few clean ways to solve this:
1. Bind Listeners Only Once (Recommended)
Move your event binding code outside of your startGame function, so it runs only once when the page loads. Then use a game state flag to control whether clicks should register:
// Define a global flag to track if the game is active let isGameActive = false; // Define your click handler as a named function (not anonymous) function handleColorClick(e) { // Ignore clicks if the game isn't active if (!isGameActive) return; const selectedColor = e.target.dataset.color; // Adjust this to match your element setup guessingColors.push(selectedColor); // Rest of your click logic (play sound, check guess, etc.) } // Bind listeners ONCE when the page loads document.querySelectorAll('.color-pad').forEach(pad => { pad.addEventListener('click', handleColorClick); }); function reset() { clearTimeout(repeating); clearTimeout(genColor); pickedColors = []; guessingColors = []; isGameActive = false; // Reset the game state flag // Add any other resets (like score, round number, etc.) } function startGame() { reset(); // Reset first to clear old state isGameActive = true; // Activate the game // Generate first color, start round logic, etc. }
2. Remove Listeners in Your Reset Function
If you need to re-bind listeners for some reason, make sure to remove them in reset first. Just note: you can only remove listeners that use named functions (anonymous functions can't be targeted):
function reset() { clearTimeout(repeating); clearTimeout(genColor); pickedColors = []; guessingColors = []; // Remove existing click listeners document.querySelectorAll('.color-pad').forEach(pad => { pad.removeEventListener('click', handleColorClick); }); } function startGame() { reset(); // Re-bind listeners (only do this if you have a specific reason to) document.querySelectorAll('.color-pad').forEach(pad => { pad.addEventListener('click', handleColorClick); }); // Start game logic... }
Other Things to Check
- Uncleared Timers: Double-check that all timers (not just
repeatingandgenColor) are cleared inreset. If a leftover timer is triggering code that modifiesguessingColors, that could also cause duplicates. - Accidental Array Duplication: Make sure your
startGamefunction isn't accidentally initializingguessingColorstwice or pushing to it automatically without user input.
Give these fixes a try—most likely the duplicate event listeners are the root cause!
内容的提问来源于stack exchange,提问作者Merim

