井字棋(Tic Tac Toe)项目问题:左上角方格无响应且胜负判断失效
井字棋(Tic Tac Toe)项目问题修复
问题1:输入“1”时左上角方格无变化
原因分析
computerMove函数的随机移动逻辑存在数组越界问题:
rand() % 9生成0-8的整数,原代码使用board[move - 1],当move为0时,索引变为-1,属于越界访问,会破坏类成员变量(如move)的内存值。- 若
move变量被意外修改为字符值(如'O'的ASCII码79),后续用户输入1时,cin >> move会读取失败,导致move保持79,最终修改的是越界位置board[78]而非board[0],因此左上角方格无变化。
修复方案
将随机移动的索引逻辑改为直接使用move作为数组索引(棋盘0-8索引对应1-9位置),并用循环替代递归找空位置,避免栈溢出:
// 原错误代码 int move; move = rand() % 9; if (board[move - 1] == 'X' || board[move - 1] == 'O') { computerMove(computer); } else { board[move - 1] = computer; } // 修改后代码 int move; do { move = rand() % 9; } while (board[move] != ' '); board[move] = computer;
问题2:电脑获胜无法被识别
原因分析
- 循环条件逻辑错误:main函数中
while (!game.checkWin() || !game.checkTie())的条件,会导致即使游戏获胜,循环仍继续执行(逻辑应为“没赢且没平局才继续”)。 - checkTie函数语法错误:使用
if (board[i] = ' ')赋值操作而非if (board[i] == ' ')比较操作,导致所有棋盘格子被强制设为空格,永远无法检测平局。 - 胜者判断变量未同步:main函数末尾使用全局
currentMove判断胜者,但该变量未同步游戏内的实际获胜状态。
修复方案
- 修正循环条件:
while (!game.checkWin() && !game.checkTie())
- 修复checkTie函数的比较操作:
bool checkTie() { for (int i = 0; i < 9; i++) { if (board[i] == ' ') return false; } return true; };
- 在类中新增
winner成员变量记录获胜者,避免依赖外部变量判断结果。
完整修复后的代码
tictactoe.h
#pragma once #include <iostream> #include <string> #include <iomanip> #include <time.h> #include <limits> using namespace std; class tictactoe { private: int move = 0; string dummy; char player = 'O'; char winner = ' '; char board[9] = { ' ',' ', ' ',' ', ' ', ' ',' ',' ',' ' }; public: void displayMenu() { cout << "Tic Tac Toe" << endl; cout << "-----------\n" << endl; cout << "Objective: make 3 marks, 'X' or 'O', in a row on a 3 x 3 grid.\n" << endl; cout << "To place marks on the grid, enter a number 1-9, 1 being the top left corner, and 9 being the bottom right." << endl; cout << "Press enter to continue: "; getline(cin, dummy); }; void displayBoard() { cout << endl; cout << " " << board[0] << " | " << board[1] << " | " << board[2] << " " << endl; cout << "---+---+---" << endl; cout << " " << board[3] << " | " << board[4] << " | " << board[5] << " " << endl; cout << "---+---+---" << endl; cout << " " << board[6] << " | " << board[7] << " | " << board[8] << " " << endl; }; char determinePlayerMark() { srand(time(NULL)); int num = rand() % 2; char mark = (num == 1) ? 'X' : 'O'; player = mark; cout << "\nYou are " << mark << "!" << endl; cout << "------------\n"; return mark; }; void playerMove() { cout << "Select a box to make your move [1-9]: "; while (!(cin >> move) || move < 1 || move >9 || board[move-1] != ' ') { cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "Invalid move! Enter a number 1-9 for an empty box: "; } board[move - 1] = player; checkWin(); }; void computerMove() { char computer = (player == 'X') ? 'O' : 'X'; // 检查电脑获胜招 for (int i = 0; i < 9; ++i) { if (board[i] == ' ') { board[i] = computer; if (checkWin()) { return; } board[i] = ' '; } } // 阻挡玩家获胜招 for (int i = 0; i < 9; ++i) { if (board[i] == ' ') { board[i] = player; if (checkWin()) { board[i] = computer; checkWin(); return; } board[i] = ' '; } } // 随机找空位置 int move; do { move = rand() % 9; } while (board[move] != ' '); board[move] = computer; checkWin(); } bool checkWin() { const int winCombos[8][3] = { {0,1,2}, {3,4,5}, {6,7,8}, {0,3,6}, {1,4,7}, {2,5,8}, {0,4,8}, {2,4,6} }; for (auto& combo : winCombos) { if (board[combo[0]] != ' ' && board[combo[0]] == board[combo[1]] && board[combo[1]] == board[combo[2]]) { winner = board[combo[0]]; return true; } } winner = ' '; return false; }; bool checkTie() { for (int i = 0; i < 9; i++) { if (board[i] == ' ') return false; } return true; }; char getWinner() { return winner; }; };
tictactoe.cpp
#include <iostream> #include <string> #include <iomanip> #include "tictactoe.h" using namespace std; int main() { tictactoe game; game.displayMenu(); char player = game.determinePlayerMark(); while (!game.checkWin() && !game.checkTie()) { if (player == 'X') { game.displayBoard(); game.playerMove(); if (game.checkWin() || game.checkTie()) break; game.computerMove(); } else if (player == 'O') { game.computerMove(); if (game.checkWin() || game.checkTie()) break; game.displayBoard(); game.playerMove(); } } game.displayBoard(); if (game.checkWin()) { cout << game.getWinner() << " wins!" << endl; } else if (game.checkTie()) { cout << "It is a tie!" << endl; } cout << "\nThank you for playing Tic Tac Toe!"; return 0; }
额外优化点
- 移除无用函数参数,简化代码逻辑;
- 将
srand调用移到determinePlayerMark内,避免多次重置随机种子; - 优化玩家输入验证,用循环替代递归避免栈溢出;
- 使用获胜组合数组简化
checkWin函数,提升代码可维护性。
内容的提问来源于stack exchange,提问作者lyanzu
相关产品推荐
相关产品推荐

