声明:摘选自“ 算法竞赛入门经典(第2版)”作者: 刘汝佳 / 陈锋 ISBN:9787302291077
谜题
有一个5 * 5的网格,其中恰好有一个格子是空的,其他格子各有一个字母。一共有4种指令:A,B,L,R,分别表示把空格上,下,左,右的相邻字母移到空格中。输入初始网格和指令序列(以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出“这个拼图没有最终的配置。”,例如,图左中执行ARRBBL0后,效果如图右所示。
解题思路
其实只要利用的getchar()循环读入字符,然后将其按照5×5的格式存放在二维字符数组,然后记录空格的位置,再根据就输入的命令将空格与对应的字符交换值即可:
#include<stdio.h>
#include<string.h>
char s[6][6]; //定义一个存储字母的二维字符串数组
int main()
{
char c, comd; //c用于存放读取的字符,comd用于存放读取的命令字符
int i=0, j=0, x, y; //i,j用于记录网格的坐标,x,y用于记录空格的坐标
while((c = getchar()) !='0') //循环读取字符 ,当输入‘0’时停止循环
{
if(c != '0') s[i][j] = c; //因为停止命令是‘0’,我们必须判断是否将‘0’读入了,如果读入,则不会将其放入数组s[][]
if(c == ' ') //如果读入的是空格,用x,y记录其坐标
{
x = i;
y =j ;
}
j ++; //s[i][j]向右移动一位进行记录
if(j==5) //当s[i][j]第一行存储满了之后,向下移动一位
{
i ++;
j = 0;
}
}
for(int m=0; m<5; m++) //将读入的字符按照5*5格式打印
{
for(int n=0; n<5; n++)
{
printf("%c ", s[m][n]);
if(n==4) printf("\n");
}
}
while((comd=getchar()) != '0') //循环读入命令字符,遇到‘0’停止读取,结束循环
{
if(comd == 'A') //向上移动空格
{
s[x][y] = s[x-1][y];
s[x-1][y] = ' ';
x = x-1;
}
else if(comd == 'B') //向下移动空格
{
s[x][y] = s[x+1][y];
s[x+1][y] = ' ';
x = x+1;
}
else if(comd == 'R') //向右移动空格
{
s[x][y] = s[x][y+1];
s[x][y+1] = ' ';
y = y+1;
}
else if(comd == 'L') //向左移动空格
{
s[x][y] = s[x][y-1];
s[x][y-1] = ' ';
y = y-1;
}
else //输入非法字符时输出
{
printf("This puzzle has no final configuration.");
return 0;
}
}
printf("\n"); //换行,以便分辨原始数组与处理后的数组
for(int m=0; m<5; m++) //将处理后的字符按照5*5格式打印
{
for(int n=0; n<5; n++)
{
printf("%c ", s[m][n]);
if(n==4) printf("\n");
}
}
}
效果图如下: