迷宫随机生成及路径搜索

这个题目和数据结构—图有关

迷宫的随机生成和路径搜索主要和图的遍历有关,一般来说图的遍历主要有两种方式:1、深度优先遍历(DFS)2、广度优先遍历(BFS)

两种遍历方式都很好理解,就说说深度优先遍历:

深度优先遍历,顾名思义,就是尽可能往深处遍历,访问到一个节点时,搜索这个节点没有被访问过的相邻节点,选择一个继续做同样的操作,直到没有邻节点为止再回溯到上一个访问的节点,并选择另外的邻节点。

可以这样描述深度遍历:

(1)访问顶点v;

(2)从v的未被访问的邻接点中选取一个顶点w,重复第一步,如果v没有未访问的邻接点,回溯至上一顶点;

(3)重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。

那么,迷宫的生成和路径搜索与图的遍历有什么关系呢?

假设有如下一个图:
在这里插入图片描述
试着对这个图进行深度优先遍历并把遍历的轨迹记录下来,如下图。
在这里插入图片描述
遍历顺序依次为 1—>2—>6---->10---->9---->5----->13----->14----->15----->11----->12-----16---->8----->7----->3---->4,

是不是有点迷宫的样子了呢?但是上面这个经过遍历生成的路径图还不能完全算一个迷宫,因为还缺少了“墙”,补上即可成为一个完整的迷宫,如下图:
在这里插入图片描述
上图中蓝色的节点为墙,在遍历过程中将点之间的墙“抹掉”–即空白的格子,这样就可形成一个完整的迷宫,如上图。

怎么样,是不是就是一个迷宫了,注意到遍历一次后任意两点之间都可以找到一条路, 所以迷宫的出口和入口只需要从外围的点任选两个即可(如上图中选择的是1旁边的和16旁边的点)。

经过上面的分析,我们就知道该怎么生成一个迷宫了。

1、首先初始化迷宫的雏形,即一个矩形图阵,并为图的每个节点旁边都添加上“墙”,如下图:
在这里插入图片描述
2、然后对图中的非“墙”节点进行遍历(深度优先或广度优先都行),为了能够生成随机的迷宫,我们可以在遍历过程过适当的做一些随机的操作(代码中会说明),每次遍历时即打通当前遍历的点与上一个点之间的“墙”

3、遍历完所有的点即可生成一个迷宫,然后再选择出口与入口,一个完整的迷宫就形成了。
在这里插入图片描述
至于迷宫的路径搜索,那就完全是图的深度遍历了,大概过程如下。

(1)从迷宫起点节点V开始访问

(2)访问这个节点V,标记为可行的路径;

(3)从v的未被访问的非"墙"邻接点中选取一个顶点w,重复第二步。如果v没有未访问的非"墙"邻接点,把这个节点的可行路径标记移除,回溯至上一节点;

(4)重复上述第(2)、(3)步,直至遍历到迷宫的出口节点。

参考迷宫路径搜索代码:

#include<stdio.h>

// 迷宫坐标位置类型
struct PosType
{
	int x; // 行值
	int y; // 列值
};

#define MAXLENGTH 25 // 设迷宫的最大行列为25
typedef int MazeType[MAXLENGTH][MAXLENGTH]; // [行][列]

// 全局变量
struct PosType end;	// 迷宫终点位置
MazeType m;			// 迷宫数组
int n;			// 迷宫行数,列数

// 定义墙元素值为0,可通过路径为-1,通过路径为足迹
int min_value = 10000;

// 由当前位置cur、当前步骤curstep试探下一点
//curstep表示当前已经尝试的步数
void Try(struct PosType cur,int curstep)
{
	int i;
	struct PosType next; // 下一个位置
	// {行增量,列增量}
	struct PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}};
	// 移动方向,依次为东南西北
	for(i=0;i<=3;i++) // 依次试探下左上右四个方向
	{
		next.x=cur.x+direc[i].x;
		next.y=cur.y+direc[i].y;

		if(m[next.x][next.y] == 0) // 是通路
		{
			m[next.x][next.y]=++curstep;
			if(next.x != end.x || next.y != end.y) // 没到终点
				Try(next,curstep); // 试探下一点(递归调用)
			else
				min_value = min_value>curstep?curstep:min_value;//该语句求出最短路径,如果输出路径,直接记录step即可
			m[next.x][next.y]=0; // 恢复为通路,试探下一条路
			curstep--;
		}
	}
}

int main()
{

	struct PosType begin;	//起点
	int i,j;
	while(scanf("%d",&n)!=EOF)
	  	for(i=0;i<n;i++) {
	          for(j=0;j<n;j++) {
	              scanf("%d",&m[i][j]);
	          }
	  	}
	  
	begin.x = 1,begin.y=1;
	end.x = n-2,end.y= n-2;
	m[begin.x][begin.y]=2;
	Try(begin,0); // 由第一步起点试探起
	if(min_value == 10000)
        printf("No solution");
	else
        printf("%d",min_value);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/hxy17682323970/article/details/88409316