php A*从迷宫迈向光明

来源:互联网 发布:我国机电产品出口数据 编辑:程序博客网 时间:2024/05/16 15:06
  1. /** 生成迷宫类 
  2.  * @date 2015-07-10 
  3.  * @edit http://www.lai18.com 
  4.  * @version 1 
  5.  **/  
  6. class Maze{  
  7.   
  8.     // Maze Create  
  9.   
  10.     private $_w;  
  11.   
  12.     private $_h;  
  13.   
  14.     private $_grids;  
  15.   
  16.     private $_walkHistory;  
  17.   
  18.     private $_walkHistory2;  
  19.   
  20.     private $_targetSteps;  
  21.   
  22.     // Construct  
  23.   
  24.     public function Maze() {  
  25.   
  26.         $this->_w = 6;  
  27.   
  28.         $this->_h = 6;  
  29.   
  30.         $this->_grids = array();  
  31.   
  32.     }  
  33.   
  34.     // 设置迷宫大小  
  35.   
  36.     public function set($width = 6, $height = 6) {  
  37.   
  38.         if ( $width > 0 ) $this->_w = $width;  
  39.   
  40.         if ( $height > 0 ) $this->_h = $height;  
  41.   
  42.         return $this;  
  43.   
  44.     }  
  45.   
  46.     // 取到迷宫  
  47.   
  48.     public function get() {  
  49.   
  50.         return $this->_grids;  
  51.   
  52.     }  
  53.   
  54.     // 生成迷宫  
  55.   
  56.     public function create() {  
  57.   
  58.         $this->_init();  
  59.   
  60.         return $this->_walk(rand(0, count($this->_grids) -1 ));  
  61.   
  62.     }  
  63.   
  64.     // 获取死胡同点  
  65.   
  66.     public function block($n = 0, $rand = false) {  
  67.   
  68.         $l = count($this->_grids);  
  69.   
  70.         for$i = 1; $i < $l$i++ ) {  
  71.   
  72.             $v = $this->_grids[$i];  
  73.   
  74.             if ( $v == 1 || $v == 2 || $v == 4 || $v == 8 ) {  
  75.   
  76.                 $return[] = $i;  
  77.   
  78.             }  
  79.   
  80.         }  
  81.   
  82.         // 随机取点  
  83.   
  84.         if ( $rand ) shuffle($return);  
  85.   
  86.    
  87.   
  88.         if ( $n == 0 ) return $return;  
  89.   
  90.    
  91.   
  92.         if ( $n == 1 ) {  
  93.   
  94.             return array_pop($return);  
  95.   
  96.         } else {  
  97.   
  98.             return array_slice($return, 0, $n);  
  99.   
  100.         }  
  101.   
  102.     }  
  103.   
  104.     /** 
  105.  
  106.     生成迷宫的系列函数 
  107.  
  108.     */  
  109.   
  110.     private function _walk($startPos) {  
  111.   
  112.         $this->_walkHistory = array();  
  113.   
  114.         $this->_walkHistory2 = array();  
  115.   
  116.         $curPos = $startPos;  
  117.   
  118.         while ($this->_getNext0() != -1) {  
  119.   
  120.             $curPos = $this->_step($curPos);  
  121.   
  122.             if ( $curPos === false ) break;  
  123.   
  124.         }  
  125.   
  126.         return $this;  
  127.   
  128.     }  
  129.   
  130.     private function _getTargetSteps($curPos) {  
  131.   
  132.         $p = 0;  
  133.   
  134.         $a = array();  
  135.   
  136.         $p = $curPos - $this->_w;  
  137.   
  138.         if ($p > 0 && $this->_grids[$p] === 0 && ! $this->_isRepeating($p)) {  
  139.   
  140.             array_push($a$p);  
  141.   
  142.         } else {  
  143.   
  144.             array_push($a, -1);  
  145.   
  146.         }  
  147.   
  148.         $p = $curPos + 1;  
  149.   
  150.         if ($p % $this->_w != 0 && $this->_grids[$p] === 0 && ! $this->_isRepeating($p)) {  
  151.   
  152.             array_push($a$p);  
  153.   
  154.         } else {  
  155.   
  156.             array_push($a, -1);  
  157.   
  158.         }  
  159.   
  160.         $p = $curPos + $this->_w;  
  161.   
  162.         if ($p < count($this->_grids) && $this->_grids[$p] === 0 && ! $this->_isRepeating($p)) {  
  163.   
  164.             array_push($a$p);  
  165.   
  166.         } else {  
  167.   
  168.             array_push($a, -1);  
  169.   
  170.         }  
  171.   
  172.         $p = $curPos - 1;  
  173.   
  174.         if (($curPos % $this->_w) != 0 && $this->_grids[$p] === 0 && ! $this->_isRepeating($p)) {  
  175.   
  176.             array_push($a$p);  
  177.   
  178.         } else {  
  179.   
  180.             array_push($a, -1);  
  181.   
  182.         }  
  183.   
  184.         return $a;  
  185.   
  186.     }  
  187.   
  188.     private function _noStep() {  
  189.   
  190.         $l = count($this->_targetSteps);  
  191.   
  192.         for ($i = 0; $i < $l$i ++) {  
  193.   
  194.             if ($this->_targetSteps[$i] != -1) return false;  
  195.   
  196.         }  
  197.   
  198.         return true;  
  199.   
  200.     }  
  201.   
  202.     private function _step($curPos) {  
  203.   
  204.         $this->_targetSteps = $this->_getTargetSteps($curPos);  
  205.   
  206.         if ( $this->_noStep() ) {  
  207.   
  208.             if ( count($this->_walkHistory) > 0 ) {  
  209.   
  210.                 $tmp = array_pop($this->_walkHistory);  
  211.   
  212.             } else {  
  213.   
  214.                 return false;  
  215.   
  216.             }  
  217.   
  218.             array_push($this->_walkHistory2, $tmp);  
  219.   
  220.             return $this->_step($tmp);  
  221.   
  222.         }  
  223.   
  224.         $r = rand(0, 3);  
  225.   
  226.         while ( $this->_targetSteps[$r] == -1) {  
  227.   
  228.             $r = rand(0, 3);  
  229.   
  230.         }  
  231.   
  232.         $nextPos = $this->_targetSteps[$r];  
  233.   
  234.         $isCross = false;  
  235.   
  236.         if ( $this->_grids[$nextPos] != 0)  
  237.   
  238.             $isCross = true;  
  239.   
  240.         if ($r == 0) {  
  241.   
  242.             $this->_grids[$curPos] ^= 1;  
  243.   
  244.             $this->_grids[$nextPos] ^= 4;  
  245.   
  246.         } elseif ($r == 1) {  
  247.   
  248.             $this->_grids[$curPos] ^= 2;  
  249.   
  250.             $this->_grids[$nextPos] ^= 8;  
  251.   
  252.         } elseif ($r == 2) {  
  253.   
  254.             $this->_grids[$curPos] ^= 4;  
  255.   
  256.             $this->_grids[$nextPos] ^= 1;  
  257.   
  258.         } elseif ($r == 3) {  
  259.   
  260.             $this->_grids[$curPos] ^= 8;  
  261.   
  262.             $this->_grids[$nextPos] ^= 2;  
  263.   
  264.         }  
  265.   
  266.         array_push($this->_walkHistory, $curPos);  
  267.   
  268.         return $isCross ? false : $nextPos;  
  269.   
  270.     }  
  271.   
  272.     private function _isRepeating($p) {  
  273.   
  274.         $l = count($this->_walkHistory);  
  275.   
  276.         for ($i = 0; $i < $l$i ++) {  
  277.   
  278.             if ($this->_walkHistory[$i] == $preturn true;  
  279.   
  280.         }  
  281.   
  282.         $l = count($this->_walkHistory2);  
  283.   
  284.         for ($i = 0; $i < $l$i ++) {  
  285.   
  286.             if ($this->_walkHistory2[$i] == $preturn true;  
  287.   
  288.         }  
  289.   
  290.         return false;  
  291.   
  292.     }  
  293.   
  294.     private function _getNext0() {  
  295.   
  296.         $l = count($this->_grids);  
  297.   
  298.    
  299.   
  300.         for ($i = 0; $i <= $l$i++ ) {  
  301.   
  302.             if ( $this->_grids[$i] == 0) return $i;  
  303.   
  304.         }  
  305.   
  306.         return -1;  
  307.   
  308.     }  
  309.   
  310.     private function _init() {  
  311.   
  312.         $this->_grids = array();  
  313.   
  314.         for ($y = 0; $y < $this->_h; $y ++) {  
  315.   
  316.             for ($x = 0; $x < $this->_w; $x ++) {  
  317.   
  318.                 array_push($this->_grids, 0);  
  319.   
  320.             }  
  321.   
  322.         }  
  323.   
  324.         return $this;  
  325.   
  326.     }  
  327.   
  328. }  

A*寻路算法

[php] view plaincopy
  1. /** 寻路算法 
  2.  * @date 2015-07-10 
  3.  * @edit http://www.lai18.com 
  4.  * @version 1 
  5.  **/  
  6. class AStar{  
  7.   
  8.     // A-star  
  9.   
  10.     private $_open;  
  11.   
  12.     private $_closed;  
  13.   
  14.     private $_start;  
  15.   
  16.     private $_end;  
  17.   
  18.     private $_grids;  
  19.   
  20.     private $_w;  
  21.   
  22.     private $_h;  
  23.   
  24.     // Construct  
  25.   
  26.     public function AStar(){  
  27.   
  28.         $this->_w = null;  
  29.   
  30.         $this->_h = null;  
  31.   
  32.         $this->_grids = null;  
  33.   
  34.     }  
  35.   
  36.     public function set($width$height$grids) {  
  37.   
  38.         $this->_w = $width;  
  39.   
  40.         $this->_h = $height;  
  41.   
  42.         $this->_grids = $grids;  
  43.   
  44.         return $this;  
  45.   
  46.     }  
  47.   
  48.     // 迷宫中寻路  
  49.   
  50.     public function search($start = false, $end = false) {  
  51.   
  52.         return $this->_search($start$end);  
  53.   
  54.     }  
  55.   
  56.     /** 
  57.  
  58.     自动寻路 - A-star 算法 
  59.  
  60.        */  
  61.   
  62.     public function _search($start = false, $end = false) {  
  63.   
  64.         if ( $start !== false ) $this->_start = $start;  
  65.   
  66.         if ( $end !== false ) $this->_end = $end;  
  67.   
  68.         $_sh = $this->_getH($start);  
  69.   
  70.         $point['i'] = $start;  
  71.   
  72.         $point['f'] = $_sh;  
  73.   
  74.         $point['g'] = 0;  
  75.   
  76.         $point['h'] = $_sh;  
  77.   
  78.         $point['p'] = null;  
  79.   
  80.         $this->_open[] = $point;  
  81.   
  82.         $this->_closed[$start] = $point;  
  83.   
  84.         while ( 0 < count($this->_open) ) {  
  85.   
  86.             $minf = false;  
  87.   
  88.             foreach$this->_open as $key => $maxNode ) {  
  89.   
  90.                 if ( $minf === false || $minf > $maxNode['f'] ) {  
  91.   
  92.                     $minIndex = $key;  
  93.   
  94.                 }  
  95.   
  96.             }  
  97.   
  98.             $nowNode = $this->_open[$minIndex];  
  99.   
  100.             unset($this->_open[$minIndex]);  
  101.   
  102.             if ( $nowNode['i'] == $this->_end ) {  
  103.   
  104.                 $tp = array();  
  105.   
  106.                 while$nowNode['p'] !== null ) {  
  107.   
  108.                     array_unshift($tp$nowNode['p']);  
  109.   
  110.                     $nowNode = $this->_closed[$nowNode['p']];  
  111.   
  112.                 }  
  113.   
  114.                 array_push($tp$this->_end);  
  115.   
  116.                 break;  
  117.   
  118.             }  
  119.   
  120.             $this->_setPoint($nowNode['i']);  
  121.   
  122.         }  
  123.   
  124.         $this->_closed = array();  
  125.   
  126.         $this->_open = array();  
  127.   
  128.         return $tp;  
  129.   
  130.     }  
  131.   
  132.     private function _setPoint($me) {  
  133.   
  134.         $point = $this->_grids[$me];  
  135.   
  136.         // 所有可选方向入队列  
  137.   
  138.         if ( $point & 1 ) {  
  139.   
  140.             $next = $me - $this->_w;  
  141.   
  142.             $this->_checkPoint($me$next);  
  143.   
  144.         }  
  145.   
  146.         if ( $point & 2 ) {  
  147.   
  148.             $next = $me + 1;  
  149.   
  150.             $this->_checkPoint($me$next);  
  151.   
  152.         }  
  153.   
  154.         if ( $point & 4 ) {  
  155.   
  156.             $next = $me + $this->_w;  
  157.   
  158.             $this->_checkPoint($me$next);  
  159.   
  160.         }  
  161.   
  162.         if ( $point & 8 ) {  
  163.   
  164.             $next = $me - 1;  
  165.   
  166.             $this->_checkPoint($me$next);  
  167.   
  168.         }  
  169.   
  170.     }  
  171.   
  172.     private function _checkPoint($pNode$next) {  
  173.   
  174.         if ( $this->_closed[$next] ) {  
  175.   
  176.             $_g = $this->_closed[$pNode]['g'] + $this->_getG($next);  
  177.   
  178.             if ( $_g < $check['g'] ) {  
  179.   
  180.                 $this->_closed[$next]['g'] = $_g;  
  181.   
  182.                 $this->_closed[$next]['f'] = $this->_closed[$next]['g'] + $this->_closed[$next]['h'];  
  183.   
  184.                 $this->_closed[$next]['p'] = $pNode;  
  185.   
  186.             }  
  187.   
  188.         } else {  
  189.   
  190.             $point['p'] = $pNode;  
  191.   
  192.             $point['h'] = $this->_getH($next);  
  193.   
  194.             $point['g'] = $this->_getG($next);  
  195.   
  196.             $point['f'] = $point['h'] + $point['g'];  
  197.   
  198.             $point['i'] = $next;  
  199.   
  200.             $this->_open[] = $point;  
  201.   
  202.             $this->_closed[$next] = $point;  
  203.   
  204.         }  
  205.   
  206.     }  
  207.   
  208.     private function _getG($point) {  
  209.   
  210.         return abs($this->_start - $point);  
  211.   
  212.     }  
  213.   
  214.     private function _getH($point) {  
  215.   
  216.         return abs($this->_end - $point);  
  217.   
  218.     }  
  219.   

0 0
原创粉丝点击