HTML 迷宮


今天補個遺,將很久以前研究 HTML5 的時候寫的生成迷宮、迷宮尋路程序整理出來。

下載鏈接在文章最后。

 

簡介

為什么要做這個 HTML5 迷宮程序?因為我喜歡、我願意。也是向老程序員學習(見第5節)。

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

怎么做的?主要參考了這幾篇文章:

How to build a maze?

這個網站提供在線的 Java Applet 示例,很直觀。

image

Labyrnth

Maze generation algorithm

Maze Generation

然后代碼自己寫,因為沒有可以照搬的,照搬的也不是按照我希望的方式去工作的。看明白原理之后,就開始設計自己的迷宮程序了。

 

原理

這是此次補遺最難的部分,因為我真的不記得是怎么做到的了!唯一有點兒印象的,是A*搜索算法,即包含當前探索節點與目標節點距離的估值函數的改進型A搜索算法,相當於對A搜索算法剪枝吧。我是這么認為的 Smile

在網頁上生成迷宮,主要解決下面幾個問題:

  • 生成迷宮
  • 挑選迷宮起點和終點
  • 探索迷宮
  • 繪制迷宮和探索結果(路徑)

前面3個問題,和 HTML 一毛錢關系都沒有。完全依靠數據結構和算法。你把數據結構和算法搬到 C# 里面去,用 WPF 畫迷宮也是可以的。

迷宮(尤其是矩形的)可以看作是很多個小格子,叫做 Cell,每個小格子都被牆(Wall)環繞,組合在一起。所以一開始,迷宮如果繪制出來,看上去應該是這樣的:

image

然后,從選定的起點開始,從周圍相鄰的 Cell 里面隨便挑選一個,打破這2個 Cell 之間的牆。接着,繼續,直到所有的 Cell  都被訪問過了。迷宮的生成大概就是這么個原理,當然,圓形、六角形的迷宮會有區別,這個方面,參考上面列出的 Wiki 上面的解釋最清楚了。

 

探索迷宮的話,需要先知道起點和終點(目標點)的 Cell 的坐標。在我的程序里面,起點 Cell (start_cell)是隨機挑選的,終點 Cell (goal_cell)則是指定的一個位置,這樣做只是為了讓出來的迷宮圖形比較好看,否則可能出現起點和終點太靠近,迷宮畫出來沒有“好復雜!”的感覺 Smile

為了避免盲目探索,每次從當前 Cell 開始挑選下一個鄰近的可以走通的  Cell 時,都會計算一個 g 值,也就是下一個 Cell 和目標 Cell 的距離值,這個值用來剪枝,距離小的,優先走。在我的程序里面,這個值是用 init_g_h_value 函數來計算的。為了提高迷宮處理速度,已經預先將所有節點的 g 值計算完畢,存在迷宮數組里面了,即用“空間換時間”是也。

有興趣的話,可以修改程序里面的 maze_g_value、maze_h_value 兩個參數變量的值,看看不同的效果,你會發現路徑會從松散到緊湊變化。

 

程序

先看網頁布局。雖然寫程序是從生成迷宮到探索到顯示的順序,但是,實現起來,要反過來,先把最終呈現效果給設計出來。

順便插一句:做軟件,可以沒有測試,可以沒有文檔,甚至可以沒有需求,但,你不能沒有設計。說得“極端”了點兒,但這只是為了強調“設計”的重要性。

IMG_1297

界面上有一個 canvas,一個 div。Canvas 用來繪制迷宮,div 用來輸出調試信息,將程序中 _debug_ 變量設置為 true 即可開啟。(_debug_ 作為全局變量,命名方式和其它全局變量不同,這是因為這個調試變量是我今天寫這篇博客時臨時加的,反映了我最近對於全局變量命名的口味。以前寫的,則是另外一種口味,人總是會變的嘛。)

 

下面是程序設計,

IMG_1299

這個迷宮程序需要 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一次就刷一個新的迷宮給你。紅色的點是起點,藍色的點是終點(目標點),紫色的點是探索過的路徑,綠色的點是最終走通的路徑。

image

 

下載

這里下載,只有一個 HTML 文件。另外還需要 jQuery(文件名是 jQuery-1.9.1.js,如果你用了其它版本的 jQuery,請到 maze.html 里面對應修改) 和 excanvas 文件,和我的迷宮程序網頁放在一個目錄即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM