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
相关产品推荐
相关产品推荐

