动态二维数组中角色移动异常:左右指令触发两步位移问题排查
海龟移动功能Bug排查
问题概述
实现海龟网格移动功能时,触发>或<指令时海龟会移动两步而非一步,最终网格标记位置不符合预期。功能核心需求:
- 读取
rows和cols创建二维网格,初始化为. - 海龟初始位置为(0,0)
- 指令规则:
x:输出网格并退出程序</>/^/v:控制海龟向对应方向移动,越界则传送至网格对侧o:在海龟当前位置标记字符o
原代码
#include <stdio.h> #include <stdlib.h> int main(){ int rows, cols; int i; int j; int x = 0, y = 0; char symbol = 'o'; scanf("%d %d", &rows, &cols); char* pole = (char*)malloc(rows * cols * sizeof(char)); for (i = 0; i < rows; i++){ for(j = 0; j < cols; j++) pole[i * rows + j] = '.'; } pole[x * rows + y] = 'o'; while(symbol != 'x'){ scanf("%c", &symbol); if (symbol == '^') x--; else if (symbol == 'v') x++; else if (symbol == '>') y++; else if (symbol == '<') y--; else if (symbol == 'o') pole[x * rows + y] = 'o'; if(0 < y) y = rows - 1; else if(y > rows) y = 0; if(x < 0) x = cols - 1; else if(x > cols) x = 0; } for (i = 0; i < rows; i++){ for(j = 0; j < cols; j++){ printf("%c", pole[i * rows + j]); } printf("\n"); } return 0; }
输入输出对比
预期输入
3 3 o > v o > v o x
预期输出
o.. .o. ..o
实际输出
o.. ..o ..o
问题原因分析
列方向边界判断逻辑完全错误
代码对列索引y的越界处理写反逻辑且混淆了行列参数:- 原代码
if(0 < y)意为当y>0时就将y设为rows-1,完全违背越界处理逻辑。比如执行>指令后y从0变为1,此时触发该条件,y被强制设为2,相当于一次指令移动了两步。 - 列索引的上限应为
cols而非rows,正确逻辑是:当y < 0时设为cols-1,当y >= cols时设为0。
- 原代码
行方向边界判断参数混淆
行索引x的越界处理错误使用cols作为边界值:- 当
x < 0时应设为rows-1而非cols-1;当x >= rows时应设为0,而非判断x > cols。
- 当
二维数组索引计算错误
用一维数组模拟二维网格时,索引应为行号 * cols + 列号,但代码中使用i * rows + j,当rows和cols数值不同时会导致网格位置错乱,本次测试用例为3x3未暴露,但属于潜在bug。scanf读取字符时捕获空白符
输入指令时的换行符、空格会被scanf("%c")读取,导致symbol为空白字符时进入循环但无指令执行,可能引发非预期的边界判断触发。
修复方案
针对上述问题修改后的代码:
#include <stdio.h> #include <stdlib.h> int main(){ int rows, cols; int i, j; int x = 0, y = 0; char symbol; // 读取行列后清除缓冲区的换行符 scanf("%d %d", &rows, &cols); getchar(); char* pole = (char*)malloc(rows * cols * sizeof(char)); // 正确初始化网格索引 for (i = 0; i < rows; i++){ for(j = 0; j < cols; j++) pole[i * cols + j] = '.'; } pole[x * cols + y] = 'o'; while(1){ scanf("%c", &symbol); // 跳过空白符,避免无效触发 if (symbol == '\n' || symbol == ' ') continue; if (symbol == 'x') break; else if (symbol == '^') x--; else if (symbol == 'v') x++; else if (symbol == '>') y++; else if (symbol == '<') y--; else if (symbol == 'o') pole[x * cols + y] = 'o'; // 正确处理行越界 if(x < 0) x = rows - 1; else if(x >= rows) x = 0; // 正确处理列越界 if(y < 0) y = cols - 1; else if(y >= cols) y = 0; } // 正确输出网格 for (i = 0; i < rows; i++){ for(j = 0; j < cols; j++){ printf("%c", pole[i * cols + j]); } printf("\n"); } free(pole); // 释放动态分配的内存,避免泄漏 return 0; }
修改说明:
- 修正二维数组索引计算为
i*cols +j,适配行列不同的场景 - 重写行、列的越界判断逻辑,使用正确的边界参数
- 添加跳过空白符的逻辑,避免
scanf读取换行/空格导致的异常 - 读取行列后用
getchar()清除缓冲区的换行符 - 调整循环逻辑为
while(1),遇到x直接break,逻辑更清晰 - 添加
free(pole)释放动态分配的内存,避免内存泄漏
内容的提问来源于stack exchange,提问作者lllk
相关产品推荐
相关产品推荐

