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对大文件进行读取操作的实现代码
Jan 23 PHP
解析yii数据库的增删查改
Jun 20 PHP
CI(CodeIgniter)框架介绍
Jun 09 PHP
PHP中执行cmd命令的方法
Oct 11 PHP
PHP获取QQ达人QQ信息的方法
Mar 05 PHP
php中mysql操作buffer用法详解
Mar 19 PHP
php项目开发中用到的快速排序算法分析
Jun 25 PHP
php使用高斯算法实现图片的模糊处理功能示例
Nov 11 PHP
php 实现Hash表功能实例详解
Nov 29 PHP
PHP精确计算功能示例
Nov 29 PHP
PDO::errorInfo讲解
Jan 28 PHP
PHP简单实现图片格式转换(jpg转png,gif转png等)
Oct 30 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
从手册去理解分析PHP session机制
2011/07/17 PHP
PHP中使用循环实现的金字塔图形
2014/11/08 PHP
php实现简单文件下载的方法
2015/01/30 PHP
浅析PHP7新功能及语法变化总结
2016/06/17 PHP
php实现XML和数组的相互转化功能示例
2017/02/08 PHP
使用PHP+MySql+Ajax+jQuery实现省市区三级联动功能示例
2017/09/15 PHP
JavaScipt基本教程之前言
2008/01/16 Javascript
JS解析XML的实现代码
2009/11/12 Javascript
JS如何判断移动端访问设备并解析对应CSS
2013/11/27 Javascript
jQuery中extend()和fn.extend()方法详解
2015/06/03 Javascript
基于Jquery和html5的7款个性化地图插件
2015/11/17 Javascript
jquery插件jquery.LightBox.js实现点击放大图片并左右点击切换效果(附demo源码下载)
2016/02/25 Javascript
NodeJs测试框架Mocha的安装与使用
2017/03/28 NodeJs
Vue+ElementUI实现表单动态渲染、可视化配置的方法
2018/03/07 Javascript
浅谈mvvm-simple双向绑定简单实现
2018/04/18 Javascript
基于vue-cli3创建libs库的实现方法
2019/12/04 Javascript
js实现菜单跳转效果
2020/12/11 Javascript
python学习手册中的python多态示例代码
2014/01/21 Python
下载给定网页上图片的方法
2014/02/18 Python
Python实现PS滤镜特效之扇形变换效果示例
2018/01/26 Python
python实现将多个文件分配到多个文件夹的方法
2019/01/07 Python
使用PyQt4 设置TextEdit背景的方法
2019/06/14 Python
Pyecharts 动态地图 geo()和map()的安装与用法详解
2020/03/25 Python
Python爬虫获取页面所有URL链接过程详解
2020/06/04 Python
python设置表格边框的具体方法
2020/07/17 Python
浅谈html5增强的页面元素
2016/06/14 HTML / CSS
华为慧通面试题
2012/09/11 面试题
大学生全国两会报告感想
2014/03/17 职场文书
中秋手机店促销方案
2014/06/16 职场文书
公安民警正风肃纪剖析材料
2014/10/10 职场文书
工作业绩不及格检讨书
2014/10/28 职场文书
入党积极分子党支部意见
2015/06/02 职场文书
鲁滨逊漂流记读书笔记
2015/06/26 职场文书
MySQL中出现乱码问题的终极解决宝典
2021/05/26 MySQL
引用计数法和root搜索算法以及JVM中判定对象需要回收的方法
2022/04/19 Java/Android
Windows server 2012 R2 安装IIS服务器
2022/04/29 Servers