数据结构——升级版迷宫非递归求解问题


一、前言

在之前的问题中,我们书写了较为简单的迷宫非递归问题(数据结构——非递归动态迷宫问题),而本文章在之前的迷宫基础上,优化了迷宫生成算法,寻找路径算法,以及加入了简单的开场动画和背景音乐,对控制台缓冲区进行了美化。

该迷宫问题类似于,有一个人不知道哪里是终点,所以只能上下左右去试探地找,有可能走到死路然后又返回,直到找到终点为止。

二、迷宫生成算法

深度优先算法的运用:

这个时候相当于在这片区域一只地鼠,要在这个区域不停的挖,直到任何一块区域再挖就会挖穿了为止。

我们挖的道路就像树结构,树上有很多的分支,分支也有子分支,每个子分支都不能相交,相交了就说明墙被挖穿了,那么此时的迷宫就可能存在多条正确道路,为了避免这一问题,我们向某个方向挖一块新的区域时,要先判断新区域是否有挖穿的可能,如果可能挖穿要立即停止并换个方向再挖。

引入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 进行购买咨询。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

数学小白不秃头

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

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

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

打赏作者

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

抵扣说明:

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

余额充值