迷宫问题(C语言实现)

问题描述

定义一个二维数组:

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

思路

  • 首先将迷宫存在一个二位数组中,然后遍历数组,遇到1则改变方向,遇到0接着向下走,将此点存入队列中,如果无路,则返回上一结点,将此结点移出队列,并将此点的数组值更改为1,防止死循环。直至找到出口。
struct path     //定义一个结构体保留遍历到的路径座标
{
    int x;      //横座标
    int y;      //纵座标
    struct path *next;     //实现队列
};
typedef struct Link
{
    struct path *head;       //队列的起始位置
    struct path *rear;       //队列的末尾
}link;
void push(link *que, int x, int y) //实现入队
{
    struct path *temp;
    temp = (struct path*)malloc(sizeof(struct path));
    temp->x = x;       //存入横座标
    temp->y = y;       //存入纵座标
    /*将结点插入到队列的尾部*/
    rear->next = temp;    
    rear = temp;
    rear->next = NULL;
}
void pop(link *que)
{
    struct path *temp;
    temp = (struct path*)malloc(sizeof(struct path));
    temp = rear;
    free(temp);         //将队列尾部移出
}
void pop1(link *que, int *x, int *y)
{
    struct path *temp;
    temp = que->head->next;  //将队列的头结点赋值给temp
    /*移出结点座标*/
    *x = temp->x;
    *y = temp->y; 
    que->head->next = temp->next; //移出temp
}
  • 写好队列的实现后,我们来实现对迷宫的分析
/*用递归对迷宫进行遍历*/
void r(int a[5][5], int x, int y, link *que)
{   
    if( x < 5 && x >= 0 && y < 5 && y >= 0)
    {
        if(x == 4 && y == 4)  //到达迷宫出口
            return;
        /*首先判断右边下一个点是否可以走*/
        if(a[x][y + 1] == 0 && (y + 1) < 5) //此处为了防止数组越界
        {
            y++;
            push(que, x, y);   //可以走就将该结点入队
            r(a, x, y, que);   //递归下一个座标
            return;
        }
        /*上一个条件不满足就判断其向下是否能走*/
        if(a[x + 1][y] == 0 && (x + 1) < 5)//防止数组越界
        {
            x++;
            push(que, x, y);       //入队
            r(a, x, y, que);       //递归
            return;
        }
        /*无路可走,就返回上一个座标*/
        if(a[x - 1][y] == 0 && x - 1 >= 0)
        {
            a[x][y] = 1; //并将该点设为1,防止死循环
            pop(que);    //将该座标移出队列
            x--;
            r(a, x, y, que);
            return;
         }
        if(a[x][y - 1] == 0 && y - 1 >= 0)
        {
            a[x][y] = 1;
            pop(que); //移出队列
            y--;
            r(a, x, y, que);
            return;
        }
    }
}   

总结

1、用到递归和队列的思想,将迷宫当作矩阵,遍历,判断下一个座标是否可以通过,如果不行则换方向,如果无路可走则退格。
2、自己今天有很多思想没有思考到,写一篇博客加深一下印象。

博客如有错误,欢迎大家评论指出,一起探讨一起进步。感谢!!

完整代码

#include<stdio.h>
#include<stdlib.h>

//迷宫问题

struct path
{    
    int x;            //横座标
    int y;            //纵座标
    struct path *next;                                                                                                    
};   

typedef struct Link
{    
    struct path *head;
    struct path *rear;
}link;

void push(link *que, int x, int y)
{    
    struct path *p;
    p = (struct path*)malloc(sizeof(struct path));
    p->x = x;
    p->y = y;
    que->rear->next = p;
    que->rear = p;
    que->rear->next = NULL;
}    

void pop(link *que)
{    
    struct path *temp;
    temp = (struct path*)malloc(sizeof(struct path));
    temp = que->rear;
    free(temp);
    return;
}       
void pop2(link *que, int *x, int *y)
{       
    struct path *temp;
    temp = que->head->next;
    que->head->next = temp->next;      //将temp结点出队
    *x = temp->x;
    *y = temp->y;
    free(temp);
}       

/*用递归对迷宫进行遍历*/
void r(int a[5][5], int x, int y, link *que)
{   
    if( x < 5 && x >= 0 && y < 5 && y >= 0)
    {
        if(x == 4 && y == 4)  //到达迷宫出口
            return;
        /*首先判断右边下一个点是否可以走*/
        if(a[x][y + 1] == 0 && (y + 1) < 5) //此处为了防止数组越界
        {
            y++;
            push(que, x, y);   //可以走就将该结点入队
            r(a, x, y, que);   //递归下一个座标
            return;
        }
        /*上一个条件不满足就判断其向下是否能走*/
        if(a[x + 1][y] == 0 && (x + 1) < 5)//防止数组越界
        {
            x++;
            push(que, x, y);       //入队
            r(a, x, y, que);       //递归
            return;
        }
        /*无路可走,就返回上一个座标*/
        if(a[x - 1][y] == 0 && x - 1 >= 0)
        {
            a[x][y] = 1; //并将该点设为1,防止死循环
            pop(que);    //将该座标移出队列
            x--;
            r(a, x, y, que);
            return;
         }
        if(a[x][y - 1] == 0 && y - 1 >= 0)
        {
            a[x][y] = 1;
            pop(que); //移出队列
            y--;
            r(a, x, y, que);
            return;
        }
    }
}   
int main(void)
{   
    int a[5][5];
    int i, j;
    int x, y;
    for(i = 0; i < 5; i++)
    {  
        for(j = 0; j < 5; j++)
        {
            scanf("%d", &a[i][j]);
        }
    }  
    link *top;
    top = (link *)malloc(sizeof(link));
    top->head = top->rear = (struct path *)malloc(sizeof(struct path));
    r(a, 0, 0, top);
    printf("(0, 0)\n");
    while(top->head->next != top->rear)
    {  
        pop2(top, &x, &y);
        printf("(%d, %d)\n", x, y);
    }
    printf("(4, 4)\n");
    return 0;
}                                                                                                                                  

猜你喜欢

转载自blog.csdn.net/weixin_42250655/article/details/81294176