人类创造迷宫的历史至少可以追溯到 5000 年前:1986 年人们在意大利西西里岛上发现了一幅绘制于公元前 3000 年的迷宫的史前壁画。希腊神话中,克里特岛国王米诺斯的儿子,半人半牛怪物的弥诺陶洛斯,就被关在克诺索斯的一座迷宫里。中世纪的英国则流行草坪迷宫,也就是把草坪栽种成迷宫的样式。清朝乾隆年间,圆明园里仿照欧洲的迷宫,用四尺高的雕花砖墙造了一座中西结合的迷宫花园:万花阵。下图是清内府宫廷满族画师伊兰泰所作的《西洋楼透视图铜版画》中的一幅,描绘的就是圆明园里的万花阵迷宫。
在这篇文章里,我将介绍如何利用 Mathematica 自身提供的和网格区域、图论、哈希表(关联)相关的各种函数,来创建形形色色的迷宫。
用图论算法构造迷宫
迷宫是指一种需要玩家从一个指定的起点出发,在用墙隔断形成的分叉道路中辨识选择,最终到达指定终点的游戏。迷宫可以有各种不同的形式和不同的构造方法,这里介绍的是一种很普适的,基于图论的构造方法。用这种方法构造的迷宫,一个显著的特点就是迷宫内部没有封闭区域,内部任意两处之间有且仅有一种走法。
基本原理
下面我们用较为常见的,外轮廓为矩形,分叉道路横平竖直的矩形迷宫为例,来说明这种构造方法的基本原理。下图就是一个典型的矩形迷宫。
要生成这样一个迷宫,首先就是要把这个矩形区域划分成一个个小的单元格,形成一片网格:
每个单元格现在都是互相隔断的,构造迷宫的过程就是"拆墙",让相邻单元格连通的过程。拆掉的墙要是少了,会有单元格仍然封闭不连通;拆掉的墙要是多了,那么两个单元格之间就可能有不止一种走法。这两种情况都不是我们想要的。要拆得恰到好处,我们需要图论相关的知识。
图论的研究对象就是图。一个图看起来是由一些小圆点(称为顶点)和连接这些圆点的直线或曲线(称之为边)组成的图形。从上面这个网格图形出发,我们可以构造一个图。具体构造方法是把每个单元格看作一个顶点,如果两个单元格相邻,也就是有共同的"墙",那么就在这两个单元格对应的顶点之间添加一条边。如下图所示,我们把暗红色的图和黑色的网格叠合在了一起:
这样通过去掉原图的部分边或顶点得到的新图,被称为原图的"子图"。上面图形的红色部分就是个子图。可以注意到,两个单元格(未必相邻)之间如果可以走通,那么子图的顶点之间,必然存在一条由边首尾相连形成的通路。
于是,我们之前说的迷宫的"墙要拆得恰到好处"所具备的两个特点,就可以翻译成子图的性质:没有封闭的单元格&#