代码写在Unity环境下,应该可以直接使用。
先上一张图
这是我最早拍脑袋凭着感觉写的一个算法结果,给定区域长宽和分支概率,可以生成一张迷宫图。这完全就是随机挖洞大法,其步骤如下:
可以看出,这个算法有相当的缺陷,生成的迷宫总面积不可控,在运气不好的极端情况下,会产生比预期面积小很多的迷宫。即使我们将分支概率调到100%,依旧会有黑色的空洞存在:
此时的迷宫已经勉强可以使用,但是与传统迷宫的差别依旧非常大。它的斜线非常多。这会使得游戏过程中包含八个方向,对玩家的方向感是极大的考验,很难再记住地图,容易晕头转向。
对于这个算法,相比室内环境,更适合生成自然环境下迷宫。也可以作为无主线、弱主线沙盘游戏的大地图生成的一环。
接下来这个算法与第一个就是两个极端——生成完全没有斜线的迷宫。话不多说,先上图:
在介绍本算法前,需要提出一个概念
完美迷宫Perfectmaze:没有回路,也没有孤立区域的迷宫。用图论来解释,就是可以用生成树表示的迷宫,迷宫中两点有且仅有一条路径。
这个算法是一个分治算法,即将一块大的生成区域分成4块小区域分别生成迷宫并保证联通,以此类推,直到不可细分。
分块很简单,长宽上各取一个随机数即可。如何保证迷宫完美呢?我们看极端情况,对于一个田字形区域,生成完美迷宫的方法是敲开三堵墙。
利用分治算法的特性,每一层递归都是完美迷宫,直到全图生成完美迷宫。算法不难,注意递归状态的边界情况就行。
这种分治递归的痕迹在生成的地图俯视图上很明显,但对于置身其中的玩家或许就不是了。
它生成的迷宫完全没有斜线,横平竖直,同时会生成4*4的小房间。用作城市地图、或建筑环境的迷宫非常合适。
当然在游戏中地图没有回路是非常致命的,一个完美迷宫会让玩家疲于奔命,并不方便设计玩法。对于回路,我们只需要消除死路就行了,也就是那些三面临墙的格子,在地图生成完后遍历死路,按一定概率打通即可。
绝大多数的编程问题都可以用数学工具解决,当然我们的迷宫生成算法也不例外。数学中最适合表达迷宫的符号莫过于图,下面两个算法是迷宫生成中应用最普遍的理论之二。
首先我们需要将地图转换为便于数学表达的形式。之前两个算法在处理地图时都是以方块为单位的,即每一个方块不是墙就是路。而图的基本组成是点与边,对于一个待处理的迷宫,我们做如下转换。
迷宫大小10*10,其中白块代表点,红块代表边,而黑块代表虚无,只是填充物质罢了。
如果一个图中,任意两点都能通过边组成的路径联通,称之为连通图。
而如果一个连通图上没有回路,则我们可以称之为树,因为没有回路,所以每对点之间有且仅有一条路径联通。
可以看到,树与我们完美迷宫的概念不谋而合,所以现在我们的任务是找到包含所有点的一棵树。
生成树,顾名思义,就是从给定的点,边集合中生成一棵符合要求的树。下面介绍的两种最小生成树算法都可以胜任。
虽然写作最小生成树,但这两个算法其实可以做到“按一定条件生成树”。“最小”是算法的典型描述,即在有权边的集合中找出权值最小的树。原算法使用贪心算法求解。
而在这里,我们的条件就是:随机。
下面简单介绍一下这两个算法的步骤:
两个算法都需要点的集合E,与边的集合V。对于上图,E代表所有白块,V代表所有红块
Kruskal:一开始每个点将自己作为单独的一棵树。
Prim:初始V为空,所有e∈E标记为0
ps:可以维护一个包含所有v∈V的标记表,防止被重复并入V,提高效率
以上为算法步骤,建议配合代码食用更佳。
下为运行结果
前者为Kruskal,后者为Prim。白路黑墙。
可以看到两个算法的生成迷宫风格几乎一样,并且都较为接近传统迷宫。可以用于各类需要迷宫生成的游戏。
赞啊,大家可以仔细看看,研究下
想把随机的房间加入,加入一个出口点,多个入口,全联通模式。可以吗
然后对每个房间设定门的数量,将房间周围路径纳入生成路径的备选。