今天补个遗,将很久以前研究 HTML5 的时候写的生成迷宫、迷宫寻路程序整理出来。

下载链接在文章最后。

简介

为什么要做这个 HTML5 迷宫程序?因为我喜欢、我愿意。也是向老程序员学习(见第5节)。

里面都有什么?包括生成迷宫,以及,走出迷宫的 Javascript 程序,绘制迷宫使用了 Canvas。

怎么做的?主要参考了这几篇文章:

How to build a maze?

这个网站提供在线的 Java Applet 示例,很直观。

Labyrnth

Maze generation algorithm

Maze Generation

然后代码自己写,因为没有可以照搬的,照搬的也不是按照我希望的方式去工作的。看明白原理之后,就开始设计自己的迷宫程序了。

原理

这是此次补遗最难的部分,因为我真的不记得是怎么做到的了!唯一有点儿印象的,是A*搜索算法,即包含当前探索节点与目标节点距离的估值函数的改进型A搜索算法,相当于对A搜索算法剪枝吧。我是这么认为的

在网页上生成迷宫,主要解决下面几个问题:

  • 生成迷宫
  • 挑选迷宫起点和终点
  • 探索迷宫
  • 绘制迷宫和探索结果(路径)

前面3个问题,和 HTML 一毛钱关系都没有。完全依靠数据结构和算法。你把数据结构和算法搬到 C# 里面去,用 WPF 画迷宫也是可以的。

迷宫(尤其是矩形的)可以看作是很多个小格子,叫做 Cell,每个小格子都被墙(Wall)环绕,组合在一起。所以一开始,迷宫如果绘制出来,看上去应该是这样的:

然后,从选定的起点开始,从周围相邻的 Cell 里面随便挑选一个,打破这2个 Cell 之间的墙。接着,继续,直到所有的 Cell  都被访问过了。迷宫的生成大概就是这么个原理,当然,圆形、六角形的迷宫会有区别,这个方面,参考上面列出的 Wiki 上面的解释最清楚了。

探索迷宫的话,需要先知道起点和终点(目标点)的 Cell 的坐标。在我的程序里面,起点 Cell (start_cell)是随机挑选的,终点 Cell (goal_cell)则是指定的一个位置,这样做只是为了让出来的迷宫图形比较好看,否则可能出现起点和终点太靠近,迷宫画出来没有“好复杂!”的感觉

为了避免盲目探索,每次从当前 Cell 开始挑选下一个邻近的可以走通的  Cell 时,都会计算一个 g 值,也就是下一个 Cell 和目标 Cell 的距离值,这个值用来剪枝,距离小的,优先走。在我的程序里面,这个值是用 init_g_h_value 函数来计算的。为了提高迷宫处理速度,已经预先将所有节点的 g 值计算完毕,存在迷宫数组里面了,即用“空间换时间”是也。

有兴趣的话,可以修改程序里面的 maze_g_value、maze_h_value 两个参数变量的值,看看不同的效果,你会发现路径会从松散到紧凑变化。

程序

先看网页布局。虽然写程序是从生成迷宫到探索到显示的顺序,但是,实现起来,要反过来,先把最终呈现效果给设计出来。

顺便插一句:做软件,可以没有测试,可以没有文档,甚至可以没有需求,但,你不能没有设计。说得“极端”了点儿,但这只是为了强调“设计”的重要性。

界面上有一个 canvas,一个 div。Canvas 用来绘制迷宫,div 用来输出调试信息,将程序中 _debug_ 变量设置为 true 即可开启。(_debug_ 作为全局变量,命名方式和其它全局变量不同,这是因为这个调试变量是我今天写这篇博客时临时加的,反映了我最近对于全局变量命名的口味。以前写的,则是另外一种口味,人总是会变的嘛。)

下面是程序设计,

这个迷宫程序需要 jQuery,1.7 以后的版本应该都可以,默认用的是 jquery-1.9.1.js。如果你是用 IE 9 以前的版本来运行这个网页程序,你还需要一个 excanvas.js 文件。这些 js 文件都和程序网页放在一层目录里面就可以了。

打开网页以后,程序立即运行:

  • $(document).ready 调用 generate_maze 函数;
  • generate_maze 将迷宫每个 cell 的数据填入 maze_cells 数组;
  • 接着 solve_maze;
  • solve_maze 将探索过程记录进入 parsed_cells 数组;
  • 接着 reformate_path;
  • reformate_path 将 parsed_cells 中的实际路径挑选出来,塞入 final_path 数组,这样,绘制迷宫的时候就比较简单了;
  • 最后是 draw_maze,在 canvas 上面绘图。只有在这里,这个迷宫程序才和 HTML5 搭上了点儿边。

这里有个技术细节。

由于生成和探索迷宫的过程中,需要不停的记录当前状态、取出上一个状态的堆栈入栈和出栈操作,因此,当迷宫尺寸比较大的时候,会出现“堆栈溢出”的消息。为此,我自己用 cell_stack 数组实现了一个堆栈来保存探索过程中的状态信息。

效果

网页打开就是这样,每F5一次就刷一个新的迷宫给你。红色的点是起点,蓝色的点是终点(目标点),紫色的点是探索过的路径,绿色的点是最终走通的路径。

下载

这里下载,只有一个 HTML 文件。另外还需要 jQuery(文件名是 jQuery-1.9.1.js,如果你用了其它版本的 jQuery,请到 maze.html 里面对应修改) 和 excanvas 文件,和我的迷宫程序网页放在一个目录即可。

HTML 迷宫的更多相关文章

  1. C语言动态走迷宫

    曾经用C语言做过的动态走迷宫程序,先分享代码如下: 代码如下: //头文件 #include<stdio.h> #include<windows.h>//Sleep(500)函 ...

  2. POJ 2251 Dungeon Master(3D迷宫 bfs)

    传送门 Dungeon Master Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 28416   Accepted: 11 ...

  3. BFS_Maze_求解迷宫最短路径

    /* 10 10 #.######.# ......#..# .#.##.##.# .#........ ##.##.#### ....#....# .#######.# ....#..... .## ...

  4. 【刷题笔记】I'm stuck! (迷宫)-----java方案

    题目描述 : 给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七个字符中的一个,分别表示如下意思: '#': 任何时候玩家都不能移动到此 ...

  5. canvas实例 ---- 制作简易迷宫(一)

    这个系列分为两部分,第一部分为迷宫的生成及操作,第二部分为自动寻路算法. 我们先看效果: See the Pen QGKBjm by fanyipin (@fanyipin) on CodePen. ...

  6. 洛谷P1605 迷宫——S.B.S.

    题目背景 迷宫 [问题描述] 给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过.给定起点坐标和 终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案.在迷宫 中移动有上下 ...

  7. Java迷宫游戏

    缘起: 去年(大三上学期)比较喜欢写小游戏,于是想试着写个迷宫试一下. 程序效果: 按下空格显示路径: 思考过程: 迷宫由一个一个格子组成,要求从入口到出口只有一条路径. 想了一下各种数据结构,似乎树 ...

  8. K - 迷宫问题

    /*定义一个二维数组:  int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, ...

  9. Dijkstra算法初步 - 迷宫问题

    你来到一个迷宫前.该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数.还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间.游戏规定了 ...

随机推荐

  1. vs运行时候冒了这个错:无法启动IIS Express Web 服务器~Win10

    后期会在博客首发更新:http://dnt.dkill.net 异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 网上的方法多种, ...

  2. js动态给当前点击元素添加css类

    1.页面:

  3. 使用HTML5里的classList操作CSS类

    在HTML5 API里,页面DOM里的每个节点上都有一个classList对象,程序员可以使用里面的方法新增.删除.修改节点上的CSS类.使用classList,程序员还可以用它来判断某个节点是否被赋 ...

  4. xprivacy改IMEI

    XPrivacy是一款基于Xposed框架的模块应用,可以对所有应用可能泄露隐私的权限进行管理,对禁止可能会导致崩溃的应用采取欺骗策略,提供伪造信息.前提你的手机进行root过.我这边使用的是geny ...

  5. iOS开发之画图板(贝塞尔曲线)

    贝塞尔曲线,听着挺牛气一词,不过下面我们在做画图板的时候就用到贝塞尔绘直线,没用到绘制曲线的功能.如果会点PS的小伙伴会对贝塞尔曲线有更直观的理解.这篇博文的重点不在于如何用使用贝塞尔曲线,而是利用贝 ...

  6. MySQL密码忘记,怎么办?

    如果哪天你忘记了线上MySQL数据库的root密码,怎么办? 大家往往会想到skip-grant-tables参数,具体步骤如下: 1. 关闭MySQL数据库,因为root密码忘记了,mysqladm ...

  7. 如何用Excel直接查询Oracle中的数据

    将Oracle中查询的数据保存为Excel文件,通常使用的是PL/SQL Developer. 其实,Excel可直接写SQL语句查询Oracle中数据,在这里,用到ODBC驱动.详细步骤如下: 一. ...

  8. 1Z0-053 争议题目解析481

    1Z0-053 争议题目解析481 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 481.Which statement is true about a running sessi ...

  9. struts2学习笔记--使用struts2插件实现ajax处理(返回json数据)

    贴一个简单的例子,通过jquery的post调用action,定义一个对象User,有name和age属性,实例化几个对象,以json的格式返回到jsp,在前台页面显示出来,模拟用户列表. 导入相关j ...

  10. 使用phpize安装php扩展

    环境: CentOs 6.3 php 7 nginx 举例: 安装ssh2扩展 1.登陆http://pecl.php.net,搜索ssh2,如下图所示,注意版本的选择要根据php的版本来 2.下载s ...