Description
有一个 10 x 10 的迷宫,起点是‘S’,终点是‘E’,墙是‘#’,道路是空格。一个机器人从起点走到终点。当机器人走到一个通道块,前面已经没有路可走时,它会转向到当前面向的右手方向继续走。如果机器人能够过,则留下足迹‘*’,如果走不通,则留下标记‘!’。下面给出书中的算法,请你模拟机器人的走法输出最终的状态。
Input
Output
Sample Input
##########
#S # # #
# # # #
# ## #
# ### #
# # #
# # # #
# ### ## #
## E#
##########
Sample Output
##########
#**#!!!# #
# *#!!!# #
#**!!## #
#*### #
#***# #
# #***# #
# ###*## #
## ****#
##########
OK,本题是迷宫的简化版本,不需要找最短路径,不需要找所有路径,只需要按照机器人的行走规则走到终点即可。
首先,我们要分析数据类型的建立。
机器人在行走过程中,我们需要知道的信息有 1,当前位置坐标 2,当前机器人面朝方向。
因此,我们创建数据类型Maze
typedef struct Maze{ int x; int y;//坐标 int dir; //面向方向 }Maze;
其次,输入数据是一个二维字符数组,为方便操作,我们将迷宫信息转化成为一个二维数组,我们先约定
方向 : 右 1 下 2 左 3 上 4 (顺时针)
7 代表入口 8 代表出口 5 代表走过的通道块 6 代表走过又退回的通道块
1 代表墙 0 代表可以通过
做完这些,然后我们分析解题思路:
1,读入数据,将其转化为二维数组。
2,获取起点和终点坐标(注意每次给的起点和终点并不一样,所以需要寻找),将起点坐标压栈,进入循环,开始走迷宫
3,每次循环先判断机器人面朝的方向dir,然后判断前方可否通过
1)如果可以通过,将当前坐标数值置为5,然后将下一个要走的坐标压栈,然后将方向重置为1!(每进入一个新的通道 块,都需要朝向1,才能达到寻找所有的方向的效果)!
2)如果不能通过,转向。dir+=1;
方向是1的时候的代码:
if(seat.dir==1) { if(a[seat.x][seat.y+1]==0) { a[seat.x][seat.y+1]=5; seat.y+=1; seat.dir=1;//每进入一个新的通道块 都需要面朝1 push(&S,seat); continue; } else { seat.dir=seat.dir+1;//转向 continue; } }
3)重点是,方向为4的时候,说明这个通道块前三个方向都不通,如果此时第四个也不通,则弹栈并将该位置置为6,表示走不通。弹栈后,将栈顶坐标方向置为1,然后继续拿来循环
方向为4的代码
if(seat.dir==4) { if(a[seat.x-1][seat.y]==0) { a[seat.x-1][seat.y]=5; seat.x-=1; seat.dir=1; push(&S,seat); continue; } else { pop(&S,&out);//退栈 a[out.x][out.y]=6;//标记不通 seat.x=( (S.top)-1)->x; seat.y=( (S.top)-1)->y; seat.dir=1;//栈顶坐标方向置为1 continue; } }
4) 每次循环结束后,判断坐标是否等于出口坐标,若等于,说明迷宫结束。
4,将二维数组转化为二维字符数组,打印输出。6对应! 5对应* 1对应# 0对应空格
解题思路可以对照坐标图,自己走一遍循环流程
具体代码如下:
代码中寻找起点终点的操作用的是遍历整个数组,这一点可以优化,有空再改吧。
#include<stdio.h> #include<string.h> #include<malloc.h> typedef struct Maze{ int x; int y;//坐标 int dir; //面向方向 }Maze; typedef struct node{ Maze *base; Maze *top; }Sqtack; void Input(int a[15][15]); void Output(int a[15][15]); void Initstack(Sqtack *L); int push(Sqtack *S,Maze elem); int pop(Sqtack *S,Maze *seat); //方向 右1 下2 左3 上4 顺时针 //7代表入口 8代表出口 5代表走过的坐标 6代表走过又退回的坐标 // 1代表墙 0代表可以通过 int main() { int a[15][15]; int Fx,Fy; Input(a); //找到起点 for(int i=0;i<10;i++) for(int j=0;j<10;j++) if(a[i][j]==7) { Fx=i; Fy=j; a[i][j]=0; } Sqtack S; Initstack(&S); Maze seat,out; seat.dir=1; seat.x=Fx; seat.y=Fy; a[seat.x][seat.y]=5; push(&S,seat); //找到终点 for(int i=0;i<10;i++) for(int j=0;j<10;j++) if(a[i][j]==8) { Fx=i; Fy=j; a[i][j]=0; } while(seat.x!=Fx||seat.y!=Fy) { if(seat.dir==1) { if(a[seat.x][seat.y+1]==0) { a[seat.x][seat.y+1]=5; seat.y+=1; seat.dir=1;//每进入一个新的通道块 都需要面朝1 push(&S,seat); continue; } else { seat.dir=seat.dir+1;//转向 continue; } } if(seat.dir==2) { if(a[seat.x+1][seat.y]==0) { a[seat.x+1][seat.y]=5; seat.x+=1; seat.dir=1; push(&S,seat); continue; } else { seat.dir=seat.dir+1;//转向 continue; } } if(seat.dir==3) { if(a[seat.x][seat.y-1]==0) { a[seat.x][seat.y-1]=5; seat.y-=1; seat.dir=1; push(&S,seat); continue; } else { seat.dir=seat.dir+1;//转向 continue; } } if(seat.dir==4) { if(a[seat.x-1][seat.y]==0) { a[seat.x-1][seat.y]=5; seat.x-=1; seat.dir=1; push(&S,seat); continue; } else { pop(&S,&out);//退栈 a[out.x][out.y]=6;//标记不通 seat.x=( (S.top)-1)->x; seat.y=( (S.top)-1)->y; seat.dir=1;//栈顶坐标方向置为1 continue; } } } Output(a); } void Input(int a[15][15])//读入数据 { char ch[15]; for(int i=0;i<10;i++) { gets(ch); int l=strlen(ch); for(int j=0;j<10;j++) { if(ch[j]==' ') { a[i][j]=0; } if(ch[j]=='#') { a[i][j]=1; } if(ch[j]=='S') { a[i][j]=7; } if(ch[j]=='E') { a[i][j]=8; } } } } void Output(int a[15][15])//打印结果 { for(int i=0;i<10;i++) { for(int j=0;j<10;j++) { if(a[i][j]==1) { printf("#"); } if(a[i][j]==0) { printf(" "); } if(a[i][j]==5) { printf("*"); } if(a[i][j]==6) { printf("!"); } } if(i!=9) printf("\n"); } } void Initstack(Sqtack *S)//初始化 { S->base=(Maze *)malloc(500*sizeof(Maze)); S->top=S->base; } int push(Sqtack *S,Maze seat)//压栈 { *(S->top)=seat; S->top+=1; } int pop(Sqtack *S,Maze *out)//弹栈 { if(S->base==S->top) { return -1; } else { S->top-=1; *out=*(S->top); *out=*(S->top); } }