JavaScript井字棋游戏重置函数异常求助:多次重置后电脑多落子
Hey Raj, let's break down why your Tic-Tac-Toe game is glitching after hitting the reset button multiple times, and fix it up!
The Root Cause
The issue is duplicate event listeners. Every time you click the reset button, your code is probably re-binding the click event to each board cell (using addEventListener) without removing the old ones. So if you click reset 6 times, each cell ends up with 6 separate click listeners attached. When you finally click a cell to place an X, all 6 listeners fire off in sequence—each one triggering the player switch and placing an O, hence the 6 Os appearing at once.
The Fix
We need to make sure we don't stack up event listeners. Here are two straightforward ways to fix this:
Option 1: Bind Events Only Once (Recommended)
Move your cell click event binding to a one-time initialization (like when the page loads) instead of re-running it every reset. Reset should only handle clearing the board and resetting game state, not re-attaching events.
Example code adjustment:
// Grab your cell elements once const cells = document.querySelectorAll('.cell'); // Bind click events ONCE when the page loads document.addEventListener('DOMContentLoaded', () => { cells.forEach(cell => cell.addEventListener('click', handleCellClick)); // Start the game with a reset resetGame(); }); // Reset function only handles state/board clearing function resetGame() { cells.forEach(cell => cell.textContent = ''); currentPlayer = 'X'; // Reset back to X // Add any other reset logic (like clearing game status) here } // Your existing cell click handler function handleCellClick(e) { const cell = e.target; // Only proceed if the cell is empty if (cell.textContent !== '') return; cell.textContent = currentPlayer; // Add your win/check logic here... // Switch player currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; }
Option 2: Remove Listeners Before Re-Binding
If you need to re-bind events during reset (for some edge case), first remove the existing listener before adding a new one. This requires using a named function (not an anonymous one) so removeEventListener can target it.
Example:
const cells = document.querySelectorAll('.cell'); function handleCellClick(e) { // Your click logic here... } function resetGame() { cells.forEach(cell => { cell.textContent = ''; // Remove existing listener first cell.removeEventListener('click', handleCellClick); // Re-add the listener cell.addEventListener('click', handleCellClick); }); currentPlayer = 'X'; }
Why This Works
By either binding events once or cleaning up old listeners before re-binding, you ensure each cell only has one active click handler at a time. No more multiple triggers when you place your first X!
内容的提问来源于stack exchange,提问作者Raj

