C++井字棋代码嵌套循环在VS Code仅提示一次输入 在线编译器正常原因
问题原因及修复方案
1. 初始版本输入一次就崩溃的核心原因
你最初声明的const char *values[ROWS][COLS]没有做初始化,数组内的所有指针都是野指针,指向非法内存地址。当程序第一次执行strcmp(values[rows][cols], "*O")时,会尝试访问野指针指向的内存,直接触发内存访问错误,导致程序崩溃退出,这就是你输入一次就自动退出的原因。
你后续将数组初始化为全"*A"的操作已经解决了这个崩溃问题。
2. 现有代码仍存在的逻辑错误
2.1 去重校验的内层for循环完全无效
你写的内层for循环的循环变量i没有任何地方用到,循环执行player_iteration + 1次没有实际意义,每次判断的都是同一个values[rows][cols]的值,属于冗余的无效代码。
井字棋的位置重复校验根本不需要循环,只需要直接判断当前用户输入的行列对应的数组值是否为初始的"*A"即可:如果是就说明位置为空可用,如果不是就说明已经被占用。
2.2 重复输入后的校验逻辑有漏洞
你现在的逻辑中,检测到位置重复后,只让用户重新输入一次就直接break,没有对新输入的位置做重复校验、也没有做越界校验,如果用户第二次输入的还是重复或者越界的数值,程序会直接将错误的值写入数组,逻辑不严谨。
2.3 玩家标识赋值错误
当前偶数轮(第1、3、5、7、9次操作,对应玩家1)你赋值的是"*O",奇数轮(对应玩家2)赋值的是"*X",和常规的玩家1用X的习惯不符,属于业务逻辑错误,不会影响程序运行但不符合常规需求。
3. 修正后的核心代码示例
#include <iostream> #include <string.h> using namespace std; int main() { const int ROWS = 3; const int COLS = 3; // 初始化数组,*A代表空位置 const char *values[ROWS][COLS] = { {"*A", "*A", "*A"} , {"*A", "*A", "*A"}, {"*A", "*A", "*A"}}; int player_iteration; int rows; int cols; for (player_iteration = 0; player_iteration < 9; player_iteration++) { const char* current_player_mark = (player_iteration % 2 == 0) ? "*X" : "*O"; int player_num = (player_iteration % 2 == 0) ? 1 : 2; cout << "请输入玩家" << player_num << "的选择:行 列" << endl; // 循环直到输入合法(越界+重复都校验) while(1){ cout << "行: " ; cin >> rows; cout << "列: "; cin >> cols; // 校验越界 if (rows < 0 || rows > 2 || cols < 0 || cols > 2) { cout << "输入不合法,行列范围是0-2,请重新输入!" << endl; continue; } // 校验重复 if(strcmp(values[rows][cols], "*A") != 0){ cout << "该位置已被占用,请重新输入!" << endl; continue; } // 校验通过跳出循环 break; } values[rows][cols] = current_player_mark; } return 0; }
上面的代码去掉了冗余的重复逻辑,把越界和重复校验都整合到同一个while循环里,逻辑更简洁也更严谨,同时修正了玩家标识的赋值问题。
内容的提问来源于stack exchange,提问作者Sherri
相关产品推荐
相关产品推荐

