HTML基础井字棋游戏仅首行获胜有效,其他判定失效求助
井字棋获胜/平局判定失效问题修复
问题现象
实现HTML版井字棋后,仅首行获胜的判定功能正常,其余获胜位置及平局判定均失效;X与O落子功能无异常,调整获胜组合顺序仅能改变可识别的获胜状态,无法解决所有情况;将解构变量由const改为var也未修复问题。
问题根源
- 循环逻辑错误:原代码在遍历获胜组合时,每检查一个组合未命中就立即判断平局并终止循环,导致后续获胜组合无法被检查,且存在平局误判的情况。
- 事件监听移除无效:移除监听时传入新的匿名函数,与原监听函数引用不一致,无法真正禁止后续落子。
- 模板字符串语法错误:插值表达式中
$与{之间存在空格,导致变量无法正确解析。
修复后的完整代码
HTML
<div class="board"> <div class="square" data-index="0"></div> <div class="square" data-index="1"></div> <div class="square" data-index="2"></div> <div class="square" data-index="3"></div> <div class="square" data-index="4"></div> <div class="square" data-index="5"></div> <div class="square" data-index="6"></div> <div class="square" data-index="7"></div> <div class="square" data-index="8"></div> </div>
CSS
.board { display: flex; flex-wrap: wrap; width: 300px; height: 300px; border: 1px solid #000; } .square { width: 100px; height: 100px; display: flex; align-items: center; justify-content: center; font-size: 48px; font-weight: bold; cursor: pointer; } .x { color: #f00; } .o { color: #00f; }
JavaScript
const board = document.querySelector('.board'); let turn = 'X'; // 提取命名函数,方便移除监听 function handleSquareClick(e) { const square = e.target; if (square.innerText) { return; // 已落子,不处理 } square.innerText = turn; if (turn === 'X') { square.classList.add('x'); turn = 'O'; } else { square.classList.add('o'); turn = 'X'; } checkWin(); // 每步后检查胜负 } board.addEventListener('click', handleSquareClick); function checkWin() { const squares = document.querySelectorAll('.square'); const winningCombos = [ [0, 1, 2], // 首行 [3, 4, 5], // 中行 [6, 7, 8], // 末行 [0, 3, 6], // 左列 [1, 4, 7], // 中列 [2, 5, 8], // 右列 [0, 4, 8], // 左上到右下对角线 [2, 4, 6] // 右上到左下对角线 ]; let winner = null; // 先遍历所有获胜组合,检查是否有赢家 for (const combo of winningCombos) { const [a, b, c] = combo; const value = squares[a].innerText; if (value && value === squares[b].innerText && value === squares[c].innerText) { winner = value; break; } } if (winner) { alert(`Player ${winner} wins!`); board.removeEventListener('click', handleSquareClick); // 正确移除监听 return; } // 无赢家时检查是否平局 if (Array.from(squares).every(s => s.innerText)) { alert('It\'s a draw!'); board.removeEventListener('click', handleSquareClick); } }
修复说明
- 重构循环逻辑:先完整遍历所有获胜组合确认是否有赢家,无赢家时再检查平局,避免提前终止循环导致的判定遗漏。
- 命名事件处理函数:将点击事件的处理逻辑提取为
handleSquareClick,确保移除监听时使用相同的函数引用,真正禁止后续落子。 - 修正模板字符串:移除
$与{之间的空格,确保变量插值正常工作。
内容的提问来源于stack exchange,提问作者calebhk98
相关产品推荐
相关产品推荐

