<?php
# php利用队列解决迷宫问题
# 思路:从一个节点开始,寻找所有下面能继续走的点。继续寻找,直到找到出口。 -- 广度优先搜索
# 方法:创建一个空队列,将起点位置进队。在队列不为空时循环:出队一次。如果当前位置为出口,则结束算法;否则找出当前方块的4个相邻方块中可走的方块,全部进队。
# 迷宫
$maze = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 1, 0, 1],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
];
# 获取节点的四个方向
function get_direction($x, $y)
{
return [
[$x - 1, $y], #上
[$x, $y + 1], #右
[$x + 1, $y], #下
[$x, $y - 1], #左
];
}
function maze_path_queue($x1, $y1, $x2, $y2, $maze)
{
$queue = []; #创建队列
$path = []; # 记录出队之后的节点
array_push($queue, [$x1, $y1, -1]);
$maze[$x1][$y1] = 2; #2表示已经走过的点
while (count($queue) > 0) {
$cur_node = array_shift($queue); # 出队列获取当前节点
array_push($path, $cur_node);
if ($cur_node[0] == $x2 && $cur_node[1] == $y2) { # 终点
$real_path = [];
$end_path = end($path);
array_push($real_path, [$end_path[0], $end_path[1]]);#将终点坐标push到real_path中
$i = $end_path[2];
while ($i >= 0) {
$node = $path[$i]; #node是一个元祖(x坐标,y坐标,该点的leader)
array_push($real_path, [$node[0], $node[1]]); #只要坐标
$i = $node[2];
}
$real_path = array_reverse($real_path); #反转后顺序才为从起点到终点
foreach ($real_path as $v) {
echo implode(',', $v) . "\n";
}
# print_r($real_path);
return True;
}
$direction = get_direction($cur_node[0], $cur_node[1]); #获取当前坐标的四个方向
$i = 0;
while ($i < 4) {
$next_node = $direction[$i]; #下一个节点,循环四个方向是否可以走
if ($maze[$next_node[0]][$next_node[1]] == 0) { #如果下一个节点可以走 就将坐标存入队列
array_push($queue, [$next_node[0], $next_node[1], (count($path) - 1)]); #(x坐标,y坐标,path最后一个元素的索引:记录哪个节点带它来的)进入队列
$maze[$next_node[0]][$next_node[1]] = 2; #标记为已经走过
}
$i++;
}
}
print("无路可走");
return False;
}
maze_path_queue(1, 1, 8, 8, $maze);
07-24
866
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)