迷宫算法实现(php)

来源:互联网 发布:打击网络违法犯罪 编辑:程序博客网 时间:2024/05/21 10:29

【迷宫算法的实现】

一、条件设计

1.使用由1包围的矩阵实现,0表示为路,1表示为墙,有且仅有一个入口和出口。

2.路况判断:

1)通路,该结点有且仅有一条路可走,即=1

2)死路,该结点无路可走了,即=0

3)路口,该结点至少有一条路可走,即>1

3.如果该结点是路口,则按照顺时针方向选择下一条要走的路。

4.不能走回头路,即走过的路不能再往回走了。


二、算法实现

1.如果该结点是通路,则继续前行。

2.如果该结点是路口,则按顺时针方向选择一条路前行,并记录该结点为路口的信息(包括来到该结点时的方向、该结点的坐标等)。

3.如果该结点时死路,则返回到上一个路口,选择下一条路前行;如果该路口的所有路都已经走过了,那么就返回到上上个路口继续。


三、问题解决

1.解决不能回头的问题

方法一:如果该结点是通路,则继续前行,并设置该结点为1;如果该结点是死路,则设置该结点为1,并返回到上个路口。

方法二:记录来到该结点时的方向,在判断路况时,直接忽略来时的方向即可。

2.返回到上个路口

使用栈来记录该结点为路口的信息,当返回到上个路口时,即路口的出栈。


以下是迷宫算法的初步实现(PHP),写的比较繁琐,先实现了,再做进一步优化:

1、判断该点是否路口,是,则记录该点位置和方向

2、判断该结点是否死路,是则返回至上个路口

3、方向不变,进行试探,如果下一结点是墙,则按顺时针改变方向,进行试探

4、如果下一结点不是墙,则前进,递归调用


<?php/*构造迷宫二维数组*///迷宫一for ($l=0;$l<=5;$l++){for ($m=0;$m<=5;$m++){if ($l==1 && $m<=3)$arr[$l][$m]=0;elseif ($l==2 && ($m==1||$m==3||$m==4))$arr[$l][$m]=0;elseif ($l==3 && $m<=4 && $m!=0 &&$m!=3)$arr[$l][$m]=0;elseif ($l==4 && ($m==1||$m>=4))$arr[$l][$m]=0;else$arr[$l][$m]=1;echo $arr[$l][$m].' ';}echo '<br/>';}echo '<br/><br/><br/><font color="red">算法的实现:</font><br/>';function path($i,$j,$dir,$arr,$iline,$jline,$dirline){//判断是否结束if ($i==4 && $j==5) return 1;$ifdirs = 0;$newdir = $dir;$lastdir = $dir;//如果该点为0,则前进if ($arr[$i][$j] == 0){ //判断方向增量switch ($dir){case 0: $ii=0;$jj=1;break;case 1: $ii=1;$jj=0;break;case 2: $ii=0;$jj=-1;break;case 3: $ii=-1;$jj=0;break;}//判断是否路口for ($n=1;$n<=4;$n++){switch ($newdir){case 0: $aa=0;$bb=1;break;case 1: $aa=1;$bb=0;break;case 2: $aa=0;$bb=-1;break;case 3: $aa=-1;$bb=0;break;}if ($arr[($i+$aa)][($j+$bb)]==0){$ifdirs++;}$newdir = ($newdir + 1)%4;}//判断是否路口,是则记录位置和方向if ($ifdirs>2){if (in_array($i,$iline)&&in_array($j,$jline)){}else{echo "该点是路口:<$i,$j,$dir><br/>";$iline[] = $i;$jline[] = $j;$dirline[] = $dir;}}if ($ifdirs>1){//不是死路,前进if($arr[($i+$ii)][($j+$jj)]==0){//方向不变,可以前进$i += $ii;$j += $jj;echo "方向不变,可以前进:$i,$j,$dir<br/>";path($i,$j,$dir,$arr,$iline,$jline,$dirline);}else{//方向改变,试探if ($ifdirs>2){//该点是路口,取来时方向为路口记录方向$lastdir = $dirline[(count($dirline)-1)];}else{//不是路口,则在改变方向前记录方向$lastdir = $dir;}//判断来时方向,不能走回头路switch($lastdir){case 0: $errdir=2;break;case 1: $errdir=3;break;case 2: $errdir=0;break;case 3: $errdir=1;break;}//改变方向$dir = ($dir + 1)%4;//判断改变后方向是否为来时方向echo "不能走回头路:err:$errdir,dir:$dir<br/>";if ($dir != $errdir){echo "turn:($i,$j,$dir)<br/>";switch ($dir){case 0: $mm=0;$nn=1;break;case 1: $mm=1;$nn=0;break;case 2: $mm=0;$nn=-1;break;case 3: $mm=-1;$nn=0;break;}if($arr[($i+$mm)][($j+$nn)]==0){$i += $mm;$j += $nn;echo "可以前进:$i,$j,$dir<br/>";path($i,$j,$dir,$arr,$iline,$jline,$dirline);}else{$dir = ($dir + 1)%4;echo "再改变方向,试探:$i,$j,$dir<br/>";if ($dir != $errdir){echo "turn:($i,$j,$dir)<br/>";switch ($dir){case 0: $ii=0;$jj=1;break;case 1: $ii=1;$jj=0;break;case 2: $ii=0;$jj=-1;break;case 3: $ii=-1;$jj=0;break;}if($arr[($i+$ii)][($j+$jj)]==0){$i += $ii;$j += $jj;echo "可以前进:$i,$j,$dir<br/>";path($i,$j,$dir,$arr,$iline,$jline,$dirline);}}else{$dir = ($dir + 1)%4;echo "再改变方向,试探:$i,$j,$dir<br/>";switch ($dir){case 0: $ii=0;$jj=1;break;case 1: $ii=1;$jj=0;break;case 2: $ii=0;$jj=-1;break;case 3: $ii=-1;$jj=0;break;}if($arr[($i+$ii)][($j+$jj)]==0){$i += $ii;$j += $jj;echo "OK:$i,$j,$dir<br/>";path($i,$j,$dir,$arr,$iline,$jline,$dirline);}}}}else{$dir = ($dir + 1)%4;echo "不能回头,再改变方向,试探:$i,$j,$dir<br/>";switch ($dir){case 0: $ii=0;$jj=1;break;case 1: $ii=1;$jj=0;break;case 2: $ii=0;$jj=-1;break;case 3: $ii=-1;$jj=0;break;}if($arr[($i+$ii)][($j+$jj)]==0){$i += $ii;$j += $jj;echo "可以前进:$i,$j,$dir<br/>";path($i,$j,$dir,$arr,$iline,$jline,$dirline);}}}}else{//是死路,需要返回到上个路口,改变方向,试探$dir = $dirline[(count($dirline)-1)];$i = $iline[(count($iline)-1)];$j = $jline[(count($jline)-1)];echo "是死路,返回到上个路口,记录为:#$i,$j,$dir#<br/>";$dir = ($dir + 1)%4;path($i,$j,$dir,$arr,$iline,$jline,$dirline);}}}$a[]=$b[]=$c[]=0;echo '初始值=>节点:($i=1,$j=1),方向:($dir=0).<br/><br/>';path(1,1,0,$arr,$a,$b,$c);?>