迷宫问题

本文介绍了一种基于队列实现的迷宫寻路算法,该算法可以找到从起点到终点的最短路径。通过随机生成迷宫并利用东南西北四个方向进行搜索,实现了对迷宫的遍历和路径记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值