如何在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
相关产品推荐
相关产品推荐

