JS手撸数据结构系列(四) ——Prim算法与迷宫生成
来源:互联网 发布:mac浏览器打不开百度 编辑:程序博客网 时间:2024/05/18 01:53
迷宫问题
一个100*100的方格的迷宫,障碍未知,只知道起点和终点,以第一视角进入,求最短距离路径。
这是当时腾讯二面的面试官给我留的题目,当时只要求写出了BFS求最短路径的算法,那么就会很自然的想到如何生成迷宫呢?
迷宫可以看成是一个图,也可以看成是一个二维数组,其中数组元素的值为1,代表可以走通,代表路,其中数组元素的值为0的话,代表不能走通,代表墙壁。要想生成随机迷宫,难点就在如何确保在墙壁和道路随机的情况下,能保证从起点到终点的路线是连通的。就算碰巧(概率应该很低了)能保证存在路线,但是这样的迷宫也好丑,障碍都是离散的…..
Prim算法
这个问题困扰了我好久,网上的资料一般关于如何寻找迷宫路径的算法比较多,直到有一天看到数据结构中的图的最小生成树一章,可以发现迷宫问题就是一种最小生成树。如下图所示,左图代表起始状态,白色路径表示所有值为1的点,我们要做的就是制造一颗连续生长的树,最后把所有值为1点的点都添加到这颗树中, 只不过书上的Prim算法每步选取新节点的原则是最小边,我们改成随机选取就好了。
=>
迷宫算法实现
(1)如上图图左所示为一个7x7的迷宫,先假设迷宫中所有的通路都是完全封闭的,白色的格子表示可以通过,黑色的格子表示墙壁不能通过。
(2)随机选择一个白色的格子作为当前正在访问的格子,同时把该格子放入一个已经访问的列表中。
(3)循环以下操作,直到所有的格子都被访问到。
1.得到当前访问格子的四周(上下左右)的格子,在这些格子中随机选择一个没有在访问列表中的格子,如果找到,则把该格子和当前访问的格子中间的墙打通(置为0),把该格子作为当前访问的格子,并放入访问列表。
2.如果周围所有的格子都已经访问过,则从已访问的列表中,随机选取一个作为当前访问的格子。
通过以上的迷宫生成算法,我们就可以生成一个路径分布很自然随机迷宫 源代码与在线预览
function Maze(col, row, start, end) { this.col = col; this.row = row; this.start = start; this.end = end; } // 向下取整,生成随机数 Maze.prototype.random = function (k) { return Math.floor(Math.random() * k); }; Maze.prototype.generate = function () { // 生成 2R+1 行 2R+1 列数组 this.mazeDataArray = []; for (let i = 0; i < 2 * this.col + 1; i++) { let arr = []; for (let j = 0; j < 2 * this.row + 1; j++) { // 设置墙和初始格子 if (i % 2 == 0 || j % 2 == 0) { arr.push({ value: 0, x: j, y: i }); } else { arr.push({ value: 1, isVisited: false, x: j, y: i }); } } this.mazeDataArray[i] = arr; } // 随机选择一点作为 currentNode let currentNode = this.mazeDataArray[2 * this.random(this.row) + 1][2 * this.random(this.col) + 1]; currentNode.isVisited = true; // 访问过的节点列表 let visitedList = []; visitedList.push(currentNode); // 循环以下操作,直到所有的格子都被访问到。 while (currentNode.isVisited) { // 得到当前访问格子的四周(上下左右)的格子 let upNode = this.mazeDataArray[currentNode.y - 2] ? this.mazeDataArray[currentNode.y - 2][currentNode.x] : {isVisited: true}; let rightNode = this.mazeDataArray[currentNode.x + 2] ? this.mazeDataArray[currentNode.y][currentNode.x + 2] : {isVisited: true}; let downNode = this.mazeDataArray[currentNode.y + 2] ? this.mazeDataArray[currentNode.y + 2][currentNode.x] : {isVisited: true}; let leftNode = this.mazeDataArray[currentNode.x - 2] ? this.mazeDataArray[currentNode.y][currentNode.x - 2] : {isVisited: true}; let neighborArray = []; if (!upNode.isVisited) { neighborArray.push(upNode); } if (!rightNode.isVisited) { neighborArray.push(rightNode); } if (!downNode.isVisited) { neighborArray.push(downNode); } if (!leftNode.isVisited) { neighborArray.push(leftNode); } // 在这些格子中随机选择一个没有在访问列表中的格子, // 如果找到,则把该格子和当前访问的格子中间的墙打通(置为0), if (neighborArray.length !== 0) { // 如果找到 let neighborNode = neighborArray[this.random(neighborArray.length)]; this.mazeDataArray[(neighborNode.y + currentNode.y) / 2][(neighborNode.x + currentNode.x) / 2].value = 1; neighborNode.isVisited = true; visitedList.push(neighborNode); currentNode = neighborNode; } else { // 把该格子作为当前访问的格子,并放入访问列表。 // 如果周围所有的格子都已经访问过,则从已访问的列表中,随机选取一个作为当前访问的格子。 currentNode = visitedList[this.random(visitedList.length)]; if (!currentNode) { // visitedList为空时 跳出循环 break; } currentNode.isVisited = true; // 从 visitedList 中删除随机出来的当前节点 let tempArr = []; visitedList.forEach(item => { if (item !== currentNode) { tempArr.push(item); } }); visitedList = tempArr; } } this.mazeDataArray[this.start[0]][this.start[1]]={ x:this.start[0], y:this.start[1], value:1 }; this.mazeDataArray[this.end[0]][this.end[1]]={ x:this.end[0], y:this.end[1], value:1}; }; let maze = new Maze(3, 3, [1, 0], [5, 6]); maze.generate();
I know H.T.M.L (How to meet ladies)
–Silicon Valley
《硅谷》第四季 强烈推荐
- JS手撸数据结构系列(四) ——Prim算法与迷宫生成
- JS手撸数据结构系列 (五) ——图的遍历与迷宫求解
- JS手撸数据结构系列(三) ——子序列、幂集与递归
- 数据结构与算法系列----最小生成树(Prim算法&Kruskal算法)
- Python 数据结构与算法 —— Prim 算法与小顶堆
- 数据结构——邻接矩阵的最小生成Prim算法
- 《大话数据结构》最小生成树——Prim算法
- 数据结构——邻接矩阵的最小生成树Prim算法
- 数据结构与算法16:最小生成树普利姆prim算法
- 数据结构与C语言实现(十一)——图(下):最小生成树与Prim与Kruskal算法
- JS手撸数据结构系列(一) ——从快排搞起
- JS手撸数据结构系列(二) —— 树的遍历
- 重学数据结构系列之——图论算法之Prim算法
- 数据结构与算法分析(Java语言描述)(31)—— 使用 Prim 算法求有权图的最小生成树(MST)
- Pku acm 1258 Agri-Net数据结构题目解题报告(四) ----最小生成树:prim算法
- 数据结构 — 图 之 MST(最小生成树 — prim算法 )
- 【数据结构】求最小生成树的权值之和——Prim算法
- 数据结构 第16讲 沟通无限校园网——最小生成树(prim算法)
- 删除表中一列
- 删除表中重复数据
- 关于oracle锁模式
- 创建连接视图注意事项
- 关于OLAP和OLTP
- JS手撸数据结构系列(四) ——Prim算法与迷宫生成
- 关于System表空间
- 更改列的名字
- 安全之非对成加密SSL/TLS
- NVL函数用法
- Decode函数用法
- 单点登录CAS使用记(七):关于服务器超时以及客户端超时的分析
- sql语句计算出每个月的天数
- ora-12592 包错误解决