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

动态二维数组中角色移动异常:左右指令触发两步位移问题排查

海龟移动功能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

问题原因分析

  1. 列方向边界判断逻辑完全错误
    代码对列索引y的越界处理写反逻辑且混淆了行列参数:

    • 原代码if(0 < y)意为当y>0时就将y设为rows-1,完全违背越界处理逻辑。比如执行>指令后y从0变为1,此时触发该条件,y被强制设为2,相当于一次指令移动了两步。
    • 列索引的上限应为cols而非rows,正确逻辑是:当y < 0时设为cols-1,当y >= cols时设为0。
  2. 行方向边界判断参数混淆
    行索引x的越界处理错误使用cols作为边界值:

    • 当x < 0时应设为rows-1而非cols-1;当x >= rows时应设为0,而非判断x > cols。
  3. 二维数组索引计算错误
    用一维数组模拟二维网格时,索引应为行号 * cols + 列号,但代码中使用i * rows + j,当rows和cols数值不同时会导致网格位置错乱,本次测试用例为3x3未暴露,但属于潜在bug。

  4. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:05:23