標籤:演算法 遍曆
PHP樹產生迷宮及A*自動尋路演算法
迷宮演算法是採用樹的深度遍曆原理,這樣產生的迷宮相當的細,而且死胡同數量相對較少!
任意兩點之間都存在唯一的一條通路。
至於A*尋路演算法是最福士化的一全自動尋路演算法
完整代碼已上傳,http://download.csdn.net/detail/hello_katty/8885779 ,此處做些簡單解釋,還需要大家自己思考動手。廢話不多說,貼上帶代碼迷宮產生類:
/** 產生迷宮類 * @date 2015-07-10 * @edit http://www.lai18.com * @version 1 **/class Maze{ // Maze Create private $_w; private $_h; private $_grids; private $_walkHistory; private $_walkHistory2; private $_targetSteps; // Construct public function Maze() { $this->_w = 6; $this->_h = 6; $this->_grids = array(); } // 設定迷宮大小 public function set($width = 6, $height = 6) { if ( $width > 0 ) $this->_w = $width; if ( $height > 0 ) $this->_h = $height; return $this; } // 取到迷宮 public function get() { return $this->_grids; } // 產生迷宮 public function create() { $this->_init(); return $this->_walk(rand(0, count($this->_grids) -1 )); } // 擷取死胡同點 public function block($n = 0, $rand = false) { $l = count($this->_grids); for( $i = 1; $i < $l; $i++ ) { $v = $this->_grids[$i]; if ( $v == 1 || $v == 2 || $v == 4 || $v == 8 ) { $return[] = $i; } } // 隨機取點 if ( $rand ) shuffle($return); if ( $n == 0 ) return $return; if ( $n == 1 ) { return array_pop($return); } else { return array_slice($return, 0, $n); } } /** 產生迷宮的系列函數 */ private function _walk($startPos) { $this->_walkHistory = array(); $this->_walkHistory2 = array(); $curPos = $startPos; while ($this->_getNext0() != -1) { $curPos = $this->_step($curPos); if ( $curPos === false ) break; } return $this; } private function _getTargetSteps($curPos) { $p = 0; $a = array(); $p = $curPos - $this->_w; if ($p > 0 && $this->_grids[$p] === 0 && ! $this->_isRepeating($p)) { array_push($a, $p); } else { array_push($a, -1); } $p = $curPos + 1; if ($p % $this->_w != 0 && $this->_grids[$p] === 0 && ! $this->_isRepeating($p)) { array_push($a, $p); } else { array_push($a, -1); } $p = $curPos + $this->_w; if ($p < count($this->_grids) && $this->_grids[$p] === 0 && ! $this->_isRepeating($p)) { array_push($a, $p); } else { array_push($a, -1); } $p = $curPos - 1; if (($curPos % $this->_w) != 0 && $this->_grids[$p] === 0 && ! $this->_isRepeating($p)) { array_push($a, $p); } else { array_push($a, -1); } return $a; } private function _noStep() { $l = count($this->_targetSteps); for ($i = 0; $i < $l; $i ++) { if ($this->_targetSteps[$i] != -1) return false; } return true; } private function _step($curPos) { $this->_targetSteps = $this->_getTargetSteps($curPos); if ( $this->_noStep() ) { if ( count($this->_walkHistory) > 0 ) { $tmp = array_pop($this->_walkHistory); } else { return false; } array_push($this->_walkHistory2, $tmp); return $this->_step($tmp); } $r = rand(0, 3); while ( $this->_targetSteps[$r] == -1) { $r = rand(0, 3); } $nextPos = $this->_targetSteps[$r]; $isCross = false; if ( $this->_grids[$nextPos] != 0) $isCross = true; if ($r == 0) { $this->_grids[$curPos] ^= 1; $this->_grids[$nextPos] ^= 4; } elseif ($r == 1) { $this->_grids[$curPos] ^= 2; $this->_grids[$nextPos] ^= 8; } elseif ($r == 2) { $this->_grids[$curPos] ^= 4; $this->_grids[$nextPos] ^= 1; } elseif ($r == 3) { $this->_grids[$curPos] ^= 8; $this->_grids[$nextPos] ^= 2; } array_push($this->_walkHistory, $curPos); return $isCross ? false : $nextPos; } private function _isRepeating($p) { $l = count($this->_walkHistory); for ($i = 0; $i < $l; $i ++) { if ($this->_walkHistory[$i] == $p) return true; } $l = count($this->_walkHistory2); for ($i = 0; $i < $l; $i ++) { if ($this->_walkHistory2[$i] == $p) return true; } return false; } private function _getNext0() { $l = count($this->_grids); for ($i = 0; $i <= $l; $i++ ) { if ( $this->_grids[$i] == 0) return $i; } return -1; } private function _init() { $this->_grids = array(); for ($y = 0; $y < $this->_h; $y ++) { for ($x = 0; $x < $this->_w; $x ++) { array_push($this->_grids, 0); } } return $this; }}
A*尋路演算法
/** 尋路演算法 * @date 2015-07-10 * @edit http://www.lai18.com * @version 1 **/class AStar{ // A-star private $_open; private $_closed; private $_start; private $_end; private $_grids; private $_w; private $_h; // Construct public function AStar(){ $this->_w = null; $this->_h = null; $this->_grids = null; } public function set($width, $height, $grids) { $this->_w = $width; $this->_h = $height; $this->_grids = $grids; return $this; } // 迷宮中尋路 public function search($start = false, $end = false) { return $this->_search($start, $end); } /** 自動尋路 - A-star 演算法 */ public function _search($start = false, $end = false) { if ( $start !== false ) $this->_start = $start; if ( $end !== false ) $this->_end = $end; $_sh = $this->_getH($start); $point[‘i‘] = $start; $point[‘f‘] = $_sh; $point[‘g‘] = 0; $point[‘h‘] = $_sh; $point[‘p‘] = null; $this->_open[] = $point; $this->_closed[$start] = $point; while ( 0 < count($this->_open) ) { $minf = false; foreach( $this->_open as $key => $maxNode ) { if ( $minf === false || $minf > $maxNode[‘f‘] ) { $minIndex = $key; } } $nowNode = $this->_open[$minIndex]; unset($this->_open[$minIndex]); if ( $nowNode[‘i‘] == $this->_end ) { $tp = array(); while( $nowNode[‘p‘] !== null ) { array_unshift($tp, $nowNode[‘p‘]); $nowNode = $this->_closed[$nowNode[‘p‘]]; } array_push($tp, $this->_end); break; } $this->_setPoint($nowNode[‘i‘]); } $this->_closed = array(); $this->_open = array(); return $tp; } private function _setPoint($me) { $point = $this->_grids[$me]; // 所有可選方向入隊列 if ( $point & 1 ) { $next = $me - $this->_w; $this->_checkPoint($me, $next); } if ( $point & 2 ) { $next = $me + 1; $this->_checkPoint($me, $next); } if ( $point & 4 ) { $next = $me + $this->_w; $this->_checkPoint($me, $next); } if ( $point & 8 ) { $next = $me - 1; $this->_checkPoint($me, $next); } } private function _checkPoint($pNode, $next) { if ( $this->_closed[$next] ) { $_g = $this->_closed[$pNode][‘g‘] + $this->_getG($next); if ( $_g < $check[‘g‘] ) { $this->_closed[$next][‘g‘] = $_g; $this->_closed[$next][‘f‘] = $this->_closed[$next][‘g‘] + $this->_closed[$next][‘h‘]; $this->_closed[$next][‘p‘] = $pNode; } } else { $point[‘p‘] = $pNode; $point[‘h‘] = $this->_getH($next); $point[‘g‘] = $this->_getG($next); $point[‘f‘] = $point[‘h‘] + $point[‘g‘]; $point[‘i‘] = $next; $this->_open[] = $point; $this->_closed[$next] = $point; } } private function _getG($point) { return abs($this->_start - $point); } private function _getH($point) { return abs($this->_end - $point); }}
延伸閱讀
《編程實用演算法實現整理》系列技術文章整理收藏
1演算法導論:選擇排序的原理與實現
2一道PHP冒泡排序演算法筆試題
3WordPress的使用者密碼計算演算法
4PHP實現四種常用的排序演算法
5非常直觀的資料結構與演算法示範
6深入探討各種背包演算法問題
7圖解插入排序演算法
8圖解堆排序Heap Sort演算法
9約瑟夫環(Josephus)問題的C++演算法類比
10趣味演算法之兔子產子問題
11一些常見演算法的JavaScript實現
12趣味演算法之猴子吃桃問題
13平方根sqrt()函數的底層演算法效率
14二叉搜尋樹的一些相關演算法介紹
15歐幾裡德演算法(輾轉相處法)練手
16螞蟻爬木杆問題的演算法思路
17電腦編程中一些重要的演算法
18面試中常見的一些演算法問題
19JavaScript排序演算法之希爾排序
20JavaScript排序演算法之堆排序
21JavaScript排序演算法之歸併排序
22JavaScript排序演算法之選擇排序
23JavaScript排序演算法之快速排序
24JavaScript排序演算法之冒泡排序
25JavaScript排序演算法之插入排序
26合并排序演算法解說與例子
27醜數Ugly Number尋找演算法
28求大數階乘的演算法
29各排序演算法的C++實現與效能測試
30演算法導論中一個蒙提霍爾問題
31實現一個棧並擷取其最小元素
32親身體驗一下KMP演算法
33面試演算法題的快速思考方法
34矩陣逆時針旋轉的演算法
35Hash魔法:分布式雜湊演算法
36Hash魔法:一致性 hash 演算法
37字串逆序的各種實現演算法
38用遞迴實現的快速排序
39收集一些top軟體公司經典演算法面試題
40趣味演算法:猴子搬香蕉問題
41一些主流的個人化推薦演算法評析
42趣味演算法:生男生女的比例
43趣味演算法:老鼠試毒瓶問題
44使用PHP內建的DES演算法函數實現資料加密解密
45第九話:資料結構與演算法的關係
46第12話:什麼樣的演算法才是好演算法
47第11話:演算法的五個基本特徵
48第13話:演算法的效能分析
49第10話:什麼是演算法?
50第16話:演算法的空間複雜度
51第15話:演算法的最壞情況與平均情況
52第14話:如何計算演算法的時間複雜度
53順序棧的進棧操作
54順序棧:棧的順序儲存結構
55棧的定義與大概理解
56棧的抽象資料類型ADT
57鏈棧:棧的鏈式儲存結構
58鏈棧的進棧操作
59擷取順序棧的棧頂元素
60順序棧的出棧操作
61為什麼要使用棧這種資料結構
62鏈棧的置空操作與判斷鏈棧是否為空白
63遞迴,棧的重要應用之一
64棧是如何?遞迴的
65鏈棧的出棧操作
66鏈棧的初始化與遍曆
67漫談遞迴:遞迴的思想
68漫談遞迴:遞迴需要滿足的兩個條件
69漫談遞迴:字串迴文現象的遞迴判斷
70漫談遞迴:二分尋找演算法的遞迴實現
71漫談遞迴:遞迴的效率問題
72漫談遞迴:遞迴與迴圈
73漫談遞迴:迴圈與迭代是一回事嗎?
74漫談遞迴:從斐波那契開始瞭解尾遞迴
75漫談遞迴:尾遞迴與CPS
76漫談遞迴:補充一些Continuation的知識
77漫談遞迴:PHP裡的尾遞迴及其最佳化
78漫談遞迴:從彙編看尾遞迴的最佳化
79快速排序裡的學問:從猜數字開始
80快速排序裡的學問:再看看稱球問題
81快速排序裡的學問:資訊熵
82快速排序裡的學問:快速排序的過程
83快速排序裡的學問:霍爾與快速排序
84快速排序裡的學問:霍爾快排的實現
85快速排序裡的學問:樞紐元選擇與演算法效率
86快速排序裡的學問:隨機化快排
87Java程式員必須掌握的8大排序演算法
88RSA,DSA等加解密演算法介紹
89許可權項目總結(一)許可權設計
延伸閱讀
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
PHP樹產生迷宮及A*自動尋路演算法