首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 中國象棋引擎開發筆記:從規則驗證到 AI 機器對戰架構設計

     編輯:關於C#

開發中國象棋程式分為兩大階段:**規則引擎** (合法走法生成、局面判斷) 與 **AI 引擎** (評估函數、搜尋演算法)。本文整理從棋子類別設計、介面定義、走法生成到引入 Minimax + Alpha-Beta 剪枝 AI 的架構演進筆記,供想實作象棋 AI 的開發者參考。

第一階段:規則引擎核心架構

1. 棋子介面與基類


public interface IChessPiece
{
    bool IsRed { get; }
    bool IsAlive { get; }
    int X { get; set; } // 1-9 (檔)
    int Y { get; set; } // 1-10 (列)
    string Name { get; }
    IReadOnlyList GetLegalMoves(Board board); // 依當前盤面生成合法走法
    void MoveTo(int x, int y); // 執行移動 (含吃子邏輯由 Board 處理)
}

public abstract class ChessPieceBase : IChessPiece
{
    public const int BoardWidth = 9;
    public const int BoardHeight = 10;

    public bool IsRed { get; protected set; }
    public bool IsAlive { get; protected set; } = true;
    public int X { get; set; }
    public int Y { get; set; }
    public abstract string Name { get; }

    protected bool IsInsideBoard(int x, int y) => x >= 1 && x <= BoardWidth && y >= 1 && y <= BoardHeight;

    public abstract IReadOnlyList GetLegalMoves(Board board);

    public void MoveTo(int x, int y)
    {
        X = x; Y = y;
    }

    public void Capture() => IsAlive = false;
}

2. 具體棋子走法生成 (以馬為例)


public class Horse : ChessPieceBase
{
    public override string Name => IsRed ? "傌" : "馬";

    // 馬腳座標偏移 (dx, dy, 腳 dx, 腳 dy)
    private static readonly (int dx, int dy, int legX, int legY)[] _moves = {
        (2, 1, 1, 0), (1, 2, 0, 1), (-1, 2, 0, 1), (-2, 1, -1, 0),
        (-2, -1, -1, 0), (-1, -2, 0, -1), (1, -2, 0, -1), (2, -1, 1, 0)
    };

    public override IReadOnlyList GetLegalMoves(Board board)
    {
        var moves = new List();
        foreach (var (dx, dy, legX, legY) in _moves)
        {
            int nx = X + dx, ny = Y + dy;
            int lx = X + legX, ly = Y + legY;
            if (!IsInsideBoard(nx, ny)) continue;
            if (board.HasPiece(lx, ly)) continue; // 搶馬腳
            var target = board.GetPiece(nx, ny);
            if (target == null || target.IsRed != IsRed) // 空位或敵子
                moves.Add(new Position(nx, ny));
        }
        return moves;
    }
}

3. 棋盤與局面管理


public class Board
{
    private readonly IChessPiece[,] _grid = new IChessPiece[10, 9]; // [y, x] 1-based
    public IReadOnlyList AllPieces { get; private set; }

    public IChessPiece GetPiece(int x, int y) => IsInside(x, y) ? _grid[y, x] : null;
    public bool HasPiece(int x, int y) => GetPiece(x, y) != null;

    public void MakeMove(Move move)
    {
        // 執行移動、處理吃子、更新棋盤狀態、切換回合
    }

    public void UndoMove(Move move) { /* 回溯用 */ }

    public bool IsInCheck(bool isRed) { /* 判斷將軍 */ }
    public bool IsCheckmate(bool isRed) { /* 判斷將死 */ }
}

第二階段:AI 引擎架構 (Minimax + Alpha-Beta)

1. 評估函數


public interface IEvaluator
{
    int Evaluate(Board board, bool isRedTurn); // 正分 = 紅方優勢
}

public class SimpleEvaluator : IEvaluator
{
    private static readonly Dictionary _pieceValues = new()
    {
        { typeof(King), 10000 }, { typeof(Advisor), 200 }, { typeof(Elephant), 200 },
        { typeof(Horse), 400 }, { typeof(Rook), 900 }, { typeof(Cannon), 450 }, { typeof(Pawn), 100 }
    };

    public int Evaluate(Board board, bool isRedTurn)
    {
        int score = 0;
        foreach (var p in board.AllPieces)
        {
            if (!p.IsAlive) continue;
            int val = _pieceValues[p.GetType()];
            score += p.IsRed ? val : -val;
        }
        // 可加入位置權重表 (棋子在特定座標的加分)
        return isRedTurn ? score : -score;
    }
}

2. 搜尋演算法核心


public class ChessEngine
{
    private readonly IEvaluator _evaluator;
    private readonly int _maxDepth;
    private int _nodesSearched;

    public ChessEngine(IEvaluator evaluator, int maxDepth = 4)
    {
        _evaluator = evaluator;
        _maxDepth = maxDepth;
    }

    public Move GetBestMove(Board board, bool isRedTurn)
    {
        _nodesSearched = 0;
        var bestMove = AlphaBeta(board, _maxDepth, int.MinValue, int.MaxValue, isRedTurn, out _);
        return bestMove;
    }

    private Move AlphaBeta(Board board, int depth, int alpha, int beta, bool isRedTurn, out int score)
    {
        _nodesSearched++;
        if (depth == 0 || board.IsCheckmate(isRedTurn) || board.IsCheckmate(!isRedTurn))
        {
            score = _evaluator.Evaluate(board, isRedTurn);
            return null;
        }

        Move bestMove = null;
        var moves = GenerateAllMoves(board, isRedTurn);
        // 走法排序:吃子優先、歷史啟發、殺手走法 → 大幅提升剪枝效率
        moves = OrderMoves(moves, board);

        foreach (var move in moves)
        {
            board.MakeMove(move);
            AlphaBeta(board, depth - 1, -beta, -alpha, !isRedTurn, out int childScore);
            board.UndoMove(move);
            childScore = -childScore; // 雙方視角轉換

            if (childScore > alpha)
            {
                alpha = childScore;
                bestMove = move;
                if (alpha >= beta) break; // Beta cutoff
            }
        }
        score = alpha;
        return bestMove;
    }
}

關鍵優化方向

  1. 走法排序:MVV-LVA (Most Valuable Victim - Least Valuable Attacker)、歷史啟發表、殺手走法、置換表 (Zobrist Hashing)。
  2. 疊代加深:逐層加深搜尋,配合時間控制,取最佳完整深度結果。
  3. 置換表:儲存局面雜湊值、評分、最佳走法、深度、旗標 (Exact/Lower/Upper Bound),避免重複搜尋。
  4. 位棋盤:用 64-bit 整數位運算表示棋盤,極大加速走法生成與攻擊檢測 (如 Stockfish 架構)。
  5. 端局資料庫:Syzygy / Nalimov Tablebase 完美玩法。

開源參考專案

  • Fairy-Stockfish:支援中國象棋變體的 Stockfish 分支。
  • Cyclone:C++ 開源中國象棋引擎,演算法極具參考價值。
  • ChineseChess.NET:C# 純管理碼實作,適合學習架構。

結語

規則引擎是基石,AI 是靈魂。建議先完成**完整、無 Bug 的走法生成與局面判斷** (含將軍、將死、和棋規則),再引入 Minimax 搜尋框架,逐步加入評估函數權重調優、走法排序、置換表。C# 雖不如 C++ 極致效能,但配合 Span<T>、ref struct、BitOperations 等現代特性,足以打造業餘高手級引擎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved