为何chess.js的isGameOver()方法会延迟一步判断游戏结束?
解决Chess.js中isGameOver()延迟判断游戏结束的问题
这个问题我之前开发国际象棋项目时也碰到过!核心原因是React的状态更新是异步的——你在onDrop里调用makeAMove更新game状态后,立刻用game.isGameOver()判断时,拿到的还是更新前的旧状态,不是刚走完那步棋后的新状态,所以才会出现“延迟一步”的情况。
修复方案
直接用你刚走完棋的gameCopy来判断游戏状态,而不是依赖还没更新的React状态。我调整了你的代码逻辑,把判断逻辑移到走棋完成后的gameCopy上:
import { Chessboard } from "react-chessboard"; import { useState } from "react"; import { Chess } from "chess.js"; const Board = () =>{ const [game, setGame] = useState(new Chess()); function onDrop(sourceSquare, targetSquare) { // 直接在onDrop里处理走棋逻辑,避免额外函数的状态异步问题 const gameCopy = new Chess(); gameCopy.loadPgn(game.pgn()); const moveResult = gameCopy.move({ from: sourceSquare, to: targetSquare, }); // 只有走棋有效时才更新状态并判断游戏结束 if (moveResult) { setGame(gameCopy); // 用最新的gameCopy判断游戏状态,而不是旧的game if(gameCopy.isGameOver()){ if(gameCopy.isStalemate() || gameCopy.isThreefoldRepetition()){ alert("Stalemate") } // 注意:turn()返回的是下一个要走的玩家,所以游戏结束时轮到黑方,说明白方刚走完将死了黑方 if(gameCopy.turn() === "b"){ alert("White won") } else if(gameCopy.turn() === "w"){ alert("Black won") } } } } return ( <> <div style = {{width: '50%',alignItems: 'center', marginLeft: '25%',justifyContent: 'center'}}> <Chessboard position={game.fen()} onPieceDrop={onDrop} id="BasicBoard"/> </div> </> ); } export default Board;
关键修改点说明:
- 把
makeAMove的逻辑合并到onDrop里,减少状态异步带来的混淆,同时可以直接拿到走棋后的gameCopy - 增加了
moveResult的判断,避免无效走棋(比如非法移动)触发状态更新和判断 - 所有游戏状态判断都基于最新的
gameCopy,而不是还没完成更新的game状态,这样就能实时检测到游戏结束的情况
这样修改后,当白方走完将死黑方的那一步,立刻就会弹出“White won”的提示,不会再等黑方走下一步啦。
内容的提问来源于stack exchange,提问作者Cam
相关产品推荐
相关产品推荐

