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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:17:46