You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++井字棋游戏中检测行/列/对角线三连相同值?

井字棋游戏胜利检测逻辑实现问题

我是编程初学者,正在开发一款TicTacToe(井字棋)游戏,目前已完成大部分功能。当前需要实现检测棋盘的行、列或对角线是否存在三个相同值的逻辑,若未满足则递归继续游戏。

我的棋盘实现代码如下:

char xToken = 'x';
char oToken = 'o';
char vertical = '|';
char horizontal = '-';

class Board {
public:
    const static int rows = 6;
    const static int cols = 6;
    char grid[rows][cols]{};

    Board() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                grid[i][0] = '0' + i;
                grid[0][j] = '0' + j;

                if (j == 2 || j == 4) {
                    grid[i][j] = vertical;
                }

                if (i == 2 || i == 4) {
                    grid[i][j] = horizontal;
                }
            }
        }
    }

    void printBoard() {
        for (auto & i : grid) {
            for (char j : i) {
                cout << j << "\t";
            }
            cout << endl;
        }
    }
};

这是我的play()函数:

void play() {
        int i = 0;
        int j = 0;

        cout << "choose index you want to play in" << endl;
        cout << "Player 1" << endl;
        cout << "Row: " << endl;
        cin >> i;
        cout << "Column: " << endl;
        cin >> j;
        cout << i << ", " << j << endl;
        if (Board().grid[i][j] != vertical && Board().grid[i][j] != horizontal) {
            grid[i][j] = xToken;
            printBoard();
        }

        cout << "choose index you want to play in" << endl;
        cout << "Player 2" << endl;
        cout << "Row: " << endl;
        cin >> i;
        cout << "Column: " << endl;
        cin >> j;
        cout << i << ", " << j << endl;
        if (Board().grid[i][j] != vertical && Board().grid[i][j] != horizontal) {
            grid[i][j] = oToken;
            printBoard();
        }

        if(grid[i][j] == xToken) {
            cout << "You Win!" << endl;
        } else
            play();
    }

核心问题是如何读取棋盘并判断是否存在三连相同值,使游戏在满足条件时停止。


解决方案

一、修正现有代码的基础问题

你的play()函数每次调用Board().grid[i][j]都会创建新的Board对象,导致无法读取当前游戏的真实棋盘状态;且胜利判断逻辑完全错误,仅判断最后一步的位置值,没有检测行、列、对角线的三连。

二、给Board类添加胜利检测方法

在Board类中新增checkWin(char token)方法,专门检测指定玩家的棋子是否达成三连:

class Board {
    // 保留原有的成员、构造函数和printBoard方法

public:
    bool checkWin(char token) {
        // 检测有效行(1、3、5行,0、2、4为分隔/行号)
        for (int i = 1; i < rows; i += 2) {
            if (grid[i][1] == token && grid[i][3] == token && grid[i][5] == token) {
                return true;
            }
        }

        // 检测有效列(1、3、5列)
        for (int j = 1; j < cols; j += 2) {
            if (grid[1][j] == token && grid[3][j] == token && grid[5][j] == token) {
                return true;
            }
        }

        // 检测两条对角线
        if (grid[1][1] == token && grid[3][3] == token && grid[5][5] == token) {
            return true;
        }
        if (grid[1][5] == token && grid[3][3] == token && grid[5][1] == token) {
            return true;
        }

        return false;
    }
};

三、重构play()函数逻辑

让play函数接收Board实例的引用,处理无效落子,每步后检测胜利或平局:

void play(Board& board) {
    int i = 0;
    int j = 0;
    bool validMove = false;

    // 玩家1落子流程
    cout << "choose index you want to play in" << endl;
    cout << "Player 1 (x)" << endl;
    while (!validMove) {
        cout << "Row: " << endl;
        cin >> i;
        cout << "Column: " << endl;
        cin >> j;
        // 校验位置合法性:在棋盘范围内、不是分隔符、未被占用
        if (i >= 0 && i < Board::rows && j >=0 && j < Board::cols 
            && board.grid[i][j] != vertical && board.grid[i][j] != horizontal
            && board.grid[i][j] != xToken && board.grid[i][j] != oToken) {
            board.grid[i][j] = xToken;
            validMove = true;
        } else {
            cout << "Invalid move! Please choose a valid empty position." << endl;
        }
    }
    board.printBoard();

    // 检查玩家1是否胜利
    if (board.checkWin(xToken)) {
        cout << "Player 1 Wins!" << endl;
        return;
    }

    // 玩家2落子流程
    validMove = false;
    cout << "choose index you want to play in" << endl;
    cout << "Player 2 (o)" << endl;
    while (!validMove) {
        cout << "Row: " << endl;
        cin >> i;
        cout << "Column: " << endl;
        cin >> j;
        if (i >= 0 && i < Board::rows && j >=0 && j < Board::cols 
            && board.grid[i][j] != vertical && board.grid[i][j] != horizontal
            && board.grid[i][j] != xToken && board.grid[i][j] != oToken) {
            board.grid[i][j] = oToken;
            validMove = true;
        } else {
            cout << "Invalid move! Please choose a valid empty position." << endl;
        }
    }
    board.printBoard();

    // 检查玩家2是否胜利
    if (board.checkWin(oToken)) {
        cout << "Player 2 Wins!" << endl;
        return;
    }

    // 检查是否平局
    bool isFull = true;
    for (int row = 1; row < Board::rows; row += 2) {
        for (int col = 1; col < Board::cols; col += 2) {
            if (board.grid[row][col] != xToken && board.grid[row][col] != oToken) {
                isFull = false;
                break;
            }
        }
        if (!isFull) break;
    }
    if (isFull) {
        cout << "It's a draw!" << endl;
        return;
    }

    // 未结束则递归继续游戏
    play(board);
}

四、主函数调用示例

int main() {
    Board gameBoard;
    gameBoard.printBoard();
    play(gameBoard);
    return 0;
}

关键说明

  • 你的6x6棋盘仅行1、3、5和列1、3、5是有效落子位,胜利检测只针对这些位置。
  • 重构后的play函数解决了无效落子、棋盘状态丢失的问题,每步后立即检测胜利,避免无意义递归。
  • 新增平局检测逻辑,当所有有效位被占且无人胜利时,游戏终止。

内容的提问来源于stack exchange,提问作者Pelz04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 13:34:57