井字棋重启后X需走两步才切换至O的问题排查
井字棋重启后落子切换异常问题修复
问题描述
给井字棋添加重启功能后,出现如下异常:X获胜后点击重启按钮,默认X为先手,但需要X连续走两步才会切换到O落子。通过DevTools能看到重启后board元素带有x类,但X走棋后并未切换至O回合。
相关代码:
const board = document.getElementById('board') const cell = document.querySelectorAll('.cell') const displayOutcome = document.getElementById('display-outcome') const winningMessge = document.getElementById('winning-message') const restart = document.getElementById('restart') let nextTurn = 'x' 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] ] restartGame() board.addEventListener('click', (e) => { let icon = document.createElement('i') if (e.target.classList.contains('cell')) { if (board.classList.contains('x')) { icon.classList.add('fa-solid', 'fa-x') e.target.appendChild(icon) e.target.classList.add('x') } if (board.classList.contains('o')) { icon.classList.add('fa-solid', 'fa-o') e.target.appendChild(icon) e.target.classList.add('o') } } if (isDraw()) { winningMessge.innerText = 'Draw!' displayOutcome.classList.add('show') } if (checkWinner(nextTurn)) { winningMessge.innerText = `${nextTurn}'s Wins` displayOutcome.classList.add('show') } changeTurns() console.log(nextTurn) }) function changeTurns() { if (nextTurn === 'x') { nextTurn = 'o' board.classList.replace('x', 'o') } else { nextTurn = 'x' board.classList.replace('o', 'x') } } function checkWinner (nextTurn) { return winningCombos.some(combo => { return combo.every(index => { return cell[index].classList.contains(nextTurn) }) }) } function isDraw() { return [...cell].every(cell => { return cell.classList.contains('x') || cell.classList.contains('o') }) } function restartGame() { cell.forEach(cell => { cell.innerHTML = '' displayOutcome.classList.remove('show') cell.classList.remove('o', 'x') board.classList.remove('o', 'x') board.classList.add('x') }) } restart.addEventListener('click', restartGame)
问题原因
重启函数只重置了board的class属性,但没有同步更新全局变量nextTurn。上一局X获胜后,changeTurns()已经把nextTurn改成了'o',重启后nextTurn依然是'o'。此时X走棋后调用changeTurns(),会把nextTurn从'o'切回'x',导致需要X再走一步才会轮到O。
修复方案
在restartGame函数中添加对nextTurn的重置,让它和board的class保持一致,同时优化代码逻辑(把displayOutcome.classList.remove('show')移出循环,避免重复执行):
function restartGame() { // 清空所有单元格内容和标记 cell.forEach(cell => { cell.innerHTML = '' cell.classList.remove('o', 'x') }) // 隐藏结果弹窗 displayOutcome.classList.remove('show') // 重置棋盘的先手标记 board.classList.remove('o', 'x') board.classList.add('x') // 关键:同步重置先手变量 nextTurn = 'x' }
内容的提问来源于stack exchange,提问作者Joe.sexton
相关产品推荐
相关产品推荐

