一、前言
在之前的问题中,我们书写了较为简单的迷宫非递归问题(数据结构——非递归动态迷宫问题),而本文章在之前的迷宫基础上,优化了迷宫生成算法,寻找路径算法,以及加入了简单的开场动画和背景音乐,对控制台缓冲区进行了美化。
该迷宫问题类似于,有一个人不知道哪里是终点,所以只能上下左右去试探地找,有可能走到死路然后又返回,直到找到终点为止。
二、迷宫生成算法
深度优先算法的运用:
这个时候相当于在这片区域一只地鼠,要在这个区域不停的挖,直到任何一块区域再挖就会挖穿了为止。
我们挖的道路就像树结构,树上有很多的分支,分支也有子分支,每个子分支都不能相交,相交了就说明墙被挖穿了,那么此时的迷宫就可能存在多条正确道路,为了避免这一问题,我们向某个方向挖一块新的区域时,要先判断新区域是否有挖穿的可能,如果可能挖穿要立即停止并换个方向再挖。
引入block绝对距离:
以上算法所生成的迷宫具有随机性,不一定有通路,因此为了保证每个迷宫都有至少一条通路,我设计了这个算法。
首先随即播撒下一颗种子,分别向end(终点)和origin(起点)生长,如果最后end到达终点,并且origin到达起点时停止生长,此时起点和终点被链接了起来,此迷宫至少有一条通路。
为了使其向起点和终点延申而不跑偏,例如end,我们让end随机向上下左右四个方向生长,这时计算新到达的地方和终点之间的block绝对距离和原来位置和终点之间的block绝对距离,如果新到达的地方的block绝对距离比原来的小或相等,那么我们就更新,否则就重新开始上下左右随即生长。
三、寻找路径的算法
因为不能够利用递归,因此我们用栈的方式来做。
首先,建立两个栈来存储通路的x和y坐标,先将起点入栈。
然后,从起点开始上下左右移动,如果该位置没有越过迷宫边界,并且不是墙,那么入栈。
如果上下左右都不能走的话,那标记为3(重复走的路不再走),退栈。
一直循环,如果最后退回了起点,那么迷宫没通路,退出,如果最后到达了终点,那么成功。
四、部分代码展示
int main()
{
Wsetting();
int e;
djs();//倒计时
printword();//打印文字
system("cls");
do {
system("color F8");//设置控制台界面背景颜色和前景颜色
system("cls");
int i, N, M;
do {
cout << "请输入迷宫大小:(1~36)";
cin >> M;
m = M; n = M;
maze = new int* [m + 2];
for (int i = 0; i < m + 2; i++)
{
maze[i] = new int[n + 2];
}
if (M <= 0|| M > 36) cout << "输入错误,请重新输入!";
} while (M <= 0 || M > 36);
do {
cout << "请输入迷宫难度(从0开始,难度依次减小)";
cin >> N;
if (N < 0) cout << "输入错误,请重新输入!";
} while (N < 0);
Pos origin; InitPos(origin);//定义起点
Pos end; InitPos(end);//定义终点
do {
cout << "请输入迷宫起点坐标(x,y)";
cin >> origin.x; cin >> origin.y;
if (origin.x <= 0 || origin.x >= m + 1 || origin.y <= 0 || origin.y >= n + 1) cout << "输入错误,请重新输入!";
} while (origin.x <= 0 || origin.x >= m + 1 || origin.y <= 0 || origin.y >= n + 1);
do {
cout << "请输入迷宫终点坐标(x,y)";
cin >> end.x; cin >> end.y;
if (end.x <= 0 || end.x >= m + 1 || end.y <= 0 || end.y >= n + 1) cout << "输入错误,请重新输入!";
} while (end.x <= 0 || end.x >= m + 1 || end.y <= 0 || end.y >= n + 1);
do {
cout << "是否打开背景音乐:(1为是,0为否)";
cin >> i;
if (i != 1 && i != 0) cout << "输入错误,请重新输入!";
} while (i != 1 && i != 0);
if (i)
{
mciSendString(L"open 迷宫.mp3 alias song", NULL, 0, NULL);
mciSendString(L"play song repeat", NULL, 0, NULL);
}
CreateMaze(maze, N, m, n, origin, end);
PrintMaze();
system("cls");
GetMazePath(origin, end);
do {
cout << "还要再来一遍吗?(1是,0否)";
cin >> e;
if (!e)
{
cout << endl << "不了不了,还是学习有意思。" << endl;
TIMEDELAY();
}
if (e != 1 && e != 0) cout << "错误,只能输入0或1!" << endl;
} while (e != 1 && e != 0);
} while (e);
return 0;
}
五、运行结果展示
1.开场动画
2.迷宫生成
3.找寻通路动态图
(由于时间问题,我们用20×20的迷宫地图来寻找通路)
六、代码获得途径
如有需要,请点击以下链接进行购买:https://download.csdn.net/download/m0_54688810/20193919
或添加微信:shuxuexiaobaibututou 进行购买咨询。