使用rand()函数实现井字棋电脑走棋时遇功能异常求助
双人井字棋改人机对战的问题修复
核心问题分析
- 随机数未初始化:未调用
srand(time(0)),导致rand()每次生成相同序列,电脑落子固定 - 胜负判断函数错误:行判断条件
board[i][1] && board[i][2]是逻辑与,不是相等判断,导致无法正确检测行胜利 - 电脑落子逻辑缺陷:
- 电脑选到已占位置时,用
i--回退循环,会导致玩家重复走回合 - 电脑落子后未重新绘制棋盘,玩家看不到电脑走棋
- 电脑落子后未检查胜负,直接切换玩家
- 电脑选到已占位置时,用
- 玩家/电脑标记切换时机错误:玩家落子后未先切换标记就执行电脑落子,导致电脑用玩家的标记下棋
- 循环次数限制不合理:
for(int i=0; i<4; i++)最多只允许玩家走4步,而玩家先手最多可走5步
修复后的完整代码
#include<iostream> #include<cstdlib> #include<ctime> using namespace std; char board[3][3] = {{'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'}}; char current_marker; int current_player; void drawBoard(){ cout<< " | | "<<endl; cout<<" "<<board[0][0]<<" | "<<board[0][1]<<" | "<<board[0][2]<<endl; cout<< "_____|_______|_____"<<endl; cout<< " | | "<<endl; cout<<" "<<board[1][0]<<" | "<<board[1][1]<<" | "<<board[1][2]<<endl; cout<< "_____|_______|_____"<<endl; cout<< " | | "<<endl; cout<<" "<<board[2][0]<<" | "<<board[2][1]<<" | "<<board[2][2]<<endl; cout<< " | | "<<endl; } bool placeMarker(int slot){ int row = slot/3; int col; if(slot % 3 == 0){ row = row - 1; col = 2; } else{ col = (slot % 3) - 1; } if(board[row][col] != 'X' && board[row][col] != 'O'){ board[row][col] = current_marker; return true; } else return false; } int winner(){ // 检查行 for(int i=0; i<3; i++){ if(board[i][0] == board[i][1] && board[i][1] == board[i][2]){ return current_player; } } // 检查列 for(int i=0; i<3; i++){ if(board[0][i] == board[1][i] && board[1][i] == board[2][i]){ return current_player; } } // 检查对角线 if(board[0][0] == board[1][1] && board[1][1] == board[2][2]){ return current_player; } if(board[0][2] == board[1][1] && board[1][1] == board[2][0]){ return current_player; } return 0; } void swap_player_marker(){ if(current_marker == 'X') current_marker = 'O'; else current_marker = 'X'; if(current_player == 1) current_player = 2; else current_player = 1; } void game(){ string name1; cout<<"Enter your name: "; cin>>name1; cout<<name1<<" choose your marker (X/O): "; char h_marker; cin>>h_marker; // 确保玩家输入有效标记 while(h_marker != 'X' && h_marker != 'O'){ cout<<"Invalid marker! Choose X or O: "; cin>>h_marker; } current_player = 1; current_marker = h_marker; // 初始化随机数生成器 srand(time(0)); drawBoard(); int player_won = 0; int moves = 0; // 记录总步数,最多9步 while(moves < 9 && player_won == 0){ if(current_player == 1){ // 玩家回合 cout<<"It's your turn. Enter slot: "; int slot; cin>> slot; if(slot < 1 || slot > 9){ cout<<"Slot invalid! Try another slot!"<<endl; continue; } if(!placeMarker(slot)){ cout<<"Slot occupied! Try another slot!"<<endl; continue; } drawBoard(); player_won = winner(); if(player_won == 1){ cout<<name1<<" won! Congratulations!"<<endl; break; } moves++; // 切换到电脑回合 swap_player_marker(); } else { // 电脑回合 cout<<"Computer's turn..."<<endl; int comp_slot; // 循环直到找到可用位置 do{ comp_slot = rand() % 9 + 1; } while(!placeMarker(comp_slot)); drawBoard(); player_won = winner(); if(player_won == 2){ cout<<"Computer won! Better luck next time!"<<endl; break; } moves++; // 切换到玩家回合 swap_player_marker(); } } if(player_won == 0 && moves == 9){ cout<<"This game is a TIE!"<<endl; } } int main(){ game(); return 0; }
关键修复说明
- 初始化随机数:在
game()函数中添加srand(time(0)),确保每次运行电脑落子随机 - 修复胜负判断:将行判断的错误逻辑改为正确的相等比较,同时限制循环次数为3(只检查3行3列)
- 优化电脑落子:用
do-while循环让电脑自动重新选择可用位置,避免影响玩家回合 - 调整回合切换逻辑:玩家完成落子并检查胜负后,再切换到电脑;电脑完成落子后切换回玩家,确保标记正确
- 改用while循环控制游戏流程:通过总步数
moves和胜负状态控制游戏结束,更符合井字棋规则
内容的提问来源于stack exchange,提问作者WhoMe
相关产品推荐
相关产品推荐

