发布于 2026-01-06 5 阅读
0

使用 React 和 Chessboardjsx 创建一个国际象棋游戏 ♟️

使用 React 和 Chessboardjsx 创建一个国际象棋游戏 ♟️

引言

本文将介绍如何使用 React 创建一个国际象棋游戏。本文基于我最近阅读的 Varun Pujari 的一篇文章。如果您想了解更多信息,可以点击以下链接查看原文。

我们将使用名为chessboardjsx的软件包,它能让我们轻松地展示国际象棋棋局。此外,我们还将使用chess.js库来实现棋步以及游戏的玩法。

这个国际象棋游戏将由一名玩家对阵人工智能,人工智能每回合都会随机走一步。最后,我们会给游戏添加一个计时器,以便测试我们击败人工智能的速度!

设置

安装过程非常简单。首先,我们需要在终端/命令提示符中运行几个命令来完成所有安装工作。

  1. 运行yarn create react-app chess-game --template typescript。你也可以运行,npx create-react-app chess-game --template typescript但对我来说 yarn 的效果更好。我之前一直收到一个错误提示,说我的 create-react-app 版本过旧。每次卸载并尝试运行 npx 命令时,都会出现同样的版本过旧错误。所以我最终选择了 yarn。
  2. 接下来我们将chessboard.jsx使用以下yarn add chessboardjsx命令进行安装。
  3. 现在让我们安装游戏的核心组件。运行yarn add chess.js此软件包。我们将使用此软件包来实现人工智能逻辑。
  4. 由于我们也在使用 TypeScript,所以我们需要添加类型chess.js。我们可以通过运行以下命令来完成此操作yarn add @types/chess.js
  5. 最后,我想给这个游戏加个计时器,这样我们就能看到游戏花了多长时间。我们来运行以下命令来设置它yarn add react-compound-timer

代码

现在到了最有趣的部分——游戏背后的实际代码。下面是本项目中唯一需要编辑的文件的代码App.tsx。我已经尽量对主要部分添加了注释,以便您更容易理解其运行机制。

import React, { useState } from "react";
import "./App.css";
import Timer from "react-compound-timer";
// Lines 5-8: Bring in chessboard and chess.js stuff
import Chessboard from "chessboardjsx";
import { ChessInstance, ShortMove } from "chess.js";

const Chess = require("chess.js");

const paddingStyle = {
  padding: 5
}

const marginStyle = {
  margin: 5
}

const App: React.FC = () => {
  const [chess] = useState<ChessInstance>(
    // Set initial state to FEN layout
    new Chess("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
  );

  const [fen, setFen] = useState(chess.fen());

  // Logic for the setting up the random computer move.
  const handleMove = (move: ShortMove) => {
    // Line 29 validates the user move.
    if (chess.move(move)) {
      setTimeout(() => {
        const moves = chess.moves();
        // Lines 33-28: Computer random move.
        if (moves.length > 0) {
          const computerMove = moves[Math.floor(Math.random() * moves.length)];
          chess.move(computerMove);
          setFen(chess.fen());
        }
      }, 300);
      // Sets state of chess board
      setFen(chess.fen());
    }
  };

  return (
    <div className="flex-center">
      <h1>Random Chess Game</h1>
      <Chessboard
        width={400}
        position={fen}
        // onDrop prop tracks everytime a piece is moved.
        // The rest is handled in the the handleMove function.
        onDrop={(move) =>
          handleMove({
            from: move.sourceSquare,
            to: move.targetSquare,
            // This promotion attribute changes pawns to a queen if they reach the other side of the board.
            promotion: "q",
          })
        }
      />
      {/* Timer code */}
      <Timer initialTime={0} startImmediately={false}>
        {/* I thought this was weird. Definitely a better way to do this, but I just wanted it to work. */}
        {({ start, resume, pause, stop, reset, timerState } : {start:any, resume:any, pause:any, stop:any, reset:any, timerState:any}) => (
            <>
                <div>
                    <span style={paddingStyle}><Timer.Minutes /> minutes</span>
                    <span style={paddingStyle}><Timer.Seconds /> seconds</span>
                    <span style={paddingStyle}><Timer.Milliseconds /> milliseconds</span>
                </div>
                <div style={paddingStyle}>{timerState}</div>
                <br />
                <div>
                    <button style={marginStyle} onClick={start}>Start</button>
                    <button style={marginStyle} onClick={pause}>Pause</button>
                    <button style={marginStyle} onClick={resume}>Resume</button>
                    <button style={marginStyle} onClick={stop}>Stop</button>
                    <button style={marginStyle} onClick={reset}>Reset</button>
                </div>
            </>
        )}
      </Timer>
    </div>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

App.tsx文件更新成这样后,你应该就能运行你的项目,yarn start并与你创建的AI下棋了。别忘了启动计时器,看看你能多快获胜!

FEN(福赛斯-爱德华兹符号)

我觉得这个项目最有趣的地方在于福赛斯-爱德华兹记谱法(Forsyth-Edwards Notation,简称FEN)。它是一种描述国际象棋棋局的记谱法。你会注意到它在App.tsx代码的第21行被使用。它之所以让我印象深刻,是因为我第一次看到它时,还以为是一堆乱码。你能猜出福赛斯-爱德华兹记谱法初始状态的字母是什么意思吗?我相信你很快就能明白,但如果你需要提示,它与棋盘上棋子的名称有关。

结论

好了,差不多就是这样。很简单,也很简短。希望你喜欢制作这款国际象棋游戏,也希望你玩得开心。如果你想挑战一下自己,可以尝试把它部署到网上,看看你的朋友和家人能多快打败AI。我推荐你使用Netlify,那是我常用的托管服务。

一如既往,祝大家编程愉快!爱你们。再见。

文章来源:https://dev.to/tyry327/create-a-chess-game-with-react-and-chessboardjsx-214e