我正在尝试为 React 创建一个国际象棋引擎评估栏。为此,我将 stockfish.js 添加到我的项目中,并使用 Web Worker api 在 useEffect 中初始化引擎,每次 fen 更改时都会重新渲染。 问题是,如果我在 fen 达到最大深度之前更改它,引擎会不断在新旧位置之间来回切换,并最终给出旧 fen 位置的评估。这完全破坏了引擎的功能,因为它应该始终分析给予它的最后一个位置。我尝试使用 stop() 方法,但它不起作用。 如何让引擎忘记旧的 fen,而在每次 fen 更新时只关注新位置? 这是代码:
engine.js:
class Engine {
constructor() {
this.stockfish = new Worker("/stockfish.js");
this.onMessage = callback => {
this.stockfish.addEventListener("message", e => {
const data = e.data;
console.log(data);
const depthMatch = data?.match(/info depth (\d+)/);
const depth = depthMatch ? parseInt(depthMatch[1]) : null;
const cpMatch = data?.match(/score cp (-?\d+)/);
const cp = cpMatch ? parseInt(cpMatch[1]) : null;
const bestMove = data?.match(/bestmove\s+(\S+)/)?.[1];
callback({ data, depth, cp, bestMove });
});
};
this.stockfish.postMessage("uci");
this.stockfish.postMessage("isready");
}
evaluatePosition(fen, depth) {
this.stockfish.postMessage(`position fen ${fen}`);
this.stockfish.postMessage(`go depth ${depth}`);
}
new() {
this.stockfish.postMessage("ucinewgame");
}
stop() {
this.stockfish.postMessage("stop");
}
quit() {
this.stockfish.postMessage("quit");
}
}
export default Engine;
EvalBar.js:
import { useEffect, useState } from "react";
import Engine from "@/utils/engine";
export default function EvalBar({ fen, on, turn }) {
const [depth, setDepth] = useState(0);
const [evalNum, setEvalNum] = useState(0);
const [barWidth, setBarWidth] = useState(164);
useEffect(() => {
const engine = new Engine();
engine.evaluatePosition(fen, 20);
engine.onMessage(({ depth, cp }) => {
if (depth) {
setDepth(depth);
}
if (cp) {
const num = cp / 100;
if (turn === "w") {
setEvalNum(num.toFixed(1));
setBarWidth(cp / 5 + 163);
} else if (turn === "b") {
setEvalNum((num * -1).toFixed(1));
setBarWidth((cp * -1) / 5 + 163);
}
}
});
}, [fen]);
return on ? (
<>
<p className="eval-depth">D{depth}</p>
<p className="eval-num">{evalNum}</p>
<div className="black-bar"></div>
<div className="white-bar" style={{ height: `${barWidth}px` }}></div>
<div className="half-marker"></div>
</>
) : null;
}
你应该在useEffect中添加return,当fen改变时它会关闭它
useEffect(() => {
const engine = new Engine();
engine.evaluatePosition(fen, 20);
engine.onMessage(({ depth, cp }) => {
if (depth) {
setDepth(depth);
}
if (cp) {
const num = cp / 100;
if (turn === "w") {
setEvalNum(num.toFixed(1));
setBarWidth(cp / 5 + 163);
} else if (turn === "b") {
setEvalNum((num * -1).toFixed(1));
setBarWidth((cp * -1) / 5 + 163);
}
}
});
**return engine.stop();**
}, [fen]);
它应该可以帮助您解决问题,但如果这无济于事,请将您的引擎更改为useState并将其存储在组件中