一旦给出新的分线,国际象棋引擎就会继续计算旧的分线位置

问题描述 投票:0回答:1

我正在尝试为 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;
}
reactjs web-worker uci stockfish
1个回答
0
投票

你应该在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并将其存储在组件中

© www.soinside.com 2019 - 2024. All rights reserved.