#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <limits>
#include <cmath>
#include <random>
#include <chrono>
#include <thread>

using namespace std;

// 棋子类型枚举
enum PieceType {
    EMPTY = 0,
    GENERAL,  // 将/帅
    ADVISOR,  // 士/仕
    ELEPHANT, // 象/相
    HORSE,    // 马/傌
    CHARIOT,  // 车/俥
    CANNON,   // 炮/砲
    SOLDIER   // 兵/卒
};

// 棋子颜色枚举
enum PieceColor {
    NONE = 0,
    RED,
    BLACK
};

// 颜色代码定义
namespace Color {
    const string RED = "\033[31m";      // 红色
    const string WHITE = "\033[37m";    // 白色
    const string RESET = "\033[0m";     // 重置颜色
}

// 棋子类
class Piece {
public:
    PieceType type;
    PieceColor color;
    int x, y;
    bool selected;
    
    Piece(PieceType t = EMPTY, PieceColor c = NONE, int posX = 0, int posY = 0) {
        type = t;
        color = c;
        x = posX;
        y = posY;
        selected = false;
    }
    
    // 获取棋子显示名称(带颜色)
    string getName() const {
        if (type == EMPTY) return "  ";
        
        string name;
        switch(type) {
            case GENERAL: name = (color == RED) ? "帅" : "将"; break;
            case ADVISOR: name = (color == RED) ? "仕" : "士"; break;
            case ELEPHANT: name = (color == RED) ? "相" : "象"; break;
            case HORSE: name = (color == RED) ? "傌" : "马"; break;
            case CHARIOT: name = (color == RED) ? "俥" : "车"; break;
            case CANNON: name = (color == RED) ? "砲" : "炮"; break;
            case SOLDIER: name = (color == RED) ? "兵" : "卒"; break;
            default: name = "  ";
        }
        
        // 根据棋子颜色添加颜色代码
        if (color == RED) {
            return Color::RED + name + Color::RESET;
        } else if (color == BLACK) {
            return Color::WHITE + name + Color::RESET;
        }
        
        return name;
    }
    
    // 复制构造函数
    Piece(const Piece& other) {
        type = other.type;
        color = other.color;
        x = other.x;
        y = other.y;
        selected = other.selected;
    }
};

// 移动结构
struct Move {
    int fromX, fromY, toX, toY;
    int score;
    
    Move(int fx, int fy, int tx, int ty) : fromX(fx), fromY(fy), toX(tx), toY(ty), score(0) {}
};

// 棋盘类
class ChessBoard {
private:
    vector<vector<Piece>> board;
    PieceColor currentPlayer;
    bool gameOver;
    string winner;
    bool aiEnabled;  // 是否启用AI
    
    // 棋子基础价值
    const int PIECE_VALUES[8] = {0, 10000, 200, 200, 400, 900, 450, 100};
    
    // 棋子位置价值表(黑方视角)
    const int SOLDIER_POSITION_VALUE[10][9] = {
        {0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0, 0},
        {10, 0, 15, 0, 20, 0, 15, 0, 10},
        {10, 0, 15, 0, 20, 0, 15, 0, 10},
        {20, 0, 25, 0, 30, 0, 25, 0, 20},
        {30, 0, 35, 0, 40, 0, 35, 0, 30},
        {40, 0, 45, 0, 50, 0, 45, 0, 40},
        {50, 0, 55, 0, 60, 0, 55, 0, 50},
        {0, 0, 0, 0, 0, 0, 0, 0, 0}
    };
    
public:
    ChessBoard() {
        // 初始化9x10的棋盘
        board.resize(9, vector<Piece>(10));
        initializeBoard();
        currentPlayer = RED;
        gameOver = false;
        winner = "";
        aiEnabled = false;  // 默认不启用AI
    }
    
    // 复制构造函数
    ChessBoard(const ChessBoard& other) {
        board = other.board;
        currentPlayer = other.currentPlayer;
        gameOver = other.gameOver;
        winner = other.winner;
        aiEnabled = other.aiEnabled;
    }
    
    // 启用或禁用AI
    void setAIEnabled(bool enabled) {
        aiEnabled = enabled;
    }
    
    // 初始化棋盘
    void initializeBoard() {
        // 清空棋盘
        for (int x = 0; x < 9; x++) {
            for (int y = 0; y < 10; y++) {
                board[x][y] = Piece(EMPTY, NONE, x, y);
            }
        }
        
        // 布置红方棋子
        board[0][9] = Piece(CHARIOT, RED, 0, 9);
        board[1][9] = Piece(HORSE, RED, 1, 9);
        board[2][9] = Piece(ELEPHANT, RED, 2, 9);
        board[3][9] = Piece(ADVISOR, RED, 3, 9);
        board[4][9] = Piece(GENERAL, RED, 4, 9);
        board[5][9] = Piece(ADVISOR, RED, 5, 9);
        board[6][9] = Piece(ELEPHANT, RED, 6, 9);
        board[7][9] = Piece(HORSE, RED, 7, 9);
        board[8][9] = Piece(CHARIOT, RED, 8, 9);
        board[1][7] = Piece(CANNON, RED, 1, 7);
        board[7][7] = Piece(CANNON, RED, 7, 7);
        board[0][6] = Piece(SOLDIER, RED, 0, 6);
        board[2][6] = Piece(SOLDIER, RED, 2, 6);
        board[4][6] = Piece(SOLDIER, RED, 4, 6);
        board[6][6] = Piece(SOLDIER, RED, 6, 6);
        board[8][6] = Piece(SOLDIER, RED, 8, 6);
        
        // 布置黑方棋子
        board[0][0] = Piece(CHARIOT, BLACK, 0, 0);
        board[1][0] = Piece(HORSE, BLACK, 1, 0);
        board[2][0] = Piece(ELEPHANT, BLACK, 2, 0);
        board[3][0] = Piece(ADVISOR, BLACK, 3, 0);
        board[4][0] = Piece(GENERAL, BLACK, 4, 0);
        board[5][0] = Piece(ADVISOR, BLACK, 5, 0);
        board[6][0] = Piece(ELEPHANT, BLACK, 6, 0);
        board[7][0] = Piece(HORSE, BLACK, 7, 0);
        board[8][0] = Piece(CHARIOT, BLACK, 8, 0);
        board[1][2] = Piece(CANNON, BLACK, 1, 2);
        board[7][2] = Piece(CANNON, BLACK, 7, 2);
        board[0][3] = Piece(SOLDIER, BLACK, 0, 3);
        board[2][3] = Piece(SOLDIER, BLACK, 2, 3);
        board[4][3] = Piece(SOLDIER, BLACK, 4, 3);
        board[6][3] = Piece(SOLDIER, BLACK, 6, 3);
        board[8][3] = Piece(SOLDIER, BLACK, 8, 3);
    }
    
    // 显示棋盘
    void display() {
        cout << "\n   0  1  2  3  4  5  6  7  8 " << endl;
        cout << "  ┌--┬--┬--┬--┬--┬--┬--┬--┬--┐" << endl;
        for (int y = 0; y < 10; y++) {
            cout << y << " │";
            for (int x = 0; x < 9; x++) {
                cout << board[x][y].getName();
                if (x < 8) cout << "│";
            }
            cout << "│" << endl;
            
            if (y < 9) {
                if (y == 4) {
                    cout << "  ├--┼--┼--┼--┼--┼--┼--┼--┼--┤" << endl;
                } else {
                    cout << "  ├--┼--┼--┼--┼--┼--┼--┼--┼--┤" << endl;
                }
            }
        }
        cout << "  └--┴--┴--┴--┴--┴--┴--┴--┴--┘" << endl;
        cout << "\n当前回合: " << (currentPlayer == RED ? Color::RED + "红方" + Color::RESET : "黑方") << endl;
        if (aiEnabled && currentPlayer == BLACK) {
            cout << "黑方由AI控制" << endl;
        }
    }
    
    // 检查移动是否合法
    bool isValidMove(int fromX, int fromY, int toX, int toY) {
        // 检查坐标是否在棋盘内
        if (fromX < 0 || fromX >= 9 || fromY < 0 || fromY >= 10 ||
            toX < 0 || toX >= 9 || toY < 0 || toY >= 10) {
            return false;
        }
        
        Piece fromPiece = board[fromX][fromY];
        Piece toPiece = board[toX][toY];
        
        // 检查是否选择己方棋子
        if (fromPiece.color != currentPlayer) {
            return false;
        }
        
        // 检查是否吃己方棋子
        if (toPiece.color == currentPlayer) {
            return false;
        }
        
        // 根据棋子类型检查移动规则
        switch(fromPiece.type) {
            case GENERAL:
                return isValidGeneralMove(fromX, fromY, toX, toY);
            case ADVISOR:
                return isValidAdvisorMove(fromX, fromY, toX, toY);
            case ELEPHANT:
                return isValidElephantMove(fromX, fromY, toX, toY);
            case HORSE:
                return isValidHorseMove(fromX, fromY, toX, toY);
            case CHARIOT:
                return isValidChariotMove(fromX, fromY, toX, toY);
            case CANNON:
                return isValidCannonMove(fromX, fromY, toX, toY);
            case SOLDIER:
                return isValidSoldierMove(fromX, fromY, toX, toY);
            default:
                return false;
        }
    }
    
    // 将/帅移动规则
    bool isValidGeneralMove(int fromX, int fromY, int toX, int toY) {
        // 将/帅只能在九宫格内移动
        if (currentPlayer == RED) {
            if (toX < 3 || toX > 5 || toY < 7 || toY > 9) return false;
        } else {
            if (toX < 3 || toX > 5 || toY < 0 || toY > 2) return false;
        }
        
        // 只能移动一步
        if (abs(fromX - toX) + abs(fromY - toY) != 1) return false;
        
        return true;
    }
    
    // 士/仕移动规则
    bool isValidAdvisorMove(int fromX, int fromY, int toX, int toY) {
        // 士/仕只能在九宫格内斜线移动
        if (currentPlayer == RED) {
            if (toX < 3 || toX > 5 || toY < 7 || toY > 9) return false;
        } else {
            if (toX < 3 || toX > 5 || toY < 0 || toY > 2) return false;
        }
        
        // 只能斜线移动一步
        if (abs(fromX - toX) != 1 || abs(fromY - toY) != 1) return false;
        
        return true;
    }
    
    // 象/相移动规则
    bool isValidElephantMove(int fromX, int fromY, int toX, int toY) {
        // 象不能过河
        if (currentPlayer == RED && toY < 5) return false;
        if (currentPlayer == BLACK && toY > 4) return false;
        
        // 象走田字
        if (abs(fromX - toX) != 2 || abs(fromY - toY) != 2) return false;
        
        // 检查象眼是否被塞
        int eyeX = (fromX + toX) / 2;
        int eyeY = (fromY + toY) / 2;
        if (board[eyeX][eyeY].type != EMPTY) return false;
        
        return true;
    }
    
    // 马/傌移动规则
    bool isValidHorseMove(int fromX, int fromY, int toX, int toY) {
        // 马走日字
        int dx = abs(fromX - toX);
        int dy = abs(fromY - toY);
        if (!((dx == 1 && dy == 2) || (dx == 2 && dy == 1))) return false;
        
        // 检查马腿是否被绊
        if (dx == 2) {
            int legX = (fromX + toX) / 2;
            if (board[legX][fromY].type != EMPTY) return false;
        } else {
            int legY = (fromY + toY) / 2;
            if (board[fromX][legY].type != EMPTY) return false;
        }
        
        return true;
    }
    
    // 车/俥移动规则
    bool isValidChariotMove(int fromX, int fromY, int toX, int toY) {
        // 车只能直线移动
        if (fromX != toX && fromY != toY) return false;
        
        // 检查路径上是否有其他棋子
        if (fromX == toX) {
            int startY = min(fromY, toY);
            int endY = max(fromY, toY);
            for (int y = startY + 1; y < endY; y++) {
                if (board[fromX][y].type != EMPTY) return false;
            }
        } else {
            int startX = min(fromX, toX);
            int endX = max(fromX, toX);
            for (int x = startX + 1; x < endX; x++) {
                if (board[x][fromY].type != EMPTY) return false;
            }
        }
        
        return true;
    }
    
    // 炮/砲移动规则
    bool isValidCannonMove(int fromX, int fromY, int toX, int toY) {
        // 炮只能直线移动
        if (fromX != toX && fromY != toY) return false;
        
        int pieceCount = 0;
        
        // 计算路径上的棋子数量
        if (fromX == toX) {
            int startY = min(fromY, toY);
            int endY = max(fromY, toY);
            for (int y = startY + 1; y < endY; y++) {
                if (board[fromX][y].type != EMPTY) pieceCount++;
            }
        } else {
            int startX = min(fromX, toX);
            int endX = max(fromX, toX);
            for (int x = startX + 1; x < endX; x++) {
                if (board[x][fromY].type != EMPTY) pieceCount++;
            }
        }
        
        // 如果目标位置有棋子,必须隔一个棋子吃子
        if (board[toX][toY].type != EMPTY) {
            return pieceCount == 1;
        } else {
            // 如果目标位置没有棋子,路径上不能有棋子
            return pieceCount == 0;
        }
    }
    
    // 兵/卒移动规则
    bool isValidSoldierMove(int fromX, int fromY, int toX, int toY) {
        // 兵只能向前移动一步,过河后可以左右移动
        if (currentPlayer == RED) {
            // 红方兵向上移动
            if (fromY < toY) return false; // 不能后退
            
            if (fromY > 4) {
                // 未过河,只能向前
                if (fromX != toX || fromY - toY != 1) return false;
            } else {
                // 已过河,可以向前或左右
                if (!((fromX == toX && fromY - toY == 1) || 
                      (fromY == toY && abs(fromX - toX) == 1))) return false;
            }
        } else {
            // 黑方卒向下移动
            if (fromY > toY) return false; // 不能后退
            
            if (fromY < 5) {
                // 未过河,只能向前
                if (fromX != toX || toY - fromY != 1) return false;
            } else {
                // 已过河,可以向前或左右
                if (!((fromX == toX && toY - fromY == 1) || 
                      (fromY == toY && abs(fromX - toX) == 1))) return false;
            }
        }
        
        return true;
    }
    
    // 执行移动
    void makeMove(int fromX, int fromY, int toX, int toY) {
        // 检查是否吃将/帅
        if (board[toX][toY].type == GENERAL) {
            gameOver = true;
            winner = (currentPlayer == RED) ? "红方" : "黑方";
        }
        
        // 移动棋子
        board[toX][toY] = board[fromX][fromY];
        board[toX][toY].x = toX;
        board[toX][toY].y = toY;
        board[fromX][fromY] = Piece(EMPTY, NONE, fromX, fromY);
        
        // 切换玩家
        currentPlayer = (currentPlayer == RED) ? BLACK : RED;
    }
    
    // 执行移动(不切换玩家,用于AI搜索)
    void makeMoveForSearch(int fromX, int fromY, int toX, int toY) {
        // 移动棋子
        board[toX][toY] = board[fromX][fromY];
        board[toX][toY].x = toX;
        board[toX][toY].y = toY;
        board[fromX][fromY] = Piece(EMPTY, NONE, fromX, fromY);
    }
    
    // 撤销移动(用于AI搜索)
    void undoMove(int fromX, int fromY, int toX, int toY, Piece capturedPiece) {
        // 恢复原棋子
        board[fromX][fromY] = board[toX][toY];
        board[fromX][fromY].x = fromX;
        board[fromX][fromY].y = fromY;
        
        // 恢复被吃的棋子
        board[toX][toY] = capturedPiece;
    }
    
    // 获取当前玩家
    PieceColor getCurrentPlayer() const {
        return currentPlayer;
    }
    
    // 设置当前玩家
    void setCurrentPlayer(PieceColor player) {
        currentPlayer = player;
    }
    
    // 检查游戏是否结束
    bool isGameOver() const {
        return gameOver;
    }
    
    // 获取所有合法移动
    vector<Move> getAllLegalMoves(PieceColor player) {
        vector<Move> moves;
        
        // 保存当前玩家
        PieceColor originalPlayer = currentPlayer;
        currentPlayer = player;
        
        // 遍历棋盘上的所有棋子
        for (int x = 0; x < 9; x++) {
            for (int y = 0; y < 10; y++) {
                if (board[x][y].color == player) {
                    // 对于每个棋子,检查所有可能的移动
                    for (int tx = 0; tx < 9; tx++) {
                        for (int ty = 0; ty < 10; ty++) {
                            if (isValidMove(x, y, tx, ty)) {
                                moves.push_back(Move(x, y, tx, ty));
                            }
                        }
                    }
                }
            }
        }
        
        // 恢复原玩家
        currentPlayer = originalPlayer;
        
        return moves;
    }
    
    // 评估棋盘状态(从黑方视角)
    int evaluate() {
        int score = 0;
        
        // 遍历棋盘上的所有棋子
        for (int x = 0; x < 9; x++) {
            for (int y = 0; y < 10; y++) {
                Piece piece = board[x][y];
                if (piece.type != EMPTY) {
                    int pieceValue = PIECE_VALUES[piece.type];
                    
                    // 黑方棋子加正分,红方棋子加负分
                    if (piece.color == BLACK) {
                        score += pieceValue;
                        
                        // 为兵/卒添加位置价值
                        if (piece.type == SOLDIER) {
                            score += SOLDIER_POSITION_VALUE[y][x];
                        }
                    } else {
                        score -= pieceValue;
                        
                        // 为兵/卒添加位置价值(红方兵的位置价值需要转换视角)
                        if (piece.type == SOLDIER) {
                            score -= SOLDIER_POSITION_VALUE[9-y][8-x]; // 转换坐标
                        }
                    }
                }
            }
        }
        
        return score;
    }
    
    // Minimax算法与Alpha-Beta剪枝
    int minimax(int depth, int alpha, int beta, bool maximizingPlayer) {
        if (depth == 0 || isGameOver()) {
            return evaluate();
        }
        
        vector<Move> moves = getAllLegalMoves(maximizingPlayer ? BLACK : RED);
        
        if (maximizingPlayer) {
            int maxEval = numeric_limits<int>::min();
            
            for (Move move : moves) {
                // 保存被吃的棋子
                Piece capturedPiece = board[move.toX][move.toY];
                
                // 执行移动
                makeMoveForSearch(move.fromX, move.fromY, move.toX, move.toY);
                
                // 递归评估
                int eval = minimax(depth - 1, alpha, beta, false);
                
                // 撤销移动
                undoMove(move.fromX, move.fromY, move.toX, move.toY, capturedPiece);
                
                maxEval = max(maxEval, eval);
                alpha = max(alpha, eval);
                
                if (beta <= alpha) {
                    break; // Alpha-Beta剪枝
                }
            }
            
            return maxEval;
        } else {
            int minEval = numeric_limits<int>::max();
            
            for (Move move : moves) {
                // 保存被吃的棋子
                Piece capturedPiece = board[move.toX][move.toY];
                
                // 执行移动
                makeMoveForSearch(move.fromX, move.fromY, move.toX, move.toY);
                
                // 递归评估
                int eval = minimax(depth - 1, alpha, beta, true);
                
                // 撤销移动
                undoMove(move.fromX, move.fromY, move.toX, move.toY, capturedPiece);
                
                minEval = min(minEval, eval);
                beta = min(beta, eval);
                
                if (beta <= alpha) {
                    break; // Alpha-Beta剪枝
                }
            }
            
            return minEval;
        }
    }
    
    // AI选择最佳移动
    Move findBestMove() {
        vector<Move> moves = getAllLegalMoves(BLACK);
        
        if (moves.empty()) {
            // 如果没有合法移动,返回一个无效移动
            return Move(-1, -1, -1, -1);
        }
        
        int bestValue = numeric_limits<int>::min();
        Move bestMove = moves[0];
        
        // 设置搜索深度(可以根据需要调整)
        int depth = 4;
        
        for (Move move : moves) {
            // 保存被吃的棋子
            Piece capturedPiece = board[move.toX][move.toY];
            
            // 执行移动
            makeMoveForSearch(move.fromX, move.fromY, move.toX, move.toY);
            
            // 评估移动
            int moveValue = minimax(depth - 1, numeric_limits<int>::min(), numeric_limits<int>::max(), false);
            
            // 撤销移动
            undoMove(move.fromX, move.fromY, move.toX, move.toY, capturedPiece);
            
            // 更新最佳移动
            if (moveValue > bestValue) {
                bestValue = moveValue;
                bestMove = move;
            }
        }
        
        return bestMove;
    }
    
    // AI进行移动
    void makeAIMove() {
        if (currentPlayer == BLACK && !gameOver) {
            cout << "AI正在思考..." << endl;
            
            // 添加延迟,使AI思考看起来更自然
            auto start = chrono::steady_clock::now();
            
            Move bestMove = findBestMove();
            
            auto end = chrono::steady_clock::now();
            auto duration = chrono::duration_cast<chrono::milliseconds>(end - start);
            
            // 确保AI思考至少1秒,使其看起来更真实
            if (duration.count() < 1000) {
                this_thread::sleep_for(chrono::milliseconds(1000 - duration.count()));
            }
            
            if (bestMove.fromX != -1) {
                cout << "AI移动: " << bestMove.fromX << " " << bestMove.fromY << " " 
                     << bestMove.toX << " " << bestMove.toY << endl;
                makeMove(bestMove.fromX, bestMove.fromY, bestMove.toX, bestMove.toY);
            }
        }
    }
    
    // 处理玩家输入
    void handlePlayerInput() {
        int fromX, fromY, toX, toY;
        cout << "请输入移动(从列从行到列到行)方格内: ";
        cin >> fromX >> fromY >> toX >> toY;
        
        if (isValidMove(fromX, fromY, toX, toY)) {
            makeMove(fromX, fromY, toX, toY);
        } else {
            cout << "无效移动,请重新输入!" << endl;
        }
    }
    
    // 游戏主循环
    void playGame() {
        cout << "欢迎来到中国象棋游戏!" << endl;
        cout << "红方先行(红是下方,黑是上方),使用坐标选择棋子并移动(例如:3 7 3 6)" << endl;
        
        // 选择游戏模式
        int mode;
        cout << "请选择游戏模式:" << endl;
        cout << "1. 单人模式 (玩家执红 vs AI执黑)" << endl;
        cout << "2. 双人模式 (两个玩家轮流)" << endl;
        cout << "请输入选择 (1 或 2): ";
        cin >> mode;
        
        if (mode == 1) {
            aiEnabled = true;
            cout << "已选择单人模式,黑方由AI控制" << endl;
        } else {
            aiEnabled = false;
            cout << "已选择双人模式" << endl;
        }
        
        while (!gameOver) {
            display();
            
            if (currentPlayer == RED) {
                // 红方总是玩家
                handlePlayerInput();
            } else {
                // 黑方:如果是单人模式且启用了AI,则使用AI;否则由玩家控制
                if (aiEnabled) {
                    makeAIMove();
                } else {
                    cout << "黑方回合:" << endl;
                    handlePlayerInput();
                }
            }
        }
        
        cout << "游戏结束!" << winner << "获胜!" << endl;
    }
};

int main() {
    ChessBoard game;
    game.playGame();
    return 0;
}

1 条评论

  • 1

信息

ID
940
时间
1000ms
内存
256MiB
难度
8
标签
递交数
135
已通过
25
上传者