题目名称:谜题
题目描述:
有一个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);