#include \u003c!--包含标准输入输出流库--> #include \u003c!--包含向量库--> using namespace std; \u003c!--使用标准命名空间--> class TicTacToe { \u003c!--声明TicTacToe类--> private: \u003c!--声明私有成员--> vector<vector> board; \u003c!--创建二维向量用于表示棋盘--> char player; \u003c!--玩家棋子--> char computer; \u003c!--电脑棋子--> public: \u003c!--声明公有成员--> TicTacToe() { \u003c!--类构造函数--> board.resize(3, vector(3, '')); \u003c!--初始化棋盘为3x3的空白格--> player = ' '; \u003c!--初始化玩家棋子为空--> computer = ' '; \u003c!--初始化电脑棋子为空--> } \u003c!--构造函数结束--> void startGame() { \u003c!--开始游戏函数--> cout << "Welcome to Tic Tac Toe!" << endl; \u003c!--输出欢迎信息--> cout << "Please choose 'X' or 'O': "; \u003c!--提示玩家选择棋子--> cin >> player; \u003c!--读取玩家的选择--> if (player == 'X' || player == 'x') { \u003c!--若玩家选择的是X,则电脑使用O--> computer = 'O'; \u003c!--电脑使用O--> } else if (player == 'O' || player == 'o') { \u003c!--若玩家选择的是O,则电脑使用X--> computer = 'X'; \u003c!--电脑使用X--> } else { \u003c!--若玩家输入无效,则输出错误信息并退出游戏--> cout << "Invalid input. Please choose 'X' or 'O'." << endl; \u003c!--输出错误信息--> return; \u003c!--退出函数--> } \u003c!--选择棋子结束--> cout << "Do you want to play first? (Y/N): "; \u003c!--提示玩家选择是否先手--> char choice; \u003c!--声明choice变量--> cin >> choice; \u003c!--读取玩家的选择--> if (choice == 'N' || choice == 'n') { \u003c!--若玩家选择不先手,则电脑先手--> computerMove(); \u003c!--电脑先手--> printBoard(); \u003c!--打印棋盘--> } \u003c!--先手选择结束--> playGame(); \u003c!--开始游戏--> } \u003c!--startGame函数结束--> private: \u003c!--声明私有成员函数--> void playGame() { \u003c!--游戏循环函数--> while (!isGameOver()) { \u003c!--当游戏未结束时循环进行玩家和电脑的移动--> playerMove(); \u003c!--玩家移动--> if (isGameOver()) { \u003c!--若玩家移动后游戏结束,则跳出循环--> break; \u003c!--跳出循环--> } \u003c!--游戏结束判断结束--> computerMove(); \u003c!--电脑移动--> printBoard(); \u003c!--打印棋盘--> } \u003c!--循环结束--> char winner = getWinner(); \u003c!--获取胜利者--> if (winner == player) { \u003c!--若胜利者为玩家,则输出玩家获胜信息--> cout << "Congratulations! You win!" << endl; \u003c!--输出玩家获胜信息--> } else if (winner == computer) { \u003c!--若胜利者为电脑,则输出电脑获胜信息--> cout << "Sorry, you lose. Computer wins!" << endl; \u003c!--输出电脑获胜信息--> } else { \u003c!--若无胜利者,则输出平局信息--> cout << "It's a draw!" << endl; \u003c!--输出平局信息--> } \u003c!--胜利者判断结束--> } \u003c!--playGame函数结束--> void playerMove() { \u003c!--玩家移动函数--> cout << "Enter your move (1-9): "; \u003c!--提示玩家输入移动位置--> int move; \u003c!--声明移动变量--> cin >> move; \u003c!--读取玩家的移动位置--> int row = (move - 1) / 3; \u003c!--计算行号--> int col = (move - 1) % 3; \u003c!--计算列号--> if (board[row][col] == '') { \u003c!--若移动位置为空,则玩家在该位置放置棋子--> board[row][col] = player; \u003c!--玩家放置棋子--> } else { \u003c!--若移动位置已被占据,则输出错误信息并重新输入--> cout << "Invalid move. Please choose an empty cell." << endl; \u003c!--输出错误信息--> playerMove(); \u003c!--重新输入--> } \u003c!--移动位置判断结束--> printBoard(); \u003c!--打印棋盘--> } \u003c!--playerMove函数结束--> void computerMove() { \u003c!--电脑移动函数--> int bestScore = INT_MIN; \u003c!--初始化最优分数为最小整数--> int bestMoveRow, bestMoveCol; \u003c!--声明最优移动位置变量--> for (int i = 0; i < 3; i++) { \u003c!--遍历棋盘行--> for (int j = 0; j < 3; j++) { \u003c!--遍历棋盘列--> if (board[i][j] == '') { \u003c!--遍历棋盘,找到空白位置--> board[i][j] = computer; \u003c!--在该位置放置电脑棋子--> int score = minimax(board, 0, false); \u003c!--调用minimax算法计算当前局面的分数--> board[i][j] = ''; \u003c!--恢复该位置为空白--> if (score > bestScore) { \u003c!--若当前分数比之前的分数大,则更新最优分数和最优移动位置--> bestScore = score; \u003c!--更新最优分数--> bestMoveRow = i; \u003c!--更新最优移动行号--> bestMoveCol = j; \u003c!--更新最优移动列号--> } \u003c!--最优分数更新结束--> } \u003c!--空白位置判断结束--> } \u003c!--列遍历结束--> } \u003c!--行遍历结束--> board[bestMoveRow][bestMoveCol] = computer; \u003c!--在最优移动位置放置电脑棋子--> } \u003c!--computerMove函数结束--> int minimax(vector<vector>& board, int depth, bool isMaximizingPlayer) { \u003c!--minimax算法函数--> if (isGameOver()) { \u003c!--若游戏结束,则返回对应的分数--> char winner = getWinner(); \u003c!--获取胜利者--> if (winner == computer) { \u003c!--若胜利者为电脑,则返回1--> return 1; \u003c!--返回1--> } else if (winner == player) { \u003c!--若胜利者为玩家,则返回-1--> return -1; \u003c!--返回-1--> } else { \u003c!--若无胜利者,则返回0--> return 0; \u003c!--返回0--> } \u003c!--胜利者判断结束--> } \u003c!--游戏结束判断结束--> if (isMaximizingPlayer) { \u003c!--若当前是最大化玩家,则找到能够使得分数最大的移动--> int bestScore = INT_MIN; \u003c!--初始化最优分数为最小整数--> for (int i = 0; i < 3; i++) { \u003c!--遍历棋盘行--> for (int j = 0; j < 3; j++) { \u003c!--遍历棋盘列--> if (board[i][j] == '') { \u003c!--遍历棋盘,找到空白位置--> board[i][j] = computer; \u003c!--在该位置放置电脑棋子--> int score = minimax(board, depth + 1, false); \u003c!--递归调用minimax算法--> board[i][j] = ''; \u003c!--恢复该位置为空白--> bestScore = max(score, bestScore); \u003c!--更新最优分数--> } \u003c!--空白位置判断结束--> } \u003c!--列遍历结束--> } \u003c!--行遍历结束--> return bestScore; \u003c!--返回最优分数--> } else { \u003c!--若当前是最小化玩家,则找到能够使得分数最小的移动--> int bestScore = INT_MAX; \u003c!--初始化最优分数为最大整数--> for (int i = 0; i < 3; i++) { \u003c!--遍历棋盘行--> for (int j = 0; j < 3; j++) { \u003c!--遍历棋盘列--> if (board[i][j] == '') { \u003c!--遍历棋盘,找到空白位置--> board[i][j] = player; \u003c!--在该位置放置玩家棋子--> int score = minimax(board, depth + 1, true); \u003c!--递归调用minimax算法--> board[i][j] = ''; \u003c!--恢复该位置为空白--> bestScore = min(score, bestScore); \u003c!--更新最优分数--> } \u003c!--空白位置判断结束--> } \u003c!--列遍历结束--> } \u003c!--行遍历结束--> return bestScore; \u003c!--返回最优分数--> } \u003c!--最大化/最小化判断结束--> } \u003c!--minimax算法函数结束--> bool isGameOver() { \u003c!--游戏结束判断函数--> return isBoardFull() || getWinner() != ' '; \u003c!--若棋盘已满或有胜利者,则游戏结束--> } \u003c!--isGameOver函数结束--> bool isBoardFull() { \u003c!--棋盘是否已满判断函数--> for (int i = 0; i < 3; i++) { \u003c!--遍历棋盘行--> for (int j = 0; j < 3; j++) { \u003c!--遍历棋盘列--> if (board[i][j] == '') { \u003c!--若存在空白位置,则棋盘未满--> return false; \u003c!--返回false--> } \u003c!--空白位置判断结束--> } \u003c!--列遍历结束--> } \u003c!--行遍历结束--> return true; \u003c!--若不存在空白位置,则棋盘已满--> } \u003c!--isBoardFull函数结束--> char getWinner() { \u003c!--胜利者判断函数--> for (int i = 0; i < 3; i++) { \u003c!--遍历棋盘行--> if (board[i][0] != '' && board[i][0] == board[i][1] && board[i][0] == board[i][2]) { \u003c!--检查每一行是否有相同棋子--> return board[i][0]; \u003c!--若有,则返回该棋子--> } \u003c!--行判断结束--> } \u003c!--行遍历结束--> for (int j = 0; j < 3; j++) { \u003c!--遍历棋盘列--> if (board[0][j] != '' && board[0][j] == board[1][j] && board[0][j] == board[2][j]) { \u003c!--检查每一列是否有相同棋子--> return board[0][j]; \u003c!--若有,则返回该棋子--> } \u003c!--列判断结束--> } \u003c!--列遍历结束--> if (board[0][0] != '' && board[0][0] == board[1][1] && board[0][0] == board[2][2]) { \u003c!--检查左上到右下对角线是否有相同棋子--> return board[0][0]; \u003c!--若有,则返回该棋子--> } \u003c!--对角线判断结束--> if (board[0][2] != '*' && board[0][2] == board[1][1] && board[0][2] == board[2][0]) { \u003c!--检查右上到左下对角线是否有相同棋子--> return board[0][2]; \u003c!--若有,则返回该棋子--> } \u003c!--对角线判断结束--> return ' '; \u003c!--若无胜利者,则返回空字符--> } \u003c!--getWinner函数结束--> void printBoard() { \u003c!--打印棋盘函数--> cout << "-------------" << endl; \u003c!--打印棋盘上边界--> for (int i = 0; i < 3; i++) { \u003c!--遍历棋盘行--> cout << "| "; \u003c!--打印棋盘左边界--> for (int j = 0; j < 3; j++) { \u003c!--遍历棋盘列--> cout << board[i][j] << " | "; \u003c!--打印棋盘内容和分隔符--> } \u003c!--列遍历结束--> cout << endl << "-------------" << endl; \u003c!--打印棋盘分隔符和右边界--> } \u003c!--行遍历结束--> } \u003c!--printBoard函数结束--> }; \u003c!--TicTacToe类结束--> int main() { \u003c!--主函数--> TicTacToe game; \u003c!--创建TicTacToe类对象--> game.startGame(); \u003c!--开始游戏--> return 0; \u003c!--返回0表示程序正常结束--> } \u003c!--主函数结束--> ```

C++ Tic-Tac-Toe Game with Minimax AI - Play Against the Computer

原文地址: https://www.cveoy.top/t/topic/qzyp 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录