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

React将棋类游戏交替玩家回合功能实现故障求助

问题分析与解决

核心问题

你代码里的steps是clickPiece函数内的局部变量,每次触发点击事件时,这个变量都会被重新初始化为1。所以每次点击都会进入steps % 2 === 1的分支,把activePlayer设为Player.US,完全起不到交替切换的作用。

解决方案

方案1:用useState保存steps状态

把steps变成组件的状态变量,这样它的值会在组件渲染周期中被保留,每次点击后更新:

// 先在组件内定义steps的状态
const [steps, setSteps] = useState<number>(1);

const clickPiece = (e: React.MouseEvent) => {
    const element = e.target as HTMLElement;
    const shogiBoard = shogiBoardRef.current;

    // 根据当前steps的奇偶性切换玩家
    if (steps % 2 === 1) {
      setActivePlayer(Player.US);
    } else {
      setActivePlayer(Player.ENEMY);
    }
    // 更新steps计数
    setSteps(prev => prev + 1);

    if (element.classList.contains("shogiPiece") && shogiBoard && activePlayer) {
      const takeX = Math.floor((e.clientX - shogiBoard.offsetLeft) / CELL_SIZE);
      const takeY = Math.abs(Math.ceil((e.clientY - shogiBoard.offsetTop - BOARD_SIZE) / CELL_SIZE));
      setTakePosition({
        x: takeX,
        y: takeY,
      });

      const x = e.clientX - CELL_SIZE / 2;
      const y = e.clientY - CELL_SIZE / 2;
      element.style.position = "absolute";
      element.style.left = `${x}px`;
      element.style.top = `${y}px`;

      setActivePiece(element);
    }
};

方案2:直接根据当前activePlayer切换(更简洁)

不需要额外的steps变量,直接判断当前活跃玩家,切换成另一方:

const clickPiece = (e: React.MouseEvent) => {
    const element = e.target as HTMLElement;
    const shogiBoard = shogiBoardRef.current;

    // 直接切换玩家
    setActivePlayer(prev => prev === Player.US ? Player.ENEMY : Player.US);

    if (element.classList.contains("shogiPiece") && shogiBoard && activePlayer) {
      const takeX = Math.floor((e.clientX - shogiBoard.offsetLeft) / CELL_SIZE);
      const takeY = Math.abs(Math.ceil((e.clientY - shogiBoard.offsetTop - BOARD_SIZE) / CELL_SIZE));
      setTakePosition({
        x: takeX,
        y: takeY,
      });

      const x = e.clientX - CELL_SIZE / 2;
      const y = e.clientY - CELL_SIZE / 2;
      element.style.position = "absolute";
      element.style.left = `${x}px`;
      element.style.top = `${y}px`;

      setActivePiece(element);
    }
};

额外建议

实际游戏中,应该只允许当前活跃玩家操作己方棋子,所以建议在点击棋子时先判断该棋子是否属于当前activePlayer,再执行后续逻辑和切换回合,避免误操作。比如给己方棋子加专属类名(如us-piece),点击时先检查:

if (element.classList.contains("shogiPiece") && element.classList.contains("us-piece") && shogiBoard && activePlayer === Player.US) {
  // 己方棋子操作逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:27:21