题目:
题目翻译: 这个原题实在是太长了,就直接上图片了,我们一起翻译一下:
Puzzle :谜题 ,有一个5*5的方格其中恰好有一个格子是空的,其他各自各有一个字母。一共有4种指令:A,B,L,R ,分别表示把空格上,下,左,右的相邻字母移动到空格中。输入初始网格和指令序列(以零结束),输出执行完之后的网格,如果有非法指令,应输出:This puzzle has no final configuration. 其中,注意本题输出格式,每个结果之间有换行,每个字母之间有一个空格。
题目解析:
本题最难的部分就是读取指令和解析指令指令了。
如果用gets,优点是能够忽略换行带来的影响,缺点是一句指令可能用换行隔开了。在处理指令的时候就不容易了。
如果用getchar,多多少少会吃掉或者少读取一些字符,但是,这样读取来的指令容易处理。所以综合情况,在读取初始网格的时候,我选择用gets(可以忽略换行),在读取指令的时候选择getchar(要把所有的指令读进去)。
部分代码解析:
int judge(char puzz[7][7] ,char ch){//找到空格的位置int i,j,flag=0;char temp;for(i=0;i<5;i++){for(j=0;j<5;j++)if(puzz[i][j]==' ') {flag=1;break;}if(flag) break;}if(ch=='A'&&i-1>=0) {temp=puzz[i][j];puzz[i][j]=puzz[i-1][j];puzz[i-1][j]=temp;i--;return 1;}else if(ch=='B'&&i+1<=4) {temp=puzz[i][j];puzz[i][j]=puzz[i+1][j];puzz[i+1][j]=temp;i++;return 1;}else if(ch=='L'&&j-1>=0) {temp=puzz[i][j];puzz[i][j]=puzz[i][j-1];puzz[i][j-1]=temp;j--; return 1;}else if(ch=='R'&&j+1<=4) {temp=puzz[i][j];puzz[i][j]=puzz[i][j+1];puzz[i][j+1]=temp;j++; return 1;}else if(ch=='') return 1;else if(ch=='0') return 0;else return 2;}
这个函数是用来处理解析指令,并且返回是否结束或者是不是无效的指令,因为指令中只有'A','B','L','R','','0',这个几个字符,如果是返回2,说明指令移动导致数组越界了,如果返回0,则代表指令读取完成,如果返回1,则继续读取下一个字符。
while(1){ch=getchar(); //读取指令flag=judge(puzz,ch);if(flag==0||flag==2) break;}if(flag==2){while((ch=getchar())!='0') ;}ch=getchar(); //吸收回车if(flag!=2){if(k>0) printf("");printf("Puzzle #%d:",++k);for(i=0;i<5;i++){printf("%c",puzz[i][0]);for(j=1;j<5;j++)printf(" %c",puzz[i][j]);printf("");}}else {if(k>1) printf("");printf("Puzzle #%d:This puzzle has no final configuration.",++k);}
这段代码是main函数里的,主要是读取读取,和控制输出,因为在OJ(在线测评)的时候,格式是非常严格的,题目要求,每种情况之间有换行,但是最后一个输出,必须以结束,如果直接在输出后面加,这样在最后一个输出的时候格式就会出错,但是,如果我们在最前面输出的的时候,第一个输出格式又不对,所以,这里用K>0来,表示从一个输出以后要在最前面加,这个问题就解决了。还有应该注意那个吸收回车的效果,因为在读取完指令指令之后,是由一个换行的,
while((ch=getchar())!='0') ;这句代码是遇到非法指令,之后要把这个指令全部读取,以免影响后面的读取网格。
完整代码:
#include #define row 7#define line 7int judge(char puzz[7][7] ,char ch){//找到空格的位置int i,j,flag=0;char temp;for(i=0;i<5;i++){for(j=0;j<5;j++)if(puzz[i][j]==' ') {flag=1;break;}if(flag) break;}if(ch=='A'&&i-1>=0) {temp=puzz[i][j];puzz[i][j]=puzz[i-1][j];puzz[i-1][j]=temp;i--;return 1;}else if(ch=='B'&&i+1<=4) {temp=puzz[i][j];puzz[i][j]=puzz[i+1][j];puzz[i+1][j]=temp;i++;return 1;}else if(ch=='L'&&j-1>=0) {temp=puzz[i][j];puzz[i][j]=puzz[i][j-1];puzz[i][j-1]=temp;j--; return 1;}else if(ch=='R'&&j+1<=4) {temp=puzz[i][j];puzz[i][j]=puzz[i][j+1];puzz[i][j+1]=temp;j++; return 1;}else if(ch=='') return 1;else if(ch=='0') return 0;else return 2;}int main(){char puzz[row][line];int i,j,flag=1,k=0;char ch;freopen("1.txt","r",stdin);while(1){//读取5*5方格数for(i=0;i<5;i++)gets(puzz[i]);//判断是否结束if(puzz[0][0]=='Z') break;//读取指令while(1){ch=getchar(); //读取指令flag=judge(puzz,ch);if(flag==0||flag==2) break;}if(flag==2){while((ch=getchar())!='0') ;}ch=getchar(); //吸收回车if(flag!=2){if(k>0) printf("");printf("Puzzle #%d:",++k);for(i=0;i<5;i++){printf("%c",puzz[i][0]);for(j=1;j<5;j++)printf(" %c",puzz[i][j]);printf("");}}else {if(k>1) printf("");printf("Puzzle #%d:This puzzle has no final configuration.",++k);}}return 0;}
个人总结:
- 这个题目刚开始看感觉很难,后来一点点的完成发现也就那样,所以,我们要要善于把大问题分解为多个简单的小问题
- 领会本题控制输出,以及读取字符的骚操作。用getchar的时候,要注意,它会不会吃掉对于的字符
- 最后附上我挣扎一天的结果:
在经过N次失败之后,AC的感觉是一种谁不出来喜悦,这也是学编程的乐趣吧,那种成就感,让人越来越自信!加油,继续努力。