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

井字棋(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:电脑获胜无法被识别

原因分析

  1. 循环条件逻辑错误:main函数中while (!game.checkWin() || !game.checkTie())的条件,会导致即使游戏获胜,循环仍继续执行(逻辑应为“没赢且没平局才继续”)。
  2. checkTie函数语法错误:使用if (board[i] = ' ')赋值操作而非if (board[i] == ' ')比较操作,导致所有棋盘格子被强制设为空格,永远无法检测平局。
  3. 胜者判断变量未同步:main函数末尾使用全局currentMove判断胜者,但该变量未同步游戏内的实际获胜状态。

修复方案

  1. 修正循环条件:
while (!game.checkWin() && !game.checkTie())
  1. 修复checkTie函数的比较操作:
bool checkTie() {
    for (int i = 0; i < 9; i++) {
        if (board[i] == ' ')
            return false;
    }
    return true;
};
  1. 在类中新增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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:29:53