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 相关文章推荐
php下删除一篇文章生成的多个静态页面
Aug 08 PHP
深入理解PHP原理之异常机制
Aug 21 PHP
php插入中文到sqlserver 2008里出现乱码的解决办法分享
Jul 19 PHP
php与flash as3 socket通信传送文件实现代码
Aug 16 PHP
Laravel 5框架学习之Eloquent (laravel 的ORM)
Apr 08 PHP
yii2使用ajax返回json的实现方法
May 14 PHP
php进行ip地址掩码运算处理的方法
Jul 11 PHP
PHP策略模式定义与用法示例
Jul 27 PHP
PHP命名空间简单用法示例
Dec 28 PHP
Laravel如何自定义command命令浅析
Mar 23 PHP
php设计模式之策略模式应用案例详解
Jun 17 PHP
PHP连接MySQL数据库操作代码实例解析
Jul 11 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
全国FM电台频率大全 - 13 福建省
2020/03/11 无线电
支持数组的ADDSLASHES的php函数
2010/02/16 PHP
php检查日期函数checkdate用法实例
2015/03/19 PHP
Laravel 5.5官方推荐的Nginx配置学习教程
2017/10/06 PHP
用JS判断IE版本的代码 超管用!
2011/08/09 Javascript
使用mouse事件实现简单的鼠标经过特效
2015/01/30 Javascript
javascript学习总结之js使用技巧
2015/09/02 Javascript
JavaScript使用DeviceOne开发实战(一) 配置和起步
2015/12/01 Javascript
微信小程序 用户数据解密详细介绍
2017/01/09 Javascript
JS中使用 after 伪类清除浮动实例
2017/03/01 Javascript
微信小程序实现倒计时60s获取验证码
2020/04/17 Javascript
jQuery简单实现向列表动态添加新元素的方法示例
2017/12/25 jQuery
Next.js项目实战踩坑指南(笔记)
2018/11/29 Javascript
Nodejs技巧之Exceljs表格操作用法示例
2019/11/06 NodeJs
element-ui 远程搜索组件el-select在项目中组件化的实现代码
2019/12/04 Javascript
python脚本实现分析dns日志并对受访域名排行
2014/09/18 Python
深入浅析python with语句简介
2018/04/11 Python
python3.X 抓取火车票信息【修正版】
2018/06/19 Python
使用TensorFlow实现二分类的方法示例
2019/02/05 Python
python爬取基于m3u8协议的ts文件并合并
2019/04/26 Python
Python实现串口通信(pyserial)过程解析
2019/09/25 Python
python numpy数组复制使用实例解析
2020/01/10 Python
设置jupyter中DataFrame的显示限制方式
2020/04/12 Python
美国著名手表网站:Timepiece
2017/11/15 全球购物
美丽的珠宝配饰:SmallThings
2019/09/04 全球购物
俄罗斯护发和专业化妆品购物网站:Hihair
2019/09/28 全球购物
会走路的树教学反思
2014/02/20 职场文书
高中生操行评语大全
2014/04/25 职场文书
相亲活动方案
2014/08/26 职场文书
乡镇党员群众路线教育实践活动对照检查材料思想汇报
2014/10/05 职场文书
2015年信访工作总结
2015/04/07 职场文书
《小蝌蚪找妈妈》教学反思
2016/02/23 职场文书
80后创业总结的9条职场用人思想,记得收藏
2019/08/13 职场文书
七年级作文(600字3篇)
2019/09/24 职场文书
Golang jwt身份认证
2022/04/20 Golang
Django中celery的使用项目实例
2022/07/07 Python