我给的建议是,如果你不是很理解这个问题的话,或者完全不懂,那么请进行默读或者朗读,并且边读边想
这里我在网上找了一个视频,有基本思路的讲解,看完可以看以下 的代码讲解
迷宫问题链接
我们将问题分块解释
#include
const int M = 8, N = 8;
const int Maxsize = 200;
using namespace std;
int mg[M + 2][N + 2] =
{
{1,1,1,1,1,1,1,1,1,1},{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},{1,1,1,1,1,1,1,1,1,1}
};
//运用1和0对不可以走和可以走的方块进行标志
typedef struct
{
int i; //当前方块的行号
int j; //当前方块的列号
int di; //di是下一可走相邻方位的方位号
}Box; //定义方块类型
typedef struct
{
Box data[Maxsize];
//因为没走一步相当于进栈,并且要把那个方块的各个性质带到栈中
//所以用上面定义好了的BOX结构体类型来定义数组
int top; //栈顶指针
}StType; //声明顺序栈类型
//初始时,入口(i,j)作为当前方块
//所有走过的方块都会进栈
走迷宫的过程跟进栈出栈一样,移动一个方位就进栈,走不动了,就原路退回,就相当于退栈,所以所以就想到用栈来解决问题。
Box中的di指的是方位,一开始进栈时,它是被初始化为-1的,这表示它还没有进行试探,还没有试探周围那一个方块可以走。
假设上面的方位为0,右为1,下为2,左为3
当开始试探时,就会对di进行赋值,比如上边可以走,那么di就为0,若上边走不通,则试右边,右边走得通,那么di就为1
(这些方位数、时针顺序等都是人为设定的,你也可以自己定义)
void InitStack(StType*& st)
{
st = (StType*)malloc(sizeof(StType));
st->top = -1;
}
bool StackEmpty(StType* s)
{
return (s->top == -1);
}
bool Push(StType*& s, Box e)
{
if (s->top == Maxsize - 1)
return false;
s->top++;
s->data[s->top] = e;
return true;
}
bool GetTop(StType* s, Box& e)
{
if (s->top == -1)
return false;
e = s->data[s->top];
return true;
}
bool Pop(StType*& s, Box& e)
{
if (s->top == -1)
return false;
e = s->data[s->top];
s->top--;
return true;
}
void DestroyStack(StType*& s)
{
free(s);
}
上面这些都是栈的基本操作,后面会用到
我准备了一个有注释的和没注释的代码
//用栈求一条迷宫路径的算法:(xi,yi),(xe,ye)
bool mgpath(int xi, int yi, int xe, int ye)
{
Box path[Maxsize], e;
int i, j, di, i1 = 0, j1 = 0, k;
bool find;
StType* st;
InitStack(st); //初始化栈顶指针
e.i = xi; e.j = yi; e.di = -1;//设置e为入口
Push(st, e); //方块e进栈
mg[xi][yi] = -1;
while (!StackEmpty(st))
{
GetTop(st, e);
i = e.i; j = e.j; di = e.di;
if (i == xe && j == ye)
{
cout << "一条迷宫路径如下:" << endl;
k = 0;
while (!StackEmpty(st))
{
Pop(st, e);
path[k++] = e;
}
while (k >= 1)
{
k--;
cout <<"\t"<<path[k].i << path[k].j;
if ((k + 2) % 5 == 0)
cout << endl;
}
cout << endl;
DestroyStack(st);
return true;
}
find = false;
while (di < 4 && !find)
{
di++;
switch (di)
{
case 0:i1 = i - 1; j1 = j; break;
case 1:i1 = i; j1 = j + 1; break;
case 2:i1 = i + 1; j1 = j; break;
case 3:i1 = i; j1 = j - 1; break;
}
if (mg[i1][j1] == 0)find = true;
}
if (find)
{
st->data[st->top].di = di;
e.i = i1; e.j = j1; e.di = -1;
Push(st, e);
mg[i1][j1] = -1;
}
else
{
Pop(st, e);
mg[e.i][e.j] = 0;
}
}
DestroyStack(st);
return false;
}
接下来将上述代码分段解释
bool mgpath(int xi, int yi, int xe, int ye)
{
Box path[Maxsize], e;
int i, j, di, i1 = 0, j1 = 0, k;
bool find;
StType* st;
InitStack(st); //初始化栈顶指针
e.i = xi; e.j = yi; e.di = -1;//设置e为入口
Push(st, e); //方块e进栈
mg[xi][yi] = -1;
一开始就是这么进栈的,这是第一个元素,并且要注意mg[xi][yi] = -1和di=-1是不同的,前者是表示将迷宫值,也就是开头定义的数组的值其中一个变为-1,让其不能走(只有迷宫值0是可以走的,其它都不可以走),避免走到下一个,又走回来(在有其它路的情况下),也就是为了避免来回循环
后者是表示未试探(上面已经说过)
while (!StackEmpty(st)) //上面有一个入口方块被压入,所以可以进行循环
{
GetTop(st, e); //获取栈顶的元素
i = e.i; j = e.j; di = e.di; //将栈顶方块的元素赋给i,j,di
if (i == xe && j == ye) //判断是否坐标是出口
{
cout << "一条迷宫路径如下:" << endl;
k = 0;
while (!StackEmpty(st))
//不断将元素弹出,只不过最后走的那一步,是最为第一个进入数组path中的
//所以要想要得到从入口到出口的顺序则需将path倒序输出
{
Pop(st, e);
path[k++] = e;
}
while (k >= 1) //这里不是大于等于0,与k++有关,看下句注释即可理解
{
k--; //前面k++每个都多加了一个1,所以每个都得减一
cout <<"\t"<<path[k].i << path[k].j;
if ((k + 2) % 5 == 0) //这是经验值,因为只有在这个迷宫里面才是加二,看下面图片即可知
cout << endl;
}
cout << endl;
DestroyStack(st);
return true;
//完成输出后,因为它是个bool函数,而它的使命就是输出走出迷宫路径,使命完成了,自然就得return
}
这是将这个例子的k值减减后一个个输出的结果,可以发现当k+2等于5的倍数时,就会换一次行,所以输出的是5个5个一行。
find = false; //假设找不到
while (di < 4 && !find)
//两个条件:在找不到的情况下,从0-3一个一个找
//这里的!find也可以在里面换成用break
{
di++;
switch (di)
{
case 0:i1 = i - 1; j1 = j; break;
case 1:i1 = i; j1 = j + 1; break;
case 2:i1 = i + 1; j1 = j; break;
case 3:i1 = i; j1 = j - 1; break;
}
if (mg[i1][j1] == 0)find = true;
//发现如果下一个点位的迷宫值为0,则说明可走,即找到
}
if (find) //如果找到的话,就进行进栈操作,而人也将移动至发现的这个方块
{
st->data[st->top].di = di;
//st指向data,data要di,所以这个代码的意思就是st指向的栈顶数组元素的di
e.i = i1; e.j = j1; e.di = -1;
//把Box中的三项装入e中,后面即可压入栈中
Push(st, e);
mg[i1][j1] = -1; //上面有解释过
}
else //如果不是记得要退栈,并且将退出去的那个元素赋值变回原来的0,这其实就是四面被堵死
{
Pop(st, e);
mg[e.i][e.j] = 0;
}
}
DestroyStack(st);
return false;
}
用循环让其重复进栈出栈的过程,最后看是否能到达出口
int main()
{
if (!mgpath(1, 1, M, N))
//这里很坑
//发现是return false的话就输出下面语句
//如果是return true的话就不输出下面语句,而是会输出迷宫路径(mgth函数已经写好)
cout << "该迷宫问题没有解!";
return 1;
}