#include #include #include #include #include #include #include #include #include

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> 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(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; }

0 条评论

目前还没有评论...

信息

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