You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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原因分析

  1. 逻辑顺序错误:在calculateWinner的循环中,每检查一条获胜线就同时判断平局,逻辑顺序混乱。正确流程应该是先确认是否有胜者,再判断是否平局。
  2. 条件判断矛盾:平局的判断条件squaresFilled && threeSquaresEqual永远不可能成立——threeSquaresEqual为真时,已经在第一个if分支返回胜者,不会走到平局分支。
  3. 冗余参数:函数声明了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 19:18:36