#include <iostream>
#include <vector>
#include <string>
#include <iomanip>  // 用于控制输出格式
#include <limits>   // 用于numeric_limits

using namespace std;

// 游戏常量定义
const int BOARD_SIZE = 15;  // 定义棋盘大小为15x15

// 棋子类型枚举
enum class Piece { 
    EMPTY,  // 空位置
    BLACK,  // 黑棋(先手)
    WHITE   // 白棋(后手)
};

// 游戏状态枚举
enum class GameState { 
    PLAYING,    // 游戏进行中
    BLACK_WIN,  // 黑方胜利
    WHITE_WIN,  // 白方胜利
    DRAW        // 平局
};

/*** 棋盘类 - 管理棋盘状态和游戏规则
 */
class Board {
private:
    vector<vector<Piece>> grid;  // 使用二维数组表示棋盘

public:
    // 构造函数 - 初始化空棋盘
    Board() : grid(BOARD_SIZE, vector<Piece>(BOARD_SIZE, Piece::EMPTY)) {}

    /*** 重置棋盘 - 将所有位置设为空
     */
    void reset() {
        // 遍历每一行
        for (auto& row : grid) {
            // 将每行的所有元素设为EMPTY
            fill(row.begin(), row.end(), Piece::EMPTY);
        }
    }

    /*** 在指定位置放置棋子
     * @param x 横坐标(0-14)
     * @param y 纵坐标(0-14)
     * @param piece 要放置的棋子类型
     * @return 放置是否成功
     */
    bool placePiece(int x, int y, Piece piece) {
        // 检查坐标是否有效且该位置为空
        if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE || grid[x][y] != Piece::EMPTY) {
            return false;  // 无效移动
        }
        grid[x][y] = piece;  // 放置棋子
        return true;
    }

    /*** 获取指定位置的棋子
     * @param x 横坐标
     * @param y 纵坐标
     * @return 该位置的棋子类型(无效坐标返回EMPTY)
     */
    Piece getPiece(int x, int y) const {
        // 检查坐标是否有效
        if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE) {
            return Piece::EMPTY;
        }
        return grid[x][y];
    }

    /*** 检查是否五子连珠
     * @param x 最后落子的横坐标
     * @param y 最后落子的纵坐标
     * @return 是否形成五子连珠
     */
    bool checkFiveInARow(int x, int y) const {
        Piece current = grid[x][y];
        if (current == Piece::EMPTY) return false;  // 空位置不可能五连

        // 四个检查方向: 水平、垂直、主对角线、副对角线
        int directions[4][2] = { {1,0},  // 水平方向
                                {0,1},   // 垂直方向
                                {1,1},   // 主对角线
                                {1,-1} }; // 副对角线
        
        // 检查每个方向
        for (auto& dir : directions) {
            int count = 1;  // 当前棋子已经算1个
            
            // 正向检查
            for (int i = 1; i < 5; i++) {
                int nx = x + dir[0] * i;
                int ny = y + dir[1] * i;
                if (getPiece(nx, ny) != current) break;  // 遇到不同颜色停止
                count++;
            }
            
            // 反向检查
            for (int i = 1; i < 5; i++) {
                int nx = x - dir[0] * i;
                int ny = y - dir[1] * i;
                if (getPiece(nx, ny) != current) break;
                count++;
            }
            
            // 如果同色棋子数达到5个或更多,返回true
            if (count >= 5) return true;
        }
        
        return false;  // 没有找到五连
    }

    /*** 打印棋盘到控制台
     */
    void print() const {
        // 打印列号(顶部坐标)
        cout << "   ";
        for (int i = 0; i < BOARD_SIZE; i++) {
            cout << setw(2) << i << " ";  // 格式化输出列号
        }
        cout << endl;

        // 打印每一行
        for (int i = 0; i < BOARD_SIZE; i++) {
            cout << setw(2) << i << " ";  // 打印行号
            for (int j = 0; j < BOARD_SIZE; j++) {
                // 根据棋子类型输出不同符号
                switch (grid[i][j]) {
                case Piece::EMPTY: cout << " . "; break;  // 空位
                case Piece::BLACK: cout << " ● "; break;  // 黑棋
                case Piece::WHITE: cout << " ○ "; break;  // 白棋
                }
            }
            cout << endl;  // 换行
        }
    }
};

/*** 游戏主类 - 管理游戏流程和状态
 */
class GomokuGame {
private:
    Board board;         // 棋盘对象
    GameState state;     // 当前游戏状态
    Piece currentPlayer; // 当前玩家

public:
    /*** 构造函数 - 初始化新游戏
     */
    GomokuGame() : state(GameState::PLAYING), currentPlayer(Piece::BLACK) {}

    /*** 开始新游戏 - 重置棋盘和游戏状态
     */
    void startNewGame() {
        board.reset();  // 清空棋盘
        state = GameState::PLAYING;
        currentPlayer = Piece::BLACK;  // 黑棋先手
    }

    /*** 获取当前游戏状态
     * @return 当前游戏状态
     */
    GameState getGameState() const {
        return state;
    }

    /*** 打印当前游戏状态
     */
    void printStatus() const {
        board.print();  // 打印棋盘
        cout << endl;

        // 根据游戏状态显示不同信息
        switch (state) {
        case GameState::PLAYING:
            cout << "当前玩家: " << (currentPlayer == Piece::BLACK ? "黑方" : "白方") << endl;
            break;
        case GameState::BLACK_WIN:
            cout << "游戏结束! 黑方获胜!" << endl;
            break;
        case GameState::WHITE_WIN:
            cout << "游戏结束! 白方获胜!" << endl;
            break;
        case GameState::DRAW:
            cout << "游戏结束! 平局!" << endl;
            break;
        }
    }

    /*** 执行走棋操作
     * @param x 横坐标
     * @param y 纵坐标
     * @return 走棋是否成功
     */
    bool makeMove(int x, int y) {
        // 检查游戏状态和走棋有效性
        if (state != GameState::PLAYING || !board.placePiece(x, y, currentPlayer)) {
            return false;  // 走棋失败
        }

        // 检查是否获胜
        if (board.checkFiveInARow(x, y)) {
            // 根据当前玩家设置胜利状态
            state = (currentPlayer == Piece::BLACK) ? GameState::BLACK_WIN : GameState::WHITE_WIN;
            return true;
        }

        // 切换玩家
        currentPlayer = (currentPlayer == Piece::BLACK) ? Piece::WHITE : Piece::BLACK;
        return true;
    }
};

/*** 主函数 - 游戏入口
 */
int main() {
    GomokuGame game;  // 创建游戏实例
    game.startNewGame(); // 初始化新游戏

    // 主游戏循环
    while (true) {
        game.printStatus();  // 显示当前游戏状态

        // 检查游戏是否结束
        if (game.getGameState() != GameState::PLAYING) {
            cout << "输入'r'重新开始,'q'退出: ";
            char cmd;
            cin >> cmd;
            if (cmd == 'r') {
                game.startNewGame();  // 重新开始游戏
                continue;
            }
            else if (cmd == 'q') {
                break;  // 退出游戏
            }
        }

        // 获取玩家输入
        cout << "输入坐标(x y): ";
        int x, y;
        cin >> x >> y;

        // 处理玩家走棋
        if (!game.makeMove(x, y)) {
            cout << "无效移动! 请重新输入。" << endl;
            // 清除错误输入
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }
    }

    return 0;
}

在这里插入图片描述

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐