基于家族函数、闭包与解构的井字棋游戏:数组多索引胜负判断逻辑错误排查求助
解决井字棋胜负判断逻辑错误的问题
嘿,我瞅了你的代码,能立刻定位到几个导致胜负判断失效的关键问题,咱们一步步来修复:
1. 核心错误:逗号运算符的误用
你写的gameBoard[0, 3, 6]这种写法完全不对!JavaScript里的逗号运算符会返回最后一个表达式的值,比如gameBoard[0,3,6]等价于直接取gameBoard[6]——这就是为啥点击单个格子(比如索引2时,你判断的gameBoard[2,5,8]其实是取gameBoard[8])就触发胜利提示,因为你只验证了最后一个索引的位置,根本没检查三个位置是否都被同一玩家占据。
2. 对gameBoard对象的错误操作
你的棋盘数组存在gameBoard.board属性里,但代码里却直接给gameBoard对象加索引属性(比如gameBoard[index] = player.marker),这不仅多余,还会造成数据不一致,咱们只需要操作gameBoard.board数组就行。
3. 冗余代码清理
squares.forEach里嵌套的那个for循环完全没用,直接删掉就好,forEach已经帮你拿到每个格子的索引了。
修复后的完整代码
JavaScript部分
const gameBoard = { board: ["", "", "", "", "", "", "", "", ""], }; function gamePlayers(player, marker) { return { player, marker }; }; const player = gamePlayers('Me', 'X'); const playerTwo = gamePlayers('You', 'O'); // 先定义所有可能的获胜索引组合 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] // 副对角线 ]; // 封装胜负判断函数,逻辑更清晰 function checkWin(board, marker) { // 遍历所有获胜组合,只要有一个组合的所有位置都是当前玩家标记,就返回true return winningCombos.some(combo => { return combo.every(index => board[index] === marker); }); } function gameController(firstPlayer, secondPlayer) { firstPlayer = player; secondPlayer = playerTwo; let turn = 1; const squares = document.querySelectorAll('.squares'); squares.forEach((square, index) => { square.addEventListener('click', () => { // 先判断格子是否已被占用,防止重复点击 if (gameBoard.board[index] !== "") return; if (turn === 1) { gameBoard.board[index] = player.marker; square.textContent = player.marker; turn = 2; // 检查当前玩家是否获胜 if (checkWin(gameBoard.board, player.marker)) { console.log('I win'); // 游戏结束,移除所有格子的点击事件 squares.forEach(sq => sq.removeEventListener('click', arguments.callee)); } } else if (turn === 2) { gameBoard.board[index] = playerTwo.marker; square.textContent = playerTwo.marker; turn = 1; if (checkWin(gameBoard.board, playerTwo.marker)) { console.log('You win'); squares.forEach(sq => sq.removeEventListener('click', arguments.callee)); } } // 检查平局:棋盘填满且无人获胜 if (!gameBoard.board.includes("")) { console.log('It\'s a tie!'); squares.forEach(sq => sq.removeEventListener('click', arguments.callee)); } }); }); return { gameBoard, firstPlayer, secondPlayer }; };
HTML部分(保持不变)
<div class="game-board"> <div class="squares" data-index="0"></div> <div class="squares" data-index="1"></div> <div class="squares" data-index="2"></div> <div class="squares" data-index="3"></div> <div class="squares" data-index="4"></div> <div class="squares" data-index="5"></div> <div class="squares" data-index="6"></div> <div class="squares" data-index="7"></div> <div class="squares" data-index="8"></div> </div>
关键改进说明
- 模块化胜负判断:把获胜组合和判断逻辑单独封装,代码更易读也更容易维护。
- 防止重复操作:添加了格子占用检查,避免玩家重复点击同一个格子。
- 完善游戏流程:游戏结束后自动移除点击事件,防止后续无效操作;还增加了平局判断逻辑。
这样修改后,胜负判断逻辑就完全正确了,不会再出现点击单个格子就触发胜利的乌龙情况啦!
内容的提问来源于stack exchange,提问作者Blazing Jas
相关产品推荐
相关产品推荐

