**先上迷宫图
迷宫数据图我们分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;
}
测试结果如图;
注意由于我们是用栈保存的行走方块,栈是先进后出,所以我们输出的路径点是从路径的终点到起点**