实现方式说明
如上图所示,猫咪可以走上下左右的灰色方块,直到把方块走完。
我们把每个灰色方块简化成一个顶点,每个方块到另一个方块的路径简化为边。这种顶点和边关系就可以用邻接矩阵来表示。有了邻接矩阵,我们就可以用深度优先算法来计算顶点之间的可达路径。
简化顶点
顶点与顶点间的边关系的邻接矩阵
用深度优先算法计算邻接矩阵,可以计算出顶点间的路径。
代码实现
输入顶点
一笔画完游戏的每一关都是“n列*m行
”的方块组成,比如上图为“5列*4行
”。我们把灰色方块记为1,不能走的空白记为0,起点(也能走)记为2. 注意不要有多余空白符号或者空白行。将所有数据输入input.txt中,如下。
解析顶点
解析input.txt,把字段转为数组,并将数组里面大于1的块编号。总共编号0-16.
<?php
$file = fopen('input.txt','r+');
$arr = array();
while (!feof($file)) {
$arr[] = trim(fgets($file));
}
fclose($file);
$coor = array();
$k = 0;
$count = count($arr);
$strlen = strlen($arr[0]);
$start = 0; //起点
for ($j = 0; $j < $count; $j ++) {
for ($i = 0; $i < $strlen; $i++) {
$a = intval(substr($arr[$j], $i,1));
if ($a>0){
if ($a > 1) {
$start = $k;
}
if ($j <= 0) {
$coor[$i] = array($a,$k);
} else {
$coor[$j . $i] = array($a,$k);
}
$k ++;
}
}
}
var_dump($coor);die;
$coor
打印部分结果如下
顶点关系
找出编号后的每个顶点的上下左右顶点。
$nabecoor = array();
foreach ($coor as $key => $co) {
if (isset($coor[$key-1])) {
$nabecoor[$co[1]]['left'] = $coor[$key-1][1];
}
if (isset($coor[$key-10])) {
$nabecoor[$co[1]]['up'] = $coor[$key-10][1];
}
if (isset($coor[$key+1])) {
$nabecoor[$co[1]]['rigt'] = $coor[$key+1][1];
}
if (isset($coor[$key+10])) {
$nabecoor[$co[1]]['down'] = $coor[$key+10][1];
}
}
var_dump($nabecoor);die;
$nabecoor
打印部分结果如下
邻接矩阵
把顶点与顶点间的关系转化为邻接矩阵$finalcoor
$finalcoor = array();
$k = 0;
foreach ($nabecoor as $co) {
for ($i = 0; $i < count($nabecoor); $i ++) {
if (in_array($i, $co)) {
$finalcoor[$k][] = 1;
} else {
$finalcoor[$k][] = 0;
}
}
$k ++;
}
计算路径
将邻接矩阵进行深度优先算法,得到路径
$s = new Search_Method();
$result = $s->dfs($start,$finalcoor);
var_dump($result);
class Search_Method
{
private $arr = array();
//深度优先搜索的递归实现方法
public function dfs($v,$save)
{
$this->arr[]= $v;
for($i=0;$i<count($save);$i++)
{
if(!in_array($i,$this->arr) && $save[$v][$i]==1)
{
$this->dfs($i,$save);
}
}
if (count($save) == count($this->arr)) {
//可以产生多条路径,选择其中一条路径返回
return $this->arr;
}
//将最后一个元素从数组里面去除
array_pop($this->arr);
}
}
结果如下
路径结果
根据结果描绘
其他路径
一关多路径
如果我们想看其他路径,可以稍作修改。
$s = new Search_Method();
$result = $s->dfs($start,$finalcoor);
class Search_Method
{
private $arr = array();
//深度优先搜索的递归实现方法
public function dfs($v,$save)
{
$this->arr[]= $v;
for($i=0;$i<count($save);$i++)
{
if(!in_array($i,$this->arr) && $save[$v][$i]==1)
{
$this->dfs($i,$save);
}
}
if (count($save) == count($this->arr)) {
//可以产生多条路径,选择其中一条路径返回
var_dump($this->arr);
}
//将最后一个元素从数组里面去除
array_pop($this->arr);
}
}
其他关路径
查看其他关的路径,只需将新数据输入input.txt,运行代码即可。
输入input.txt
1120
1111
0111
1111
得到结果
array (size=14)
0 => int 2
1 => int 1
2 => int 0
3 => int 3
4 => int 4
5 => int 5
6 => int 6
7 => int 9
8 => int 13
9 => int 12
10 => int 8
11 => int 7
12 => int 11
13 => int 10
完整代码
input.txt(可以输入其他)
11012
11111
10101
11111
index.php
<?php
$file = fopen('input.txt','r+');
$arr = array();
while (!feof($file)) {
$arr[] = trim(fgets($file));
}
fclose($file);
$coor = array();
$k = 0;
$count = count($arr);
$strlen = strlen($arr[0]);
$start = 0; //起点
for ($j = 0; $j < $count; $j ++) {
for ($i = 0; $i < $strlen; $i++) {
$a = intval(substr($arr[$j], $i,1));
if ($a>0){
if ($a > 1) {
$start = $k;
}
if ($j <= 0) {
$coor[$i] = array($a,$k);
} else {
$coor[$j . $i] = array($a,$k);
}
$k ++;
}
}
}
$nabecoor = array();
foreach ($coor as $key => $co) {
if (isset($coor[$key-1])) {
$nabecoor[$co[1]]['left'] = $coor[$key-1][1];
}
if (isset($coor[$key-10])) {
$nabecoor[$co[1]]['up'] = $coor[$key-10][1];
}
if (isset($coor[$key+1])) {
$nabecoor[$co[1]]['rigt'] = $coor[$key+1][1];
}
if (isset($coor[$key+10])) {
$nabecoor[$co[1]]['down'] = $coor[$key+10][1];
}
}
$finalcoor = array();
$k = 0;
foreach ($nabecoor as $co) {
for ($i = 0; $i < count($nabecoor); $i ++) {
if (in_array($i, $co)) {
$finalcoor[$k][] = 1;
} else {
$finalcoor[$k][] = 0;
}
}
$k ++;
}
$s = new Search_Method();
$result = $s->dfs($start,$finalcoor);
var_dump($result);
class Search_Method
{
private $arr = array();
//深度优先搜索的递归实现方法
public function dfs($v,$save)
{
$this->arr[]= $v;
for($i=0;$i<count($save);$i++)
{
if(!in_array($i,$this->arr) && $save[$v][$i]==1)
{
$this->dfs($i,$save);
}
}
if (count($save) == count($this->arr)) {
//可以产生多条路径,选择其中一条路径返回
return $this->arr;
}
//将最后一个元素从数组里面去除
array_pop($this->arr);
}
}