UVa227:Puzzle

本文介绍了一款基于C语言的谜题游戏实现过程,包括使用gets()与scanf()的区别及注意事项,通过实例演示如何控制网格中空白格的移动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目名称:谜题

题目描述:

有一个55的网格,其中恰好有一个格子是空的,其他格子各有一个字母,一共有四种指令:A,B,L,R,分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格和指令序列(分别以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出”This puzzle has no final configuration.”
1.第一遍理解题意测试程序:
1)没有考虑输出输入
2)将char类型先替换成int类型
3)没有考虑多次输出输入

#include<stdio.h>
#include<string.h>
#define maxn 10000
int S[maxn][maxn];
int ope[maxn];
int main () {
    int i,j,m,n;
    for(i=0;i<5;i++)
        for(j=0;j<5;j++)
        scanf("%d",&S[i][j]);
    for(i=0;i<5;i++)
        for(j=0;j<5;j++)
        if(S[i][j] == 9 )
        {
            m=i;
            n=j;
            break;
        }
    printf("=====================================\n");
    printf("m=%d\nn=%d\n",m,n);
    printf("=====================================\n");

    int e;
    for(e=0;e<7;e++){
        scanf("%c",&ope[e]);

    }
   printf("=====================================\n");
    int d;
    char temp;
    for(d=0;d<7;d++){
       if(ope[d]=='A')
       {
           temp=S[m][n];
           S[m][n]=S[m-1][n];
           S[m-1][n]=temp;
           m--;
       }
       else if(ope[d]=='B')
       {
           temp=S[m][n];
           S[m][n]=S[m+1][n];
           S[m+1][n]=temp;
           m++;
       }
       else if(ope[d]=='R')
       {
           temp=S[m][n];
           S[m][n]=S[m][n+1];
           S[m][n+1]=temp;
           n++;
       }
       else if(ope[d]=='L')
       {
           temp=S[m][n];
           S[m][n]=S[m][n-1];
           S[m][n-1]=temp;
           n--;
       }
    }

    for(i=0;i<5;i++) {
        for(j=0;j<5;j++)
            printf("%5d",S[i][j]);
            printf("\n");
    }
    printf("=====================================\n");
return 0;
}

这里写图片描述
从运行结果可知大体空位(此处以数字9代替)移动方位正确。
存在问题:
1)操作序列变成了ARRBBLL,多了一个L才使9位置移动正确。并且通过试验知道,最后一个L不起作用。
2)尝试用char替换int类型,可是运行结果却在m,n定位就出错了。

2.第二次调整代码:
参考文章:
http://blog.youkuaiyun.com/to_xidianhph_youth/article/details/36623797
(第一次写的时候没保存,结果中间好多错误也忘记了,但是最终错误在于使用scanf()函数,和gets()函数,gets()使得读入字符和操作数正确,整个程序也就正确啦)

#include<stdio.h>
#include<string.h>
#define maxn 20
#define command 10000
char S[maxn][maxn];
char ope[command];
int main () {
    int i,j,m=0,n=0;

    gets(S[0]);
    gets(S[1]);
    gets(S[2]);
    gets(S[3]);
    gets(S[4]);
    for(i=0;i<5;i++)
        for(j=0;j<5;j++)
        if(S[i][j] == ' ' )
        {
            m=i;
            n=j;
            break;
        }

    gets(ope);
    int len ;
    len = strlen(ope);
    int d;
    char temp=' ';
for(d=0;d<len;d++){

       if(ope[d]=='A' && m!=0)
       {
           temp=S[m][n];
           S[m][n]=S[m-1][n];
           S[m-1][n]=temp;
           --m;
       }
       if(ope[d]=='B' && m!=4)
       {
           temp=S[m][n];
           S[m][n]=S[m+1][n];
           S[m+1][n]=temp;
           ++m;

       }
       if(ope[d]=='R' && n!=4)
       {
           temp=S[m][n];
           S[m][n]=S[m][n+1];
           S[m][n+1]=temp;
           ++n;
       }
       if(ope[d]=='L' && n!=0)
       {
           temp=S[m][n];
           S[m][n]=S[m][n-1];
           S[m][n-1]=temp;
           --n;
       }
}
for(i = 0; i < 5; i++)
        {
            printf("%c %c %c %c %c\n", S[i][0], S[i][1], S[i][2], S[i][3], S[i][4]);
        }

return 0;
}

运行结果:(截图总上传不上,先将就看看这个)
AAAAA
BBBBB
C CCC
DDDDD
EEEEE
ARRBBL
A A A A A
B B B C B
C B C D C
D D D D
E E E E E
3.优化代码:
根据题目要求要以0为结尾,改动如下:

    gets(ope);
    int len ;
    int flag=1;
    len = strlen(ope);
    int d;
    char temp=' ';
for(d=0;d<len;d++){

    if(s[len-1] == '0' || s[i] == 'A' || s[i] == 'R' || s[i] == 'B' || s[i] == 'L' ) {

       if(ope[d]=='A' && m!=0)
       {
           temp=S[m][n];
           S[m][n]=S[m-1][n];
           S[m-1][n]=temp;
           --m;
       }
       if(ope[d]=='B' && m!=4)
       {
           temp=S[m][n];
           S[m][n]=S[m+1][n];
           S[m+1][n]=temp;
           ++m;

       }
       if(ope[d]=='R' && n!=4)
       {
           temp=S[m][n];
           S[m][n]=S[m][n+1];
           S[m][n+1]=temp;
           ++n;
       }
       if(ope[d]=='L' && n!=0)
       {
           temp=S[m][n];
           S[m][n]=S[m][n-1];
           S[m][n-1]=temp;
           --n;
       }
    }
    else 
        flag=0;
}
    if(flag) 
    {
       for(i = 0; i < 5; i++)
       printf("%c %c %c %c %c\n", S[i][0], S[i][1], S[i][2], S[i][3], S[i][4]);
    }
    else
       printf("This puzzle has no final configuration.\n");

5.//预留:以后再想想可以不间断的输入等等和格式优化

6.总结:
参考文章:http://www.cnblogs.com/qinjunni/archive/2012/03/03/2378323.html
http://www.cnblogs.com/JMDWQ/archive/2012/03/06/2381302.html

*****gets

  【1】函数:gets(字符指针)

  【2】头文件:stdio.h(c中),c++不需包含此头文件

  【3】原型:char*gets(char*buffer);

  【4】功能:从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取(接受)的换行符被转换为null值,并由此来结束字符串。

  【5】返回值:读入成功,返回与参数buffer相同的指针;读入过程中遇到EOF(End-of-File)或发生错误,返回NULL指针。所以在遇到返回值为NULL的情况,要用ferror或feof函数检查是发生错误还是遇到EOF。

  【6】注意:本函数可以无限读取,不会判断上限,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值,为了避免这种情况,我们可以用fgets()来替换gets()。这个事实导致gets函数只适用于玩具程序。在V7的手册(1979年)中说明:为了向后兼容,gets删除换行符,gets并不将换行符存入缓冲区。

========================================================

【1】scanf() 会忽略行开头的所有空格,并以空格、换行符结束输入;

  使用getchar()读取scanf语句执行后,缓冲区留下的换行符,

  gets读入以任何字符开始的字符串,以换行符结束,但之后会丢弃换行符并以’\0’代替;

【2】在数据大量的情况下,用gets读取快于scanf()10倍以上(注:来自pudn,只有一段开头话)

【3】第一:要注意不同的函数是否接受空格符、是否舍弃最后的回车符的问题!
读取字符时:
scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
getchar()以Enter结束输入,也不会舍弃最后的回车符;
读取字符串时:
scanf()以Space、Enter、Tab结束一次输入
gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!

   第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:

方法1:C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
这个函数是fflush(stdin)。
方法2:自己取出缓冲区里的残留数据。
scanf(“%[^\n]”,string);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值