利用栈数据结构彻底搞定走迷宫案例解析(并非最短路径)

**先上迷宫图
这里写图片描述
迷宫数据图我们分0 1 -1 三种可能 0表示可以走白色表示 1表示障碍物 -1表示已经走过
这里写图片描述
方位规则设置:
这里写图片描述
方位也就是我们下面的di的取值为0 1 2 3 这四个方位 表示当前格子可行走的方位
迷宫算法分析:
这里写图片描述
刚开始的时候我们是有迷宫起点也就是(i,j)是当前起点方块
并且还没有找到当前方块的下一个行走方位,我们根据上面的介绍我们知道方位根据顺时针开始标号为0 1 2 3,刚好是个十字架。因此这个时候我们还没有下步方位的话就设置di = -1; 表示还没有下个行走路线。
然后我们把当前方块入栈 也就是i , j -1
这里写图片描述

如果我们找到了当前方块的下个行走方位对应的方块,那么我们就把当前方块的方位给di保存。继续把下个行走方块入栈。

但是路不是一帆风顺的。我们在走的时候也许当前方块附近全部是障碍物也可以啊,那么我们怎么办,如果你进了死胡同咋办,肯定是回到以前的路,并且从没有走的一个出口继续走。那么原先走过的路我们怎么去找,计算机和我们人不同,你不保存以前走过的路,是不会像人一样自动回到过去的路的,我们这个是用了栈数据结构已经把走过的全部方块入栈了,那么我们想回退就把当前走不通的路出栈就可以啊,这样下次出栈就是上次走的方块,这个时候我们就可以以当前方块寻找其他方位有没有通路的情况。当然既然我已经把入栈过的方块出栈了,那么我们是不是要标志一下设置为0呢,这个意思就表示下次也许我用其他路径是可以走的。
记住我假如把当前行走的方块入栈后,我会把当前方块对应的值设置为-1 表示这个方块已经走了,不能在走了。
大家主要学习思路即可

// 利用栈数据结构走迷宫.cpp: 定义控制台应用程序的入口点。
#include "stdafx.h"
#define  MaxSize 64   //64就够了后面的路径最多把除了墙以外的全部存进来
#define  M 8          //地图行
#define  N 8          //地图列
//全局变量地图数组  我们在外面一层设置为1是墙。  规则0表示可以行走的方块 1是障碍物 
//后面我们还会设置地图的值为-1标志我们已经走过,以免重复走进入死循环
int MG[M + 2][N + 2] =
{
    { 1,1,1,1,1,1,1,1,1,1 },
    { 1,0,0,1,0,0,1,0,1,1 },
    { 1,0,0,0,0,1,0,0,1,1 },
    { 1,0,0,0,0,1,0,1,1,1 },
    { 1,1,1,1,0,0,0,0,1,1 },
    { 1,0,0,0,0,0,1,0,0,1 },
    { 1,0,1,1,0,0,0,0,0,1 },
    { 1,0,0,0,0,1,1,0,1,1 },
    { 1,0,0,1,0,1,0,0,0,1 },
    { 1,1,1,1,1,1,1,1,1,1 }
};

//地宫格子对应的数据类型设计
typedef struct
{
    int i;  //当前方块的行号
    int j;  //当前方块的列号
    int di; //是下一可行走相邻方位的方位号 可取 0 1 2 3
}Box;
//迷宫对应的栈数据结构类型设计
typedef struct
{
    Box data[MaxSize]; //可以用来保存我们的行走路径点或者叫可以走的白色方块数据
    int top;           //栈顶指针
} StType;              //定义顺序栈类型
//迷宫数据类型设计  我们假如迷宫的行和列是M = 8,N = 8
//我们还会在外面设计一层墙因此加上2侧的围墙数组行的元素个数是M+2
//我们规定MG[x][y] = 0表示这个格子可以行走,为1表示是障碍物
//MG[x][y] = -1,表示当前格子已经走过
//用栈求一条走迷宫的路径算法  起点start(xi,yi)->end(xe,ye)
//迷宫数组MG[M+2][N+ 2]
bool MGPath(int xi, int yi, int xe, int ye)
{
    //定义需要用到的一些初始化变量    find用来标识我们是不是找到了当前方块走向下个方块:规则0没有找到 1找到
    int i, j, di, find;

    //定义栈,并初始化栈数据结构
    StType st;
    st.top = -1; //栈顶指针初始化为-1
    //先开始把迷宫起点的方块数据入栈
    st.top++;  //入栈前先栈顶指针+1
    //开始真正入栈方块
    st.data[st.top].i = xi;
    st.data[st.top].j = yi;
    st.data[st.top].di = -1;
    MG[xi][yi] = -1; //是地图的数组数据  表示当前的格子已经走过,下次就不要在走了

    //使用循环判断当前入栈的方块是不是就是我们要的终点数据
    while (st.top > -1) //栈里有方块才有出栈操作  
    {
        //得到栈顶的方块数据
        i = st.data[st.top].i;
        j = st.data[st.top].j;
        di = st.data[st.top].di;
        //比较是不是到了终点
        if (i == xe && j == ye) //找到了出口,输出路径
        {
            printf("(特别提示由于我们的路径是用栈保存,因此输出的路径是从终点到起点)\n迷宫路径如下:\n");
            int k = 0;
            //用一个死循环来输出我们的迷宫行走方块路径坐标
            while (true)
            {
                if (st.top == -1) break;  //当栈为空的时候就表示没有方块数据了 直接退出即可

                k++; //就是用换行用 没有其他作用
                //输出方块对应地图中的坐标
                printf("\t(%d,%d)", st.data[st.top].i, st.data[st.top].j);
                if (k% 5 == 0) //每输出5个方块换一行
                {
                    printf("\n");
                }
                st.top--; //由于栈顶方块路径已经输出,那么就出栈当前的一个方块,让指针指向下个方块路径继续循环输出
            }           
            printf("\n");  //换行
            return true; //找到了一条路径就退出循环
        }
        //开始寻找当前方块的下个可走的方块是什么
        find = 0; //初始化为没有找到
        //注意di初始是-1的  因为还没有找到下个方位
        while (di < 4 && find == 0) //为设么加find必须== 0这个是我们只要找到下个方位就没有必要在找了
        {
            di++; //当前方块di = -1的  我们这个保证di依次从0到3可以得到当前方块的4个方位的方块
            switch (di)
            {
            case 0:
                //注意:由于我们当前的方块是入栈的,因此我们想要得到当前方块的上下左右4个方位的话,
                //直接通过栈里的数据来得到   当然我们这里是0方位 表示我们需要得到当前方块的上一个方块的坐标i和j,后面用来测试是不是可以行走
                i = st.data[st.top].i - 1;j = st.data[st.top].j;   
                break;
            case 1:
                //得到当前行走方块的右方块的坐标i和j
                i = st.data[st.top].i;j = st.data[st.top].j + 1;
                break;
            case 2:
                //得到当前行走方块的下方块的坐标i和j
                i = st.data[st.top].i + 1;j = st.data[st.top].j;
                break;
            case 3:
                //得到当前行走方块的左方块的坐标i和j
                i = st.data[st.top].i;j = st.data[st.top].j - 1;
                break;
            default:
                break;
            }
            if (MG[i][j] == 0)   //上面已经得到了i,j,我们这里就直接判断对应坐标在地图中是不是可以行走
            {
                //说明当前格子是可以行走的
                find = 1; //设置标志位
            }//找到了下个可走的相邻方块(i,j)
        }

        if (find == 1) //找到了下个可走的相邻方块(i,j)
        {
            //进行入栈操作   我们是只要找到可行走方块就会入栈
            st.data[st.top].di = di; //设置当前方块的方位di值  注意我们的di是上面得到的
            //下面是当前方块可行走的下个方块的入栈操作
            st.top++;                //栈指针+1   
            st.data[st.top].i = i;
            st.data[st.top].j = j;
            st.data[st.top].di = -1;  //表示下个方位还没找到
            MG[i][j] = -1;    //避免重复行走
        }
        else   //没有路径可以行走
        {
            MG[st.data[st.top].i][st.data[st.top].j] = 0; //让当前方块下次可以行走
            st.top--;    //出栈方块
        }

    }
    return false;  //表示没有可走路径
}
int main()
{

    if (!MGPath(1, 1, M, N )) //返回值为false表示没有找到迷宫路径
    {
        printf("迷宫没有路\n");
    }
    return 0;
}

测试结果如图;
这里写图片描述
注意由于我们是用栈保存的行走方块,栈是先进后出,所以我们输出的路径点是从路径的终点到起点**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你一身傲骨怎能输

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值