【问题标题】:Why this program loops endlessly sometimes and not always为什么这个程序有时而不是总是无限循环
【发布时间】:2018-05-22 13:20:06
【问题描述】:

我成功解决了 K.N.国王。

程序运行良好,但有时会进入无限循环。我不明白这背后的原因。

我使用了一个随机函数,它会给出从 0 到 3 的随机值,并且我使用了充分的条件来处理所有四个随机值。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
    char walk[10][10];
    int direction,currenti=5,currentj=5;

    int i,j;
    for(i=0; i<10; i++)
    {
        for(j=0; j<10; j++)
        {
            walk[i][j]='.';
        }
    }
    srand((unsigned) time(NULL));
    for(i=0; i<26;)
    {
        direction=rand()%4;
        printf("%d ",direction);
        if(direction==0&&walk[currenti][currentj-1]=='.'&&(currentj-1)>0&&(currentj-1)<10)
        {
            currentj=currentj-1;
            walk[currenti][currentj]='A'+i;
            i++;
        }
        else if(direction==1&&walk[currenti][currentj+1]=='.'&&(currentj+1)>0&&(currentj+1)<10)
        {
            currentj=currentj+1;
            walk[currenti][currentj]='A'+i;
            i++;
        }
        else if(direction==2&&walk[currenti-1][currentj]=='.'&&(currenti-1)>0&&(currenti-1)<10)
        {
            currenti=currenti-1;
            walk[currenti][currentj]='A'+i;
            i++;
        }
        else if(direction==3&&walk[currenti+1][currentj]=='.'&&(currenti+1)>0&&(currenti+1)<10)
        {
            currenti=currenti+1;
            walk[currenti][currentj-1]='A'+i;
            i++;
        }
    }
    for(i=0; i<10; i++)
    {
        for(j=0; j<10; j++)
        {
            printf("%c ",walk[i][j]);
        }
        printf("\n");
    }
    return 0;
}

【问题讨论】:

  • 你错过了最后一个 else 部分,它应该处理极端情况。
  • 将i++ 移出第三个for 子句是一个非常糟糕的主意。
  • 您是否尝试在每次更改后打印walk 的所有值?如果程序走{上、上、左、左、下、右、上}会发生什么?
  • @emmrk 因为我使用了 rand()%4,所以方向的值将取值 (0,1,2,3),我已经为它们设置了所有四个条件...什么你的意思是不使用充分条件?
  • @SouravGhosh 我已经处理了 if 条件本身的极端情况,就像在第一个 if 条件中一样,我已经指定 (currentj-1) 不应超出数组范围,即 0 或 9

标签: c c89


【解决方案1】:

只是快速浏览一下,我的猜测是因为在您的主 for 循环中,您只会在某些条件下增加 i,而且很可能它们都不满足,这意味着 i++ 会不会被调用。

验证这一点的最佳方法是将else 子句放置在您正确处理该案例的位置,通过打印一条消息,或者在您永远不会遇到该案例时放置一个断言。

作为预防措施,当您有if/else if 子句时,您应该始终有一个else 子句来处理“如果所有其他方法都失败”值,您可以在其中正确处理错误,或断言代码是否永远不会到达 else 子句。

另外,作为旁注,您应该考虑使用空格以使您的代码更易于阅读,例如:

if (direction == 3 && walk[currenti + 1][currentj] == '.' && (currenti + 1) > 0 && (currenti + 1) < 10)

【讨论】:

  • 范围测试应该在访问数组越界之前进行,我相信下界应该是&gt;= 0。
【解决方案2】:

当你进入一个角落并且它周围的数组只包含点时,你将有一个无限循环。 这只是偶尔发生,因为当然是随机行为

【讨论】:

    【解决方案3】:

    因为您的步行是随机的,所以您可以在无法进一步移动时进入条件,无论数字如何,i 都不会增加

    无限循环示例(您的程序从 1 走到 9)

    1 2 3 . . . . . . .
    8 9 4 . . . . . . .
    7 6 5 . . . . . . .
    . . . . . . . . . .
    . . . . . . . . . .
    . . . . . . . . . .
    . . . . . . . . . .
    . . . . . . . . . .
    . . . . . . . . . .
    . . . . . . . . . .
    

    在第 9 步,您的程序将被阻止,无论下一个 direction 是什么,因为它已经阻止了所有可能的下一步操作。

    这种情况当然有很多变种,但这也意味着你的程序在执行它的 26 步之前就阻塞了自己的情况。

    您应该检测到这种情况以提前终止您的循环。

    【讨论】:

      猜你喜欢
      • 2021-08-16
      • 2018-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-25
      • 1970-01-01
      相关资源
      最近更新 更多