#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>
///本题我采取队列查询迷宫路径,也同时是最短路径
#define N 5///定义要多大的迷宫
#define OK 1
#define ERROR 0
int maze[N+2][N+2],mark[N+2][N+2];///+2是因为当做墙用的
int move[4][2]={1,0,-1,0,0,1,0,-1};///这个是移动东南西北的方向时候使用的
struct node///左边的结构体
{
int x,y;
}way[N],pre[N][N],begin,end,temp;///way是用来输出路径,pre是每一步的前一步
///链式队列
typedef struct Que
{
struct node path;///路径记录
struct Que *next;
}quelink;
typedef struct
{
quelink *front;///队首
quelink *rear;///队尾
}LinkQueue;
int init_queue(LinkQueue *);///初始化队列
int push_queue(LinkQueue *,struct node );///入队
int pop_queue(LinkQueue *);///出队
int Front_queue(LinkQueue ,struct node *);///查询队首
int empty_queue(LinkQueue );///判断队列是否为空
void creatMaze()///随机生成一个迷宫的函数
{
int i,j;
for(i=0;i<N+2;i++)
{
maze[0][i]=1;
maze[N+1][i]=1;
maze[i][0]=1;
maze[i][N+1]=1;
}
srand(time(NULL));
for(i=1;i<=N;i++)
for(j=1;j<=N;j++)
maze[i][j]=rand()%2;
maze[1][1]=maze[N][N]=0;
}
///查找迷宫的出路,并记录路径的函数
void findmaze()
{
int i,top;
LinkQueue Q;
memset(mark,0,sizeof(mark));///初始化mark数组,都是为0,意思这些地方都没有经过
init_queue(&Q);///初始化队列
begin.x=1;begin.y=1;///起点是(1,1)
end.x=N;end.y=N;///终点是(N,N)
struct node now;///now是查找过程使用的
push_queue(&Q,begin);///把起点存进队列
mark[begin.x][begin.y]=1;///起点走过了标记为1
while(!empty_queue(Q))///判断队列是否为空的
{
Front_queue(Q,&now);///查询队首,队首就赋值到了now
pop_queue(&Q);///查询完,使用完之后就出队
if(now.x==end.x&&now.y==end.y)///如果走到终点了,也就是结束了,并把路径进行输出
{
top=0;///初始化top
while(1)
{
way[top++]=now;///一开始就是终点,
if(now.x==begin.x&&now.y==begin.y)///输出到起点也就是说路径都存好到数组里了
break;///跳出
now=pre[now.x][now.y];///pre就是我说的,终点的前一步就是靠pre数组存起来的,然后它的上一步pre也存好了,我的思路就是基于此的,
}
while(top--&&top>0)///我们是倒着存入路径,那这样就可以正确输出路径了
printf("(%d,%d)->",way[top].x,way[top].y);
printf("(%d,%d)\n",way[0].x,way[0].y);
return ;///结束并返回
}
for(i=0;i<4;i++)///朝这着东西南北走
{
temp.x=now.x+move[i][0];///now是目前的位置,上面开了数组move就是用来移动方向,东南西北方向都进行移动
temp.y=now.y+move[i][1];///而这都基于now这步走的
if((!mark[temp.x][temp.y])&&maze[temp.x][temp.y]==0)///如果哪个方向可走,并且还没走过就可以进入这个条件
{
pre[temp.x][temp.y]=now;///temp是基于now移动的,那么now就是temp的前一步,到时候输出存路径的时候需要
mark[temp.x][temp.y]=1;///这个位置走过了就标记为1
push_queue(&Q,temp);///并且把这步存入到队列里,我们下次会基于这一步再去查找别的路线
}
}
if(empty_queue(Q))///如果队列是空的,说明根本没有能走到终点的路径
puts("无解");///输出无解
}
}
int main()
{
int i,j;
creatMaze();
for(i=0;i<N+2;i++)
{
for(j=0;j<N+2;j++)
printf("%d ",maze[i][j]);
puts("");
}
findmaze();
return 0;
}
///初始化队列
int init_queue(LinkQueue *Q)
{
Q->front=Q->rear=(quelink *)malloc(sizeof(quelink));///初始化队列,并让front和rear都指向同一个地方,并申请一个空间
if(!Q->front)///如果申请失败返回ERROR
return ERROR;
Q->front->next=NULL;///让他们的next指向NULL
return OK;///初始化成功返回OK
}
///入队
int push_queue(LinkQueue *Q,struct node t)
{
quelink *p;
p=(quelink *)malloc(sizeof(quelink));
if(!p)
return ERROR;
p->path=t;///把路径赋值给p
p->next=NULL;///让它的next指向NULL
Q->rear->next=p;///入队之后,rear的next就指向p,rear第一个类似头结点不使用的
Q->rear=p;///跟链表的尾插法一样,让rear指向p
return OK;
}
///出队
int pop_queue(LinkQueue *Q)
{
quelink *p;
if(Q->front==Q->rear)///rear和front指向同一个位置也就是队列是空的
return ERROR;///出队失败返回ERROR
p=Q->front->next;///front的第一个也是不存数据的,它的next才是存数据的
Q->front->next=p->next;///p-next这时候是front的next的next 让front的next指向它,也就是把front的next跳过了,达到了转移
if(Q->rear==p)///如果队列只剩一个的元素的话,出队之后队列肯定是空的,那就让它指向front,下次判断的时候就知道它是空的了
Q->rear=Q->front;
free(p);///释放了p的空间
return OK;///出队成功返回OK
}
///查询队首
int Front_queue(LinkQueue Q,struct node *t)
{
if(Q.front==Q.rear)///如果指向一起说明队列是空的
return ERROR;///空的并返回ERROR
*t=Q.front->next->path;///把队首元素赋值给t,t进行返回
return OK;///查询成功返回OK
}
///判断队列是否为空的
int empty_queue(LinkQueue Q)
{
if(Q.front==Q.rear)///如果rear和front指向一起,说明队列是空的
return OK;///队列是空的,返回OK
return ERROR;///不是空的返回ERROR
}
#include<time.h>
#include<stdlib.h>
#include<string.h>
///本题我采取队列查询迷宫路径,也同时是最短路径
#define N 5///定义要多大的迷宫
#define OK 1
#define ERROR 0
int maze[N+2][N+2],mark[N+2][N+2];///+2是因为当做墙用的
int move[4][2]={1,0,-1,0,0,1,0,-1};///这个是移动东南西北的方向时候使用的
struct node///左边的结构体
{
int x,y;
}way[N],pre[N][N],begin,end,temp;///way是用来输出路径,pre是每一步的前一步
///链式队列
typedef struct Que
{
struct node path;///路径记录
struct Que *next;
}quelink;
typedef struct
{
quelink *front;///队首
quelink *rear;///队尾
}LinkQueue;
int init_queue(LinkQueue *);///初始化队列
int push_queue(LinkQueue *,struct node );///入队
int pop_queue(LinkQueue *);///出队
int Front_queue(LinkQueue ,struct node *);///查询队首
int empty_queue(LinkQueue );///判断队列是否为空
void creatMaze()///随机生成一个迷宫的函数
{
int i,j;
for(i=0;i<N+2;i++)
{
maze[0][i]=1;
maze[N+1][i]=1;
maze[i][0]=1;
maze[i][N+1]=1;
}
srand(time(NULL));
for(i=1;i<=N;i++)
for(j=1;j<=N;j++)
maze[i][j]=rand()%2;
maze[1][1]=maze[N][N]=0;
}
///查找迷宫的出路,并记录路径的函数
void findmaze()
{
int i,top;
LinkQueue Q;
memset(mark,0,sizeof(mark));///初始化mark数组,都是为0,意思这些地方都没有经过
init_queue(&Q);///初始化队列
begin.x=1;begin.y=1;///起点是(1,1)
end.x=N;end.y=N;///终点是(N,N)
struct node now;///now是查找过程使用的
push_queue(&Q,begin);///把起点存进队列
mark[begin.x][begin.y]=1;///起点走过了标记为1
while(!empty_queue(Q))///判断队列是否为空的
{
Front_queue(Q,&now);///查询队首,队首就赋值到了now
pop_queue(&Q);///查询完,使用完之后就出队
if(now.x==end.x&&now.y==end.y)///如果走到终点了,也就是结束了,并把路径进行输出
{
top=0;///初始化top
while(1)
{
way[top++]=now;///一开始就是终点,
if(now.x==begin.x&&now.y==begin.y)///输出到起点也就是说路径都存好到数组里了
break;///跳出
now=pre[now.x][now.y];///pre就是我说的,终点的前一步就是靠pre数组存起来的,然后它的上一步pre也存好了,我的思路就是基于此的,
}
while(top--&&top>0)///我们是倒着存入路径,那这样就可以正确输出路径了
printf("(%d,%d)->",way[top].x,way[top].y);
printf("(%d,%d)\n",way[0].x,way[0].y);
return ;///结束并返回
}
for(i=0;i<4;i++)///朝这着东西南北走
{
temp.x=now.x+move[i][0];///now是目前的位置,上面开了数组move就是用来移动方向,东南西北方向都进行移动
temp.y=now.y+move[i][1];///而这都基于now这步走的
if((!mark[temp.x][temp.y])&&maze[temp.x][temp.y]==0)///如果哪个方向可走,并且还没走过就可以进入这个条件
{
pre[temp.x][temp.y]=now;///temp是基于now移动的,那么now就是temp的前一步,到时候输出存路径的时候需要
mark[temp.x][temp.y]=1;///这个位置走过了就标记为1
push_queue(&Q,temp);///并且把这步存入到队列里,我们下次会基于这一步再去查找别的路线
}
}
if(empty_queue(Q))///如果队列是空的,说明根本没有能走到终点的路径
puts("无解");///输出无解
}
}
int main()
{
int i,j;
creatMaze();
for(i=0;i<N+2;i++)
{
for(j=0;j<N+2;j++)
printf("%d ",maze[i][j]);
puts("");
}
findmaze();
return 0;
}
///初始化队列
int init_queue(LinkQueue *Q)
{
Q->front=Q->rear=(quelink *)malloc(sizeof(quelink));///初始化队列,并让front和rear都指向同一个地方,并申请一个空间
if(!Q->front)///如果申请失败返回ERROR
return ERROR;
Q->front->next=NULL;///让他们的next指向NULL
return OK;///初始化成功返回OK
}
///入队
int push_queue(LinkQueue *Q,struct node t)
{
quelink *p;
p=(quelink *)malloc(sizeof(quelink));
if(!p)
return ERROR;
p->path=t;///把路径赋值给p
p->next=NULL;///让它的next指向NULL
Q->rear->next=p;///入队之后,rear的next就指向p,rear第一个类似头结点不使用的
Q->rear=p;///跟链表的尾插法一样,让rear指向p
return OK;
}
///出队
int pop_queue(LinkQueue *Q)
{
quelink *p;
if(Q->front==Q->rear)///rear和front指向同一个位置也就是队列是空的
return ERROR;///出队失败返回ERROR
p=Q->front->next;///front的第一个也是不存数据的,它的next才是存数据的
Q->front->next=p->next;///p-next这时候是front的next的next 让front的next指向它,也就是把front的next跳过了,达到了转移
if(Q->rear==p)///如果队列只剩一个的元素的话,出队之后队列肯定是空的,那就让它指向front,下次判断的时候就知道它是空的了
Q->rear=Q->front;
free(p);///释放了p的空间
return OK;///出队成功返回OK
}
///查询队首
int Front_queue(LinkQueue Q,struct node *t)
{
if(Q.front==Q.rear)///如果指向一起说明队列是空的
return ERROR;///空的并返回ERROR
*t=Q.front->next->path;///把队首元素赋值给t,t进行返回
return OK;///查询成功返回OK
}
///判断队列是否为空的
int empty_queue(LinkQueue Q)
{
if(Q.front==Q.rear)///如果rear和front指向一起,说明队列是空的
return OK;///队列是空的,返回OK
return ERROR;///不是空的返回ERROR
}