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

无法实现井字棋(Tic Tac Toe)游戏玩家轮流切换问题求助

问题分析与解决方案

问题根源

  1. 事件绑定时机错误:你在playerMove函数中遍历单元格时,仅在函数执行瞬间根据player-turn类的存在情况为单元格绑定点击事件。第一次调用playerMove时,ticTacToeBoard带有player-turn类,所有单元格都绑定了「X转O」的点击逻辑,后续即使切换类名,这些事件也不会被替换,导致else分支永远无法触发。
  2. 冗余条件判断:else if (ticTacToeBoard.classList.contains("player-turn") === false)完全可以简化为else,因为contains方法返回布尔值,非真即假。
  3. 缺少重复点击限制:当前代码允许同一单元格被多次点击,会不断追加字符,不符合井字棋规则。

修正后的代码

"use strict";
const gameClock = document.querySelector(".clock");
const playerTitle = document.querySelector(".player-title");
const ticTacToeBoard = document.querySelector(".tic-tac-toe-container");
const cells = document.querySelectorAll(".cell");
const startPauseBtn = document.querySelector(".start-btn"); // 修正选择器,原代码遗漏类选择器的点
const resetBtn = document.querySelector(".resetBtn");

let currentPlayer = "X";
ticTacToeBoard.classList.add("player-turn");
playerTitle.innerHTML = "Player: 1"; // 初始化玩家标题

// 统一的单元格点击处理逻辑
const handleCellClick = (cell) => {
  // 单元格已有内容则直接返回,禁止重复点击
  if (cell.textContent.trim() !== "") return;

  cell.append(currentPlayer);
  // 根据当前玩家切换状态
  if (currentPlayer === "X") {
    currentPlayer = "O";
    playerTitle.innerHTML = "Player: 2";
  } else {
    currentPlayer = "X";
    playerTitle.innerHTML = "Player: 1";
  }
  ticTacToeBoard.classList.toggle("player-turn");
};

const playerMove = () => {
  // 给所有单元格绑定统一的点击事件
  cells.forEach((cell) => {
    cell.addEventListener("click", () => handleCellClick(cell));
  });
};

// 调用函数初始化事件绑定
playerMove();

关键修正点

  • 统一事件处理:不再根据初始化状态绑定不同事件,而是在每次点击时实时判断当前玩家状态,执行切换逻辑。
  • 拦截重复点击:通过判断单元格内容是否为空,避免同一位置多次落子。
  • 修正选择器错误:修复了startPauseBtn的选择器,确保能正确选中按钮。
  • 初始化玩家标题:添加初始状态的玩家标题,避免首次点击前标题为空。

内容的提问来源于stack exchange,提问作者Deshawn Reid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:35:25