【Javascript + Vue】实现随机生成迷宫图片 (3)

把被破过墙的方格使用 checked 属性标记起来,并且放入数组 nodesChecked,每次就从这个数组随机取下一个方格。getNextDirections 添加一个过滤条件,就是如果某面墙对着的方格曾经被破过墙,就不能选这面墙了。如果一个方格已经无墙可破,则把他从 nodesChecked 中删除,减少迭代次数。

完整代码:https://codesandbox.io/s/maze-vite-12-28isc?file=http://www.likecs.com/src/maze.js:9899-10297

运行效果:

image

回溯法

现在所有区域都联通了,不再有孤立区域,但是却存在一些非常难看的死胡同,比如:

image

这些死胡同实在太浅了,如何让迷宫拥有良好的战略纵深呢?答案就是结合我们的第一个方案,先不要使用随机传送法,而是沿路往前推进,直至遇到无墙可破的情况,再从 nodesChecked 出栈一个 node,把他当作新的起点继续前进,直到 nodesChecked 为空即可:

async breakWall (cb = async () => {}) { let { nodes, nodesChecked } = this nodesChecked.push(nodes[0]) nodes[0].checked = true let current = nodes[0] for (; nodesChecked.length > 0;) { let breakDirection = this.getRandomNext(current) await cb(current) if (breakDirection !== null) { current.value ^= breakDirection.value let { nextNode } = breakDirection nextNode.value ^= breakDirection.oppositeValue nextNode.checked = true nodesChecked.push(nextNode) current = nextNode } else { current = nodesChecked.pop() } } }

image

效果很不错,这种方法可以称为回溯法,看起来也确实像。

这种方法的缺点也是显而易见,随着迷宫规模的增大,需要的迭代次数和数组空间也会增大。

最后,加入一些必要的可定义参数,最终成品:https://codesandbox.io/s/maze-vite-13-j9uqv?file=http://www.likecs.com/src/maze.js:10050-10503

image

墙壁建造者

从现实的角度考虑,没有人在建造迷宫时先把所有的墙造好,然后再把他们凿穿。所以是否有一种算法是通过添加墙壁来实现生成迷宫的呢?答案是有的。

一开始,整个迷宫看起来是这样的:

image

什么也没有,所以接下来要往里面添加墙壁?是,也不是,我们要换一种思路,不是添加墙壁,而是将整个迷宫一分为二:

image

接着在分界线上砸出一个缺口:

image

然后在剩下的区域里面再做同样的事情

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfsps.html