PHP树的深度编历生成迷宫及A*自动寻路算法实例分析


Posted in PHP onMarch 10, 2015

本文实例讲述了PHP树的深度编历生成迷宫及A*自动寻路算法。分享给大家供大家参考。具体分析如下:

有一同事推荐了三思的迷宫算法,看了感觉还不错,就转成php
三思的迷宫算法是采用树的深度遍历原理,这样生成的迷宫相当的细,而且死胡同数量相对较少!
任意两点之间都存在唯一的一条通路。

至于A*寻路算法是最大众化的一全自动寻路算法

废话不多说,贴上带代码

迷宫生成类:

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*寻路算法

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);

    }

}

完整实例代码点击此处本站下载。

有需要大家可以直接下demo,看看效果!

希望本文所述对大家的php程序设计有所帮助。

PHP 相关文章推荐
php5数字型字符串加解密代码
Apr 24 PHP
PHP 图像尺寸调整代码
May 26 PHP
浅谈php冒泡排序
Dec 30 PHP
php+xml实现在线英文词典之添加词条的方法
Jan 23 PHP
php实现字符串首字母转换成大写的方法
Mar 17 PHP
微信支付扫码支付php版
Jul 22 PHP
php、java、android、ios通用的3des方法(推荐)
Sep 09 PHP
thinkPHP简单实现多个子查询语句的方法
Dec 05 PHP
php判断str字符串是否是xml格式数据的方法示例
Jul 26 PHP
Win10 下安装配置IIS + MySQL + nginx + php7.1.7
Aug 04 PHP
Yaf框架封装的MySQL数据库操作示例
Mar 06 PHP
掌握PHP垃圾回收机制详解
Mar 13 PHP
PHP实现扎金花游戏之大小比赛的方法
Mar 10 #PHP
php获取本周开始日期和结束日期的方法
Mar 09 #PHP
php数组转成json格式的方法
Mar 09 #PHP
php实现将数组转换为XML的方法
Mar 09 #PHP
php返回字符串中所有单词的方法
Mar 09 #PHP
php通过正则表达式记取数据来读取xml的方法
Mar 09 #PHP
PHP实现算式验证码和汉字验证码实例
Mar 09 #PHP
You might like
ThinkPHP关联模型操作实例分析
2012/09/23 PHP
PHP zip扩展Linux下安装过程分享
2014/05/05 PHP
PHP清除字符串中所有无用标签的方法
2014/12/01 PHP
php cli模式下获取参数的方法
2017/05/05 PHP
PHP与Web页面的交互示例详解一
2020/08/04 PHP
PHP7 错误处理机制修改
2021/03/09 PHP
JavaScript效率调优经验
2009/06/04 Javascript
JS 实现双色表格实现代码
2009/11/24 Javascript
深入理解JQuery keyUp和keyDown的区别
2013/12/12 Javascript
select多选 multiple的使用示例
2014/06/16 Javascript
让JavaScript的Alert弹出框失效的方法禁止弹出警告框
2014/09/03 Javascript
js实现二级菜单渐隐显示
2015/11/03 Javascript
Javascript中字符串相关常用的使用方法总结
2017/03/13 Javascript
Angular2仿照微信UI实现9张图片上传和预览的示例代码
2017/10/19 Javascript
Bootstrap实现翻页效果
2017/11/27 Javascript
vue项目打包后打开页面空白解决办法
2018/06/29 Javascript
使用vue2.0创建的项目的步骤方法
2018/09/25 Javascript
基于Webpack4和React hooks搭建项目的方法
2019/02/05 Javascript
基于Vue实现的多条件筛选功能的详解(类似京东和淘宝功能)
2019/05/07 Javascript
JavaScript动态检测密码强度原理及实现方法详解
2019/06/11 Javascript
vue axios重复点击取消上一次请求封装的方法
2019/06/19 Javascript
VUE注册全局组件和局部组件过程解析
2019/10/10 Javascript
vue+iview使用树形控件的具体使用
2020/11/02 Javascript
python del()函数用法
2013/03/24 Python
Python的高级Git库 Gittle
2014/09/22 Python
Python中asyncore异步模块的用法及实现httpclient的实例
2016/06/28 Python
Python实现的异步代理爬虫及代理池
2017/03/17 Python
python实现输入数字的连续加减方法
2018/06/22 Python
python批量修改图片后缀的方法(png到jpg)
2018/10/25 Python
用python写测试数据文件过程解析
2019/09/25 Python
python对指定字符串逆序的6种方法(小结)
2020/04/02 Python
纯css3(无图片/js)制作的几个社交媒体网站的图标
2013/03/21 HTML / CSS
浅谈HTML5中dialog元素尝鲜
2018/10/15 HTML / CSS
销售主管的自我评价分享
2014/01/03 职场文书
大学学生会竞选稿
2015/11/19 职场文书
Django + Taro 前后端分离项目实现企业微信登录功能
2022/04/07 Python