[不靠谱颜论] 用ggplot2画迷宫
导言: 对ggplot2来说,画几个迷宫,还不就跟玩一样。

ggplot2
绝对算得上我掌握的最实用编程技能。随机地画一大堆迷宫,每个迷宫都有且只有一条正确路径,这对于讨好喜欢走迷宫的小闺女来说,可真是太好用了。
下面就来介绍,这个画迷宫的想法,是如何变成现实的。
1
首先,对题图这样的迷宫,可以将其考虑是一个w x h
的网格(w
和h
分别表示横向和纵向分别有多少个格子),从中拆除部分相邻格子间的隔板后,而得到的结果。
为方便ggplot2
使用,在构造数据时,直接构造w x h
行数据记录,并且用x
和y
两个字段来分别表示每条记录对应的坐标位置,其他字段则分别表示该坐标的其他属性。于是就有如下代码,来完成一个“拆除隔板”前的迷宫的绘制:
|
|
这里,使用了一个实现技巧,即考虑每个格子只拥有右侧和上侧的隔板(对应下面代码中的vline
和hline
,这两个字段若取值为FALSE
,则表示拆除了该隔板,即不再绘制),左侧和下侧的隔板则共享其相邻格子的。相应地,其实我们构造了一个(w + 1) x (h + 1)
行的数据表。为了去除网格在上边界和有边界的多余线段,在构造hline
和vline
初始值时,限制了相应的范围。
有了上面这个框架,接下去,我们只需要设置hline
和vline
字段,实现合适的隔板拆除,迷宫就可以完成。
2
该拆除哪些隔板呢?
这需要一个循环过程。首先假定有一个精灵,站在迷宫的起点,然后采取随机游走的方式,走到相邻的下一个格子。游走的过程需要进行标记,避免走入已经到达过的格子。依靠这个游走的过程进行隔板拆除,最终,就能确保有且只有一条正确路径,到达预期终点。 下面这个动画,比较直观地展示了上述过程。相应的代码,就不在这里详细解释了。

值得注意的是,这个精灵并不是完全一条道走到黑。如果是,则生成的迷宫很可能会变得很简单。所以,我们需要按照某个概率(比如10%),从已经到达过的某个格子出发,分叉出去,走另一条路径。这个概率,可以用来帮助调整迷宫的复杂度。
3
在上述动画中,展示了每次步进,拆除一片隔板,从而生成整个迷宫的过程。这个动画的每一帧,也同样都是基于ggplot2
语句进行绘制的。其间无非是增加了几个字段,分别表示出对应路径及其他图像元素,然后将其映射到对应的geom_xxx()
语句即可。
此外,ggplot2
有个映射坐标系的强大功能,可以直接将笛卡尔坐标系(即我们通常熟悉的互相垂直的x轴和y轴所构成的平面)转化为极坐标系。这让我们可以直接把上面实现的迷宫,变成一个圆形迷宫。

最终迷宫实现(包括上述演示动画)的完整代码,均可在github上找到,点击“阅读原文”可进行查看。
注:本文发表于“不靠谱颜论”公众号,并同步至本站。