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

JavaScript井字棋游戏点击后X/O无法显示问题求助

井字棋游戏点击无标记问题排查与修复

以下是导致点击单元格无法显示X/O标记的几个关键错误,以及对应的修复方案:

1. JavaScript常量与语法错误

  • 拼写错误:
    • 胜利组合常量名WINNING_COMBITNATIONS应为WINNING_COMBINATIONS;
    • isDraw函数中误用Player_X_CLASS,正确应为PLAYER_X_CLASS;
    • setBoardHoverClass函数中IsPlayer_O_Turn首字母大写错误,正确应为isPlayer_O_Turn。
  • 数组语法错误:
    胜利组合数组中多处使用圆括号(如[(3,4,5)])和嵌套数组(如[[2,4,6]]),需改为标准数组格式[3,4,5]和[2,4,6]。
  • 模板字符串错误:
    endGame函数中获胜消息用单引号包裹,导致变量无法解析,需改为反引号:
    winningMessageTextElement.innerText = `Player with ${isPlayer_O_Turn ? "O's" : "X's"} wins!`;
    

2. CSS变量与选择器错误

  • 根变量定义错误:--1: 10px应为--l: 10px(与后续var(--l)对应);
  • 悬停效果选择器错误:.board.circle .cell.not(.circle)中的.not应为:not伪类,正确写法是.board.circle .cell:not(.circle):not(.x):hover。

3. HTML元素ID错误

获胜消息文本元素ID为winningMesssageText(多一个s),需改为winningMessageText,与JS中的winningMessageTextElement = document.getElementById("winningMessageText")匹配。


修复后的完整代码

JavaScript

const PLAYER_X_CLASS = "x";
const PLAYER_O_CLASS = "circle";
const WINNING_COMBINATIONS = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8],
  [0, 4, 8],
  [2, 4, 6]
];

const cellElements = document.querySelectorAll("[data-cell]");
const boardElement = document.getElementById("board");
const winningMessageElement = document.getElementById("winningMessage");
const restartButton = document.getElementById("restartButton");
const winningMessageTextElement = document.getElementById("winningMessageText");
let isPlayer_O_Turn = false;

startGame();

restartButton.addEventListener("click", startGame);

function startGame() {
  isPlayer_O_Turn = false;
  cellElements.forEach((cell) => {
    cell.classList.remove(PLAYER_X_CLASS);
    cell.classList.remove(PLAYER_O_CLASS);
    cell.removeEventListener("click", handleCellClick);
    cell.addEventListener("click", handleCellClick, { once: true });
  });
  setBoardHoverClass();
  winningMessageElement.classList.remove("show");
}

function handleCellClick(e) {
  const cell = e.target;
  const currentClass = isPlayer_O_Turn ? PLAYER_O_CLASS : PLAYER_X_CLASS;
  placeMark(cell, currentClass);
  if (checkWin(currentClass)) {
    endGame(false);
  } else if (isDraw()) {
    endGame(true);
  } else {
    swapTurns();
    setBoardHoverClass();
  }
}

function endGame(draw) {
  if (draw) {
    winningMessageTextElement.innerText = "平局!";
  } else {
    winningMessageTextElement.innerText = `${isPlayer_O_Turn ? "O" : "X"}方获胜!`;
  }
  winningMessageElement.classList.add("show");
}

function isDraw() {
  return [...cellElements].every((cell) => {
    return cell.classList.contains(PLAYER_X_CLASS) || cell.classList.contains(PLAYER_O_CLASS);
  });
}

function placeMark(cell, currentClass) {
  cell.classList.add(currentClass);
}

function swapTurns() {
  isPlayer_O_Turn = !isPlayer_O_Turn;
}

function setBoardHoverClass() {
  boardElement.classList.remove(PLAYER_X_CLASS);
  boardElement.classList.remove(PLAYER_O_CLASS);

  if (isPlayer_O_Turn) {
    boardElement.classList.add(PLAYER_O_CLASS);
  } else {
    boardElement.classList.add(PLAYER_X_CLASS);
  }
}

function checkWin(currentClass) {
  return WINNING_COMBINATIONS.some((combination) => {
    return combination.every((index) => {
      return cellElements[index].classList.contains(currentClass);
    });
  });
}

CSS

:root {
  --cell-size: 100px;
  --color: #81c3fd;
  --color-set: #0275d8;
  --l: 10px;
}

body {
  margin: 0;
}

.board {
  width: 100vw;
  height: 100vh;
  display: grid;
  justify-content: center;
  align-content: center;
  justify-items: center;
  align-items: center;
  grid-template-columns: repeat(3, auto);
}

.cell {
  width: var(--cell-size);
  height: var(--cell-size);
  border: 1px solid black;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  cursor: pointer;
}

/* 移除边缘格子的边框 */
.cell:nth-child(1),
.cell:nth-child(2),
.cell:nth-child(3) {
  border-top: none;
}

.cell:nth-child(1),
.cell:nth-child(4),
.cell:nth-child(7) {
  border-left: none;
}

.cell:nth-child(3),
.cell:nth-child(6),
.cell:nth-child(9) {
  border-right: none;
}

.cell:nth-child(7),
.cell:nth-child(8),
.cell:nth-child(9) {
  border-bottom: none;
}

.cell.x,
.cell.circle {
  cursor: not-allowed;
}

/* X的悬停样式 */
.board.x .cell:not(.circle):not(.x):hover {
  background: linear-gradient(to top right, transparent calc(50% - var(--l) / 2), var(--color) calc(50% - var(--l) / 2) calc(50% + var(--l) / 2), transparent calc(50% + var(--l) / 2)), linear-gradient(to bottom right, transparent calc(50% - var(--l) / 2), var(--color) calc(50% - var(--l) / 2) calc(50% + var(--l) / 2), transparent calc(50% + var(--l) / 2));
  background-size: 80% 80%;
  background-repeat: no-repeat;
  background-position: center;
}

/* X的选中样式 */
.cell:not(.circle).x {
  background: linear-gradient(to top right, transparent calc(50% - var(--l) / 2), var(--color-set) calc(50% - var(--l) / 2) calc(50% + var(--l) / 2), transparent calc(50% + var(--l) / 2)), linear-gradient(to bottom right, transparent calc(50% - var(--l) / 2), var(--color-set) calc(50% - var(--l) / 2) calc(50% + var(--l) / 2), transparent calc(50% + var(--l) / 2));
  background-size: 80% 80%;
  background-repeat: no-repeat;
  background-position: center;
}

/* O的悬停样式 */
.board.circle .cell:not(.circle):not(.x):hover {
  background: radial-gradient(var(--color) 60%, transparent 60%);
}

/* O的选中样式 */
.cell:not(.x).circle {
  background: radial-gradient(var(--color-set) 60%, transparent 60%);
}

.winning-message {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: var(--color-set);
  justify-content: center;
  align-items: center;
  color: white;
  font-size: 5rem;
  font-family: 'Courier New', Courier, monospace;
  flex-direction: column;
}

.winning-message button {
  border-radius: 10px;
  font-size: 3rem;
  background-color: white;
  border: 1px solid var(--color-set);
  padding: .25em .5em;
  cursor: pointer;
}

.winning-message button:hover {
  background-color: var(--color-set);
  color: white;
  border-color: white;
}

.winning-message.show {
  display: flex;
}

HTML

<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="Tic_Tac_Toe.css" />
<title>井字棋</title>

<div class="board" id="board">
  <div class="cell" data-cell></div>
  <div class="cell" data-cell></div>
  <div class="cell" data-cell></div>
  <div class="cell" data-cell></div>
  <div class="cell" data-cell></div>
  <div class="cell" data-cell></div>
  <div class="cell" data-cell></div>
  <div class="cell" data-cell></div>
  <div class="cell" data-cell></div>
</div>

<div class="winning-message" id="winningMessage">
  <div id="winningMessageText"></div>
  <button id="restartButton">重新开始</button>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 08:15:35