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

React井字棋:点击获胜棋子后如何同步设置获胜状态?

井字棋获胜状态即时更新解决方案

问题根源

  1. 闭包导致状态陈旧:newStatuses声明在组件顶层,每次组件渲染都会重新生成,但handleClick引用的是旧变量实例,状态更新不同步。
  2. 用旧状态判断获胜:调用handleWinning(status)时,status还是点击前的旧状态,刚下的棋子状态没被纳入判断。
  3. 获胜状态未触发重渲染:修改newStatuses后没有再次调用setStatus,界面无法感知获胜状态变化。

修改后的代码

function Board() {
    const [nextMoveX, setNextMoveX] = useState(true);
    const [status, setStatus] = useState(Array(9).fill(empty))

    function handleClick(i) {
        // 每次点击基于当前状态创建新数组,避免闭包问题
        const newStatuses = status.slice();
        // 设置当前点击棋子的状态
        const currentMove = nextMoveX ? clickedX : clickedZero;
        newStatuses[i] = currentMove;

        // 检查获胜线并修改状态
        const winningLines = [
            [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 (const line of winningLines) {
            const [a, b, c] = line;
            if (newStatuses[a] === currentMove && newStatuses[b] === currentMove && newStatuses[c] === currentMove) {
                const winStatus = nextMoveX ? xWin : zeroWin;
                newStatuses[a] = winStatus;
                newStatuses[b] = winStatus;
                newStatuses[c] = winStatus;
                break; // 找到获胜线后停止检查
            }
        }

        // 统一更新状态,一次完成棋子+获胜状态同步
        setStatus(newStatuses);
        setNextMoveX(!nextMoveX);
    }

    return (
        <div className={styles.mainContainer}>
            <Button classTitle={status[0]} onClick={() => handleClick(0)}/>
            {/* 省略中间6个Button组件 */}
            <Button classTitle={status[8]} onClick={() => handleClick(8)}/>
        </div>
    );
};

关键优化点

  • 将newStatuses移至handleClick内部,确保每次操作的都是当前最新状态的副本。
  • 用刚修改后的新状态数组判断获胜,避免旧状态导致的判断失效。
  • 找到获胜线后直接修改新状态数组,通过一次setStatus完成所有状态更新,确保界面即时渲染获胜样式。

内容的提问来源于stack exchange,提问作者tomvas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:25:19