Vanilla JS井字棋游戏:胜负/平局提示异常问题求助
井字棋游戏胜负与平局提示异常问题修复
我在用Vanilla JS开发井字棋游戏时遇到两个问题:
- 玩家回合切换提示正常,但获胜提示始终不出现
- 平局提示会在棋盘为空时自动弹出,无需任何操作
原实现代码
HTML部分
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1" /> <link rel="stylesheet" href="style.css"> </head> <body> <h1>TIC-TAC-TOE</h1> <h2 id="player1"> Player 1: </h2> <h2 id="player2">Player 2: </h2> <h2 id="result"></h2> <table id="board"> <tr> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> </tr> </table> <button>Restart</button> </body> <script src="app.js"></script> </html>
JS部分
let players = ['x', 'o'] let board = [ null, null, null, null, null, null, null, null, null ] let boardWins = [ [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 result = document.getElementById('result') let cells = document.querySelectorAll('td') let currentPlayer = players[0] cells.forEach(function(cell) { cell.addEventListener('click', function() { if (cell.innerHTML != '') { return; } if (!cell) { return; } if (currentPlayer === players[0]) { currentPlayer = players[1] cell.innerHTML = players[0] result.innerHTML = "Player O's turn!" } else if (currentPlayer === players[1]){ currentPlayer = players[0] cell.innerHTML = players[1] result.innerHTML = "Player X's turn!" } }) wins() }) function wins() { for (let i = 0; i < boardWins.length; i++) { let win = boardWins[i] let zero = win[0] let one = win[1] let two = win[2] if (board[zero] === players[0] && board[zero] === board[one] && board[zero] === board[two]) { result.innerHTML = 'Player X wins!' } else if (board[i] != null) { result.innerHTML = 'Draw!' } } } }
问题根源
- 获胜判断失效:
board数组从未同步页面上的落子操作,始终是初始全null状态,导致胜负判断条件永远不满足。 - 平局提示异常:
wins()函数在页面加载时就被调用(cells.forEach里直接执行wins()),而非落子后触发- 平局判断逻辑错误:用
board[i] != null,这里的i是获胜组合数组的索引(0-7),不是棋盘格子索引,只要board[0]到board[7]中有一个不为null就触发平局,完全不符合逻辑。
- 胜负检查时机错误:没有在每次玩家落子后立即检查胜负状态。
修复后的JS代码
let players = ['x', 'o'] let board = [null, null, null, null, null, null, null, null, null] let boardWins = [ [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 result = document.getElementById('result') let cells = document.querySelectorAll('td') let currentPlayer = players[0] let gameOver = false // 新增游戏结束状态,防止后续操作 // 绑定格子点击事件 cells.forEach(function(cell, index) { // 获取cell索引,对应board数组位置 cell.addEventListener('click', function() { if (gameOver || cell.innerHTML !== '') { return; // 游戏结束或格子已被占用,直接返回 } // 落子并同步更新board数组 cell.innerHTML = currentPlayer board[index] = currentPlayer // 检查是否获胜 if (checkWinner()) { result.innerHTML = `Player ${currentPlayer.toUpperCase()} wins!` gameOver = true return } // 检查是否平局 if (checkDraw()) { result.innerHTML = 'Draw!' gameOver = true return } // 切换玩家 currentPlayer = currentPlayer === players[0] ? players[1] : players[0] result.innerHTML = `Player ${currentPlayer.toUpperCase()}'s turn!` }) }) // 检查获胜逻辑 function checkWinner() { for (let win of boardWins) { const [a, b, c] = win if (board[a] && board[a] === board[b] && board[a] === board[c]) { return true } } return false } // 检查平局逻辑 function checkDraw() { return board.every(cell => cell !== null) } // 重启按钮功能 document.querySelector('button').addEventListener('click', function() { board.fill(null) cells.forEach(cell => cell.innerHTML = '') currentPlayer = players[0] gameOver = false result.innerHTML = `Player X's turn!` })
关键修改点
- 落子时通过格子索引同步更新
board数组,让胜负判断有正确的数据依据 - 将胜负、平局判断拆分为独立函数,逻辑更清晰
- 新增
gameOver状态,避免获胜或平局后继续落子 - 调整检查时机,每次落子后立即判断胜负
- 修复平局逻辑:通过
board.every()判断所有格子是否被占用 - 增加重启按钮功能,完善游戏体验
内容的提问来源于stack exchange,提问作者cgyipj
相关产品推荐
相关产品推荐

