PHP树生成迷宫及A*自动寻路算法

原创 2015年07月10日 08:21:02

PHP树生成迷宫及A*自动寻路算法

迷宫算法是采用树的深度遍历原理,这样生成的迷宫相当的细,而且死胡同数量相对较少!
任意两点之间都存在唯一的一条通路。
至于A*寻路算法是最大众化的一全自动寻路算法
完整代码已上传,http://download.csdn.net/detail/hello_katty/8885779 ,此处做些简单解释,还需要大家自己思考动手。废话不多说,贴上带代码
迷宫生成类:

/** 生成迷宫类
 * @date 2015-07-10
 * @edit http://www.lai18.com
 * @version 1
 **/
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*寻路算法

/** 寻路算法
 * @date 2015-07-10
 * @edit http://www.lai18.com
 * @version 1
 **/
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);

    }

}

延伸阅读

1算法导论:选择排序的原理与实现

2一道PHP冒泡排序算法笔试题

3WordPress的用户密码计算算法

4PHP实现四种常用的排序算法

5非常直观的数据结构与算法演示

6深入探讨各种背包算法问题

7图解插入排序算法

8图解堆排序Heap Sort算法

9约瑟夫环(Josephus)问题的C++算法模拟

10趣味算法之兔子产子问题

11一些常见算法的JavaScript实现

12趣味算法之猴子吃桃问题

13平方根sqrt()函数的底层算法效率

14二叉搜索树的一些相关算法介绍

15欧几里德算法(辗转相处法)练手

16蚂蚁爬木杆问题的算法思路

17计算机编程中一些重要的算法

18面试中常见的一些算法问题

19JavaScript排序算法之希尔排序

20JavaScript排序算法之堆排序

21JavaScript排序算法之归并排序

22JavaScript排序算法之选择排序

23JavaScript排序算法之快速排序

24JavaScript排序算法之冒泡排序

25JavaScript排序算法之插入排序

26合并排序算法解说与例子

27丑数Ugly Number查找算法

28求大数阶乘的算法

29各排序算法的C++实现与性能测试

30算法导论中一个蒙提霍尔问题

31实现一个栈并获取其最小元素

32亲身体验一下KMP算法

33面试算法题的快速思考方法

34矩阵逆时针旋转的算法

35Hash魔法:分布式哈希算法

36Hash魔法:一致性 hash 算法

37字符串逆序的各种实现算法

38用递归实现的快速排序

39收集一些top软件公司经典算法面试题

40趣味算法:猴子搬香蕉问题

41一些主流的个性化推荐算法评析

42趣味算法:生男生女的比例

43趣味算法:老鼠试毒瓶问题

44使用PHP内置的DES算法函数实现数据加密解密

45第九话:数据结构与算法的关系

46第12话:什么样的算法才是好算法

47第11话:算法的五个基本特征

48第13话:算法的性能分析

49第10话:什么是算法?

50第16话:算法的空间复杂度

51第15话:算法的最坏情况与平均情况

52第14话:如何计算算法的时间复杂度

53顺序栈的进栈操作

54顺序栈:栈的顺序存储结构

55栈的定义与大概理解

56栈的抽象数据类型ADT

57链栈:栈的链式存储结构

58链栈的进栈操作

59获取顺序栈的栈顶元素

60顺序栈的出栈操作

61为什么要使用栈这种数据结构

62链栈的置空操作与判断链栈是否为空

63递归,栈的重要应用之一

64栈是如何实现递归的

65链栈的出栈操作

66链栈的初始化与遍历

67漫谈递归:递归的思想

68漫谈递归:递归需要满足的两个条件

69漫谈递归:字符串回文现象的递归判断

70漫谈递归:二分查找算法的递归实现

71漫谈递归:递归的效率问题

72漫谈递归:递归与循环

73漫谈递归:循环与迭代是一回事吗?

74漫谈递归:从斐波那契开始了解尾递归

75漫谈递归:尾递归与CPS

76漫谈递归:补充一些Continuation的知识

77漫谈递归:PHP里的尾递归及其优化

78漫谈递归:从汇编看尾递归的优化

79快速排序里的学问:从猜数字开始

80快速排序里的学问:再看看称球问题

81快速排序里的学问:信息熵

82快速排序里的学问:快速排序的过程

83快速排序里的学问:霍尔与快速排序

84快速排序里的学问:霍尔快排的实现

85快速排序里的学问:枢纽元选择与算法效率

86快速排序里的学问:随机化快排

87Java程序员必须掌握的8大排序算法

88RSA,DSA等加解密算法介绍

89权限项目总结(一)权限设计


延伸阅读


PHP树生成迷宫及A*自动寻路算法完整代码

  • 2015年07月10日 08:27
  • 14KB
  • 下载

树形地图的A*寻路算法

普通的A*寻路可以在网格化的地图中寻路,但是我们想一想另一种情况,魔兽世界的大地图的飞行点路径选择,我们选择了终点,游戏就自动帮我们找到了最佳的飞行路径,这种寻路方式与网格化地图的寻路很大不同,我们可...
  • clb929
  • clb929
  • 2017年02月20日 17:43
  • 492

【bzoj1030】文本生成器 AC自动机+树型dp

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3797  Solved: 1553[Submit][Stat...
  • chty2018
  • chty2018
  • 2016年11月21日 13:05
  • 147

PHP版的AC多模式匹配算法

  • 2011年11月15日 14:32
  • 23KB
  • 下载

两种迷宫生成算法

这里要介绍两种迷宫生成的算法,Recursive Backtracking和Eller’s Algorithm。它们都生成的是Perfect maze,也就是说每个区域都连通,并且没有环的迷宫。 我...
  • u013249689
  • u013249689
  • 2014年03月13日 02:09
  • 901

用C++编写简易寻路算法

大概在半年前,看见一到信息竞赛题:在任意方格阵中设置障碍物,确定起始点后,求这两点之间路径。当时觉得蛮有意思的,但是没有时间去做,今天花了两个小时来实现它。据说有一个更高级的寻路算法叫做a*, 那我就...
  • yorhomwang
  • yorhomwang
  • 2013年07月02日 19:24
  • 13972

bzoj4231 回忆树(AC自动机+fail树+KMP(+树状数组))

bzoj4231 回忆树 原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3881 题意: 回忆树是树。 具体来说,是n个点n-1条边...
  • Bfk_zr
  • Bfk_zr
  • 2018年02月06日 08:41
  • 51

bzoj 1030: [JSOI2007]文本生成器(AC自动机+DP)

1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 5187  Solved: 2136 [Submit]...
  • Jaihk662
  • Jaihk662
  • 2017年10月03日 16:18
  • 123

基于递归分割的迷宫生成算法与自动寻路

代码下载:基于递归分割的迷宫生成算法与自动寻路 今天给大家介绍一个图形学里的东西—迷宫的生成算法。迷宫的生成算法有很多种,比如基于深度优先和广度优先的生成算法,在此介绍另外一种方法,基于递归分割的迷...
  • yutianzuijin
  • yutianzuijin
  • 2016年07月31日 14:06
  • 4868

迷宫生成算法和迷宫寻路算法

迷宫生成算法和迷宫寻路算法 大学二年级的时候,作为对栈这个数据结构的复习,我制作了一个迷宫生成算法的小程序,当时反响十分好,过了几天我又用自己已经...
  • jiangcaiyang123
  • jiangcaiyang123
  • 2012年12月14日 20:57
  • 25910
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:PHP树生成迷宫及A*自动寻路算法
举报原因:
原因补充:

(最多只允许输入30个字)