迷宫求解,可以用穷举法,将每个点的方向都穷举完;由于在求解过程中会遇到某一方向不可通过,此时就必须按原路返回。

  想到用Perl数组来保存路径,记录每次所探索的方向,方便原路返回时得到上一步的方向,再退回到可以通过的方向,继续探索,直到终点或者最终无法到达,正常退出程序为止。

求解过程的关键思想:
1、由于需要标记下一位置是否已探索,需要一个数组用来记录每个点是否可通过;

  定义如:0--未经过 1--已走 2--不可通过

2、原路返回需要知道回退到哪个点,那么每一步要记录当前坐标;

3、采用深度优先搜索路径,每一步需记录搜索方向;

  采用HASH表:{ coordinate=>[y,x] , direct=>'UP' }

4、用数组保存每一步,数组下标即代表当前步

关键算法:

  北上,撞墙后原路返回,取出数组末元素,判断方向是否已搜索;已搜索完毕,继续原路返回;未搜索完,进行下个方向搜索,当前点放到数组尾。

  循环。

5、算法伪码:  

do{
if(当前点未经过){
设置已走
将当前位置的坐标、方向保存
if(当前点为终点){
修改迷宫的数据,记录所走的路线
return
}
当前步增一
新的坐标点=当前坐标+移动方向
}
else{ # 当前位置走不通
if(数组非空){
取出当前步
while(当前位置所走方向已搜索 && 数组非空){
记录当前位置不可通过
取出上一步状态
原路返回
}
if(当前的位置搜索方向小于4){
当前位置的方向增一
数组重新记录当前步数
新的坐标点=当前坐标+移动方向
}
}
}
}while(数组非空)

  初始化迷宫:

    

  初始化标记数组: 2、不可通过    0、未经过

    

  路径:从蛇头到蛇尾

    

代码如下:

use strict;
use constant {WIDTH=>,HEIGHT=>,DEBUG=>,};
my %uldr=(=>[-,],
=>[,-],
=>[,],
=>[,],); # 上、左、下、右
my @bg=();
for(my $y=;$y<HEIGHT;$y++){
for( my $x= ; $x<WIDTH ; $x++ ){
if( $y == || $y == HEIGHT- ||
$x == || $x == WIDTH- ){
$bg[$y][$x] = '*';
}
else{
$bg[$y][$x] = ' ';
}
}
} # 初始化迷宫 my @tmp=( [,],[,],[,],[,],[,],[,],[,], ); # 障碍物坐标
map{ $bg[ $tmp[$_][] ][ $tmp[$_][] ] = '#' } ..$#tmp-1;
$bg[ $tmp[][] ][ $tmp[][] ] = '@';
print @$_,"\n" foreach(@bg); my @bg_ghost=map{ [ split('','0'x (WIDTH)) ] }..(HEIGHT-); # 0--未经过 1--已走 2--不可通过
map{ my $y=$_;map { $bg_ghost[$y][$_] = ( $bg[$y][$_] eq '#' || $bg[$y][$_] eq '*')?: }..$#{$bg[0]} }0..$#bg; # 障碍物设置不可通过 print @$_,"\n" foreach(@bg_ghost);
print "-"x15,"\n"; sub handle{
my @path=(); # 存放步数的数组
my $cur_position=[ $tmp[][] , $tmp[][] ]; # 起点
my $end=[ $tmp[-][] , $tmp[-][] ]; # 终点
my ($step,$p_step)=(,''); # 步数、指向数组元素的指针
do{
if($bg_ghost[ $cur_position->[] ][ $cur_position->[] ] == ){ # 当前位置未经过
$bg_ghost[ $cur_position->[] ][ $cur_position->[] ]=; # 设置当前位置已走
$path[$step]={step=>$step,
coordinate=>[$cur_position->[],$cur_position->[]],
direct=>,
}; # 保存当前位置信息:坐标、方向
print "path[$step]:$path[$step]:",$path[$step]->{step},"\n" if DEBUG;
print " (y,x):(",$cur_position->[],",",$cur_position->[],")\n" if DEBUG;
if( $cur_position->[]==$end->[] && $cur_position->[]==$end->[]){
my @arr=('A'..'Z','a'..'z');
foreach(..$#path){
$bg[ $path[$_]->{coordinate}->[] ][ $path[$_]->{coordinate}->[] ] = $arr[$_];
}
return ;
}
$step++;
$cur_position=[ $path[$step-]->{coordinate}->[]+$uldr{}->[],
$path[$step-]->{coordinate}->[]+$uldr{}->[] ];
}
else{ # 当前位置已走/不可通过
if(@path){
$p_step=pop(@path); # 取出当前步
while($p_step->{direct}== && (@path)){ # 4个方向已经搜索完
$bg_ghost[ $p_step->{coordinate}->[] ][ $p_step->{coordinate}->[] ] = ; # 设置不可通过
$p_step=pop(@path); # 上一步状态
$step--; # 上一步编号
}
if($p_step->{direct}<){
$p_step->{direct}++;
print " step:",scalar(@path)," p_step->{direct}:",$p_step->{direct},"\n" if DEBUG;
push @path,$p_step;
my @temp=@{$p_step->{coordinate}}[,];
$cur_position = [ $temp[]+$uldr{$p_step->{direct}}->[],
$temp[]+$uldr{$p_step->{direct}}->[] ];
print " (y,x):(",$cur_position->[],",",$cur_position->[],")\n" if DEBUG;
}
}
}
}while(@path);
return ;
}
my $x=&handle;
print @$_,"\n" foreach(@bg);

运行信息如下:

path[]:HASH(0x1585174):
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
path[]:HASH(0x15849f4):
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
path[]:HASH(0x1584a14):
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
path[]:HASH(0x1584954):
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
path[]:HASH(0x1584924):
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
path[]:HASH(0x1584884):
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
path[]:HASH(0x158479c):
(y,x):(,)
step: p_step->{direct}:
(y,x):(,)
path[]:HASH(0x158471c):
(y,x):(,)
path[]:HASH(0x158463c):
(y,x):(,)

Perl深度优先迷宫算法的更多相关文章

  1. perl面向对象

    来源: http://www.cnblogs.com/itech/archive/2012/08/21/2649580.html Perl面向对象     首先让我们来看看有关 Perl 面向对象编程 ...

  2. Perl面向对象(2):对象

    本系列: Perl面向对象(1):从代码复用开始 Perl面向对象(2):对象 Perl面向对象(3):解构--对象销毁 第3篇依赖于第2篇,第2篇依赖于1篇. 已有的代码结构 现在有父类Animal ...

  3. Perl 正则表达式语法

    1. 概要 Perl正则表达式是Boost.regex 默认行为,也可以将perl传入basic_regex 构造. boost::regex  e1(my_expression); boost::r ...

  4. Perl OOP

    1. 模块/类(包) 创建一个名为Apple.pm的包文件(扩展名pm是包的缺省扩展名.意为Perl Module). 一个模块就是一个类(包). 2. new方法 new()方法是创建对象时必须被调 ...

  5. Perl看完这个,再不敢说自己会玩贪吃蛇

    某天闲逛时看见一副动图: 真的是非常贪吃,各种拐弯各种吃,感觉十分有趣. 用Perl来实现自动吃满,蓄谋已久,之前的字符贪吃蛇.深度优先算法.A*算法,都是为此篇做铺垫. 那么,怎样让蛇不吃到自己呢? ...

  6. Perl寻路A*算法实现

    A*算法:A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法.估价值与实际值越接近,估价函数取得就越好. 公式表示为: f(n)=g(n)+h(n),其中 f(n) 是从初始点经 ...

  7. Perl 的继承

    Perl 类的定义 Perl的一个packag可以作为一个类使用,文件后缀名为.pm,并且把package里的函数当作类的方法来用.如: package Person; 创建和使用对象 大多数程序使用 ...

  8. 邻接矩阵的深度优先遍历(java版)

    这是一个有向边带权的图 顶点数组:[v0, v1, v2, v3, v4] 边数组: v0 v1 v2 v3 v4 v0 6 v1 9 3 v2 2 5 v3 1 v4 package com.dat ...

  9. 精通Perl(第2版)

    精通Perl(第2版)(通往Perl大师之路必读经典书籍,体现了一种编程思维,能够帮你解决很多实际的问题) [美]brian d foy(布瑞恩·D·福瓦)著   王兴宇 刘宸宇 译 ISBN 978 ...

随机推荐

  1. Vue 默认IIS站点配置

    // Vue 默认IIS站点配置 module.exports = { baseUrl: '/SG/',  }

  2. RabbitMQ java 原生代码

    rabbitMQ 的交换器有四种类型:direct.fanout.topic.headers 以下是具体的代码: direct:路由键只能全部匹配,才能进入到指定队列中.其他使用 direct生产者 ...

  3. fontawesome-iconpicker 自定义字体图标选择器

    官网地址:https://farbelous.io/fontawesome-iconpicker/ 头部文件引入 <!--本地地址--> <link href="../cs ...

  4. Windows性能计数器监控实践

    Windows性能计数器(Performance Counter)是Windows提供的一种系统功能,它能实时采集.分析系统内的应用程序.服务.驱动程序等的性能数据,以此来分析系统的瓶颈.监控组件的表 ...

  5. 右键tomcat找不到项目:There are no resources that can be added or removed from the server.

    右键Add and Remove找不到项目,会出现下面这个弹框: 之后在项目文件夹上右键(Java Build Path中引用的jdk的版本也需要和下面这个Project Facets中配置的java ...

  6. java基础(9)---静态方法和成员方法

    一.方法:  方法的区别: 静态方法:有static方法 成员方法:没有static方法 方法的定义:  方法的调用:类.静态方法,对象.成员方法 一个MyClass类包含静态方法和成员方法: 静态方 ...

  7. Java精通并发-自旋对于synchronized关键字的底层意义与价值分析以及互斥锁属性详解与Monitor对象特性解说【纯理论】

    自旋对于synchronized关键字的底层意义与价值分析: 对于synchronized关键字的底层意义和价值分析,下面用纯理论的方式来对它进行阐述,自旋这个概念就会应运而生,还是很重要的,下面阐述 ...

  8. Oracle数据库的分页

    Oracle的分页 ORACLE支持一个关键字ROWNUM,ROWNUM是一个伪列,该列不存在于任何一张表中,但是每张表都可以查询该列. 而该列在结果集的中值是结果集中每条记录的"行号&qu ...

  9. go语言-for循环

    一.for循环语法: for 循环变量初始化:循环条件:循环变量迭代{ 循环体 }案例: 打印10句hello 方式一 package main import "fmt" func ...

  10. linux下新磁盘创建lvm、扩容lvm

    1.首先查看磁盘fdisk -l2.进入磁盘fdisk /dev/sdbn 创建新磁盘p 创建主分区创建分区ID 1-4为主分区根据提示选择磁盘开始位置(默认空格就好)选择结束位置(新增磁盘大小)t ...