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

C++中std::out_of_range错误排查及井字棋代码修正咨询

问题描述

我正在用C++开发井字棋(tic-tac-toe)游戏,编写的代码如下:

#include <iostream>
#include <vector>

bool X = true;
bool O = false;
bool b = true;
int a = 0;
int j = 100;
std::string game = "";
std::vector<char> c = {'1', '2', '3', '4', '5','6','7','8','9'};

void check(){
    std::cout<<"Enter position: ";
    int pos;
    std::cin>>pos;
    if(c.at(pos-1)==pos){
      if(X == true){
         c[pos-1] = 'X';
         O = true;
         X = false;
         a = 0;
      }
      else if(O == true){
        c[pos-1] = 'O';
        X = true;
        O = false;
        a = 0;
      }
    }
    else{
      std::cout<<"Not empty, enter again.";
      a = 1;
    }
}

void print(){
  std::cout<<"|---|---|---|
| "<<c.at(0)<<" | "<<c.at(1)<<" | "<<c.at(2)<<" | "<<"\n"
"|---|---|---|
| "<<c.at(3)<<" | "<<c.at(4)<<" | "<<c.at(5)<<" | "<<"\n"
"|---|---|---|
| "<<c.at(6)<<" | "<<c.at(7)<<" | "<<c.at(8)<<" | \n"
"|---|---|---|
";
}
int main(){
  print();
    int b = 0;
    while((X==true||O==true)&&b<9){
         check();
         while(a=1){
          check();
         }
         print();
         for(int i = 0;i<7;i+=3){
          if(c.at(i)==c.at(i+1)&&c.at(i+1)==c.at(i+2)&&c.at(i)==c.at(i+2)){
            j = i;
            break;
            }
          else{
              continue;
            }
          }
          for(int i = 0;i<3;i++){
            if(c.at(i)==c.at(i+3)&&c.at(i+3)==c.at(i+6)&&c.at(i)==c.at(i+6)){
               j = i;
               break;
               }
            else{
              continue;
            }
          }
          if(c.at(0)==c.at(4)&&c.at(4)==c.at(8)&&c.at(0)==c.at(8)){
            j = 0;
          }
          else if(c.at(2)==c.at(4)&&c.at(4)==c.at(6)&&c.at(2)==c.at(6)){
            j = 2;
          }
          if(j!=100){
            break;
          }
          b++;
    }
    if(j!=100){
      if(c.at(j)=='X'){
        game = "Won by X!";
      }
      else{
        game = "Won by O!";
      }
    }
    else if(j=100){
        game = "Draw";
    }
    std::cout<<game<<"\n";
}

运行时持续出现以下错误:

|---|---|---|
| 1 | 2 | 3 |
|---|---|---|
| 4 | 5 | 6 |
|---|---|---|
| 7 | 8 | 9 |
|---|---|---|
Enter position: terminate called after throwing an instance of
'std::out_of_range'
what():  vector::_M_range_check: __n (which is
18446744073709551615) >= this->size() (which is 9)

我编写了两个函数并在main函数的while循环中调用,循环以bool类型变量X或O为true作为执行条件。我认为错误出在第一个函数,但未发现问题。请问该如何修复这个错误?此外,我的代码其余部分是否正确?


错误修复及代码优化建议

1. 核心错误:std::out_of_range 异常修复

这个异常是因为访问了vector的非法索引(18446744073709551615是无符号的-1,说明pos-1变成了负数),根源有两点:

  • 输入验证缺失:用户输入非整数(字母、符号)时,std::cin >> pos会失败,pos变成垃圾值,导致c.at(pos-1)越界。
  • 位置判断错误:c里存的是字符'1'-'9',直接对比c.at(pos-1)==pos是错的(字符和整数的ASCII值不匹配)。

修复后的check()函数:

void check(){
    std::cout << "Enter position: ";
    int pos;
    // 强制输入1-9的整数,处理非法输入
    while(!(std::cin >> pos) || pos < 1 || pos > 9){
        std::cin.clear(); // 重置输入流错误状态
        std::cin.ignore(1000, '\n'); // 跳过当前行的无效输入
        std::cout << "无效输入!请输入1-9之间的数字:";
    }
    // 正确判断位置是否未被占用:字符转数字对比
    if(c.at(pos-1) == '0' + pos){
        if(X){
            c[pos-1] = 'X';
            X = false;
            O = true;
            a = 0;
        } else if(O){
            c[pos-1] = 'O';
            O = false;
            X = true;
            a = 0;
        }
    } else {
        std::cout << "该位置已被占用,请重新输入。\n";
        a = 1;
    }
}

2. 其他代码问题修复

(1)循环条件的赋值错误

main函数里的while(a=1)是赋值操作,会导致循环永远为真,必须改成判断:while(a == 1)。

(2)三连判断冗余

检查胜负的代码里,c.at(i)==c.at(i+1)&&c.at(i+1)==c.at(i+2)&&c.at(i)==c.at(i+2)最后一个判断完全多余,简化为c.at(i)==c.at(i+1) && c.at(i+1)==c.at(i+2)即可。

(3)平局判断的赋值错误

else if(j=100)是赋值操作,应该改成else if(j == 100)。

(4)全局变量滥用

全局变量X、O、a、j、c容易导致逻辑混乱,建议改成局部变量或通过参数传递,比如把棋盘和回合状态作为参数传给函数。

(5)循环条件冗余

main里的while((X==true||O==true)&&b<9)可以简化为while(j == 100 && b < 9),因为只要没分出胜负(j还是100)且没下满9步就继续。

3. 优化后的完整代码示例

#include <iostream>
#include <vector>
#include <limits>

// 打印棋盘
void print(const std::vector<char>& board){
    std::cout << "|---|---|---|\n"
              << "| " << board[0] << " | " << board[1] << " | " << board[2] << " |\n"
              << "|---|---|---|\n"
              << "| " << board[3] << " | " << board[4] << " | " << board[5] << " |\n"
              << "|---|---|---|\n"
              << "| " << board[6] << " | " << board[7] << " | " << board[8] << " |\n"
              << "|---|---|---|\n";
}

// 检查是否获胜
bool checkWin(const std::vector<char>& board){
    // 检查行
    for(int i = 0; i < 9; i += 3){
        if(board[i] == board[i+1] && board[i+1] == board[i+2]){
            return true;
        }
    }
    // 检查列
    for(int i = 0; i < 3; ++i){
        if(board[i] == board[i+3] && board[i+3] == board[i+6]){
            return true;
        }
    }
    // 检查对角线
    if(board[0] == board[4] && board[4] == board[8]){
        return true;
    }
    if(board[2] == board[4] && board[4] == board[6]){
        return true;
    }
    return false;
}

// 玩家落子
void makeMove(std::vector<char>& board, bool& isXTurn){
    int pos;
    std::cout << "请输入位置:";
    while(!(std::cin >> pos) || pos < 1 || pos > 9 || board[pos-1] != '0' + pos){
        if(!std::cin){
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "无效输入!请输入1-9之间的数字:";
        } else if(board[pos-1] != '0' + pos){
            std::cout << "该位置已被占用,请重新输入:";
        } else {
            std::cout << "请输入1-9之间的数字:";
        }
    }
    board[pos-1] = isXTurn ? 'X' : 'O';
    isXTurn = !isXTurn;
}

int main(){
    std::vector<char> board = {'1', '2', '3', '4', '5','6','7','8','9'};
    bool isXTurn = true;
    int moves = 0;
    bool gameWon = false;

    print(board);
    while(moves < 9 && !gameWon){
        makeMove(board, isXTurn);
        print(board);
        gameWon = checkWin(board);
        moves++;
    }

    if(gameWon){
        std::cout << (isXTurn ? "O" : "X") << "获胜!\n";
    } else {
        std::cout << "平局!\n";
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者Asteria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 16:47:32