PHP树的深度编历生成迷宫及A*自动寻路算法实例分析
本文实例讲述了PHP树的深度编历生成迷宫及A*自动寻路算法。分享给大家供大家参考。具体分析如下:
有一同事推荐了三思的迷宫算法,看了感觉还不错,就转成php
三思的迷宫算法是采用树的深度遍历原理,这样生成的迷宫相当的细,而且死胡同数量相对较少!
任意两点之间都存在唯一的一条通路。
至于A*寻路算法是最大众化的一全自动寻路算法
废话不多说,贴上带代码
迷宫生成类:
classMaze{ //MazeCreate private$_w; private$_h; private$_grids; private$_walkHistory; private$_walkHistory2; private$_targetSteps; //Construct publicfunctionMaze(){ $this->_w=6; $this->_h=6; $this->_grids=array(); } //设置迷宫大小 publicfunctionset($width=6,$height=6){ if($width>0)$this->_w=$width; if($height>0)$this->_h=$height; return$this; } //取到迷宫 publicfunctionget(){ return$this->_grids; } //生成迷宫 publicfunctioncreate(){ $this->_init(); return$this->_walk(rand(0,count($this->_grids)-1)); } //获取死胡同点 publicfunctionblock($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){ returnarray_pop($return); }else{ returnarray_slice($return,0,$n); } } /** |--------------------------------------------------------------- |生成迷宫的系列函数 |--------------------------------------------------------------- */ privatefunction_walk($startPos){ $this->_walkHistory=array(); $this->_walkHistory2=array(); $curPos=$startPos; while($this->_getNext0()!=-1){ $curPos=$this->_step($curPos); if($curPos===false)break; } return$this; } privatefunction_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; } privatefunction_noStep(){ $l=count($this->_targetSteps); for($i=0;$i<$l;$i++){ if($this->_targetSteps[$i]!=-1)returnfalse; } returntrue; } privatefunction_step($curPos){ $this->_targetSteps=$this->_getTargetSteps($curPos); if($this->_noStep()){ if(count($this->_walkHistory)>0){ $tmp=array_pop($this->_walkHistory); }else{ returnfalse; } 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; } privatefunction_isRepeating($p){ $l=count($this->_walkHistory); for($i=0;$i<$l;$i++){ if($this->_walkHistory[$i]==$p)returntrue; } $l=count($this->_walkHistory2); for($i=0;$i<$l;$i++){ if($this->_walkHistory2[$i]==$p)returntrue; } returnfalse; } privatefunction_getNext0(){ $l=count($this->_grids); for($i=0;$i<=$l;$i++){ if($this->_grids[$i]==0)return$i; } return-1; } privatefunction_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*寻路算法
classAStar{ //A-star private$_open; private$_closed; private$_start; private$_end; private$_grids; private$_w; private$_h; //Construct publicfunctionAStar(){ $this->_w=null; $this->_h=null; $this->_grids=null; } publicfunctionset($width,$height,$grids){ $this->_w=$width; $this->_h=$height; $this->_grids=$grids; return$this; } //迷宫中寻路 publicfunctionsearch($start=false,$end=false){ return$this->_search($start,$end); } /** |--------------------------------------------------------------- |自动寻路-A-star算法 |--------------------------------------------------------------- */ publicfunction_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->_openas$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; } privatefunction_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); } } privatefunction_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; } } privatefunction_getG($point){ returnabs($this->_start-$point); } privatefunction_getH($point){ returnabs($this->_end-$point); } }
完整实例代码点击此处本站下载。
有需要大家可以直接下demo,看看效果!
希望本文所述对大家的php程序设计有所帮助。