React井字棋平局判断Bug排查求助
井字棋游戏平局判断Bug排查
问题描述
我正在学习React官方文档,尝试给教程中的井字棋游戏添加平局判断功能。但实现判断胜负的辅助函数后出现Bug:当9个格子全部填满且明显存在胜者时,界面有时显示胜者,有时显示平局。
异常界面

原代码
function Square(props) { return ( <button className="square" onClick={props.onClick}> {props.value} </button> ); } class Board extends React.Component { constructor(props) { super(props); this.state = { squares: Array(9).fill(null), xIsNext: true, } } handleClick(i){ const squares = this.state.squares.slice(); if(calculateWinner(squares) || squares[i]) { return; } squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({squares: squares, xIsNext: !this.state.xIsNext,}) } renderSquare(i) { return <Square value={this.state.squares[i]} onClick={()=>this.handleClick(i)} />; } render() { const winner = calculateWinner(this.state.squares); let status; if(winner) { status = 'Winner: ' + winner; } else { status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); } return ( <div> <div className="status">{status}</div> <div className="board-row"> {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)} </div> <div className="board-row"> {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)} </div> <div className="board-row"> {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)} </div> </div> ); } } class Game extends React.Component { render() { return ( <div className="game"> <div className="game-board"> <Board /> </div> <div className="game-info"> <div>{/* status */}</div> <ol>{/* TODO */}</ol> </div> </div> ); } } const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<Game />); function calculateWinner(squares, counter) { const lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6], ]; for (let i = 0; i < lines.length; i++) { const [a, b, c] = lines[i]; const squaresFilled = squares.every(value => value !== null); const threeSquaresEqual = squares[a] && squares[a] === squares[b] && squares[a] === squares[c] console.log(!threeSquaresEqual) if(threeSquaresEqual) { return squares[a]; } else if(squaresFilled && threeSquaresEqual) { return "Draw"; } } return null; }
Bug原因分析
- 逻辑顺序错误:在
calculateWinner的循环中,每检查一条获胜线就同时判断平局,逻辑顺序混乱。正确流程应该是先确认是否有胜者,再判断是否平局。 - 条件判断矛盾:平局的判断条件
squaresFilled && threeSquaresEqual永远不可能成立——threeSquaresEqual为真时,已经在第一个if分支返回胜者,不会走到平局分支。 - 冗余参数:函数声明了
counter参数但从未使用,属于无效代码。
修复方案
1. 修正calculateWinner函数
调整逻辑顺序:先遍历所有获胜线找胜者,无胜者时再检查棋盘是否填满,填满则返回平局。
function calculateWinner(squares) { const lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6], ]; // 先检查是否有胜者 for (let i = 0; i < lines.length; i++) { const [a, b, c] = lines[i]; const threeSquaresEqual = squares[a] && squares[a] === squares[b] && squares[a] === squares[c] if(threeSquaresEqual) { return squares[a]; } } // 无胜者时检查是否平局 const squaresFilled = squares.every(value => value !== null); if(squaresFilled) { return "Draw"; } // 游戏未结束 return null; }
2. 调整状态显示逻辑
在Board组件的render方法中,区分胜者和平局的显示文本:
render() { const result = calculateWinner(this.state.squares); let status; if(result === "Draw") { status = 'Game Over: Draw'; } else if(result) { status = 'Winner: ' + result; } else { status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); } // 其余render代码不变 }
修复后效果
- 棋盘填满且存在胜者时,稳定显示胜者信息
- 棋盘填满且无胜者时,显示平局信息
- 游戏未结束时,正常显示下一位玩家
内容的提问来源于stack exchange,提问作者Zia
相关产品推荐
相关产品推荐

