php玩一笔画完

实现方式说明

在这里插入图片描述
如上图所示,猫咪可以走上下左右的灰色方块,直到把方块走完。
我们把每个灰色方块简化成一个顶点,每个方块到另一个方块的路径简化为边。这种顶点和边关系就可以用邻接矩阵来表示。有了邻接矩阵,我们就可以用深度优先算法来计算顶点之间的可达路径。

简化顶点
简化成顶点
顶点与顶点间的边关系的邻接矩阵
用深度优先算法计算邻接矩阵,可以计算出顶点间的路径。
在这里插入图片描述

代码实现

输入顶点

在这里插入图片描述
一笔画完游戏的每一关都是“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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值