Php 行走十六进制地图时识别和处理两条有效路径

Php 行走十六进制地图时识别和处理两条有效路径,php,map,hexagonal-tiles,Php,Map,Hexagonal Tiles,我正在编写一个用于六边形贴图的成本路径脚本。目前我正处于“学会走路”的发展阶段 一般来说,代码是有效的。我可以可靠地从A到B。但是,请考虑下面的地图: 序列0406->0405->0505和0406->0506->0505均有效。我想遍历并输出这两条路径 我的代码如下: public function walkMap($origCol, $origRow, $destCol, $destRow) { $curRow = $origRow; $curCol = $origCol;

我正在编写一个用于六边形贴图的成本路径脚本。目前我正处于“学会走路”的发展阶段

一般来说,代码是有效的。我可以可靠地从A到B。但是,请考虑下面的地图:

序列
0406->0405->0505
0406->0506->0505
均有效。我想遍历并输出这两条路径

我的代码如下:

public function walkMap($origCol, $origRow, $destCol, $destRow) {
    $curRow = $origRow;
    $curCol = $origCol;
    while (($curRow != $destRow) || ($curCol != $destCol)) {
        $newRow = self::getNextMove($curRow,$destRow);
        if ($newRow == $curRow) {
            $curCol = self::getNextMove($curCol,$destCol);
        } else {
            $curRow = $newRow;
        }
    }
}

private function getNextMove($cur,$dest) {
    if ($cur < $dest) {
        ++$cur;
    } else if ($cur > $dest) {
        --$cur;
    }
    return $cur;
}
public function walkMap($origCol、$origRow、$destCol、$destRow){
$curRow=$origRow;
$curCol=$origCol;
而($curRow!=$destRow)| |($curCol!=$destCol)){
$newRow=self::getNextMove($curRow,$destRow);
如果($newRow==$curRow){
$curCol=self::getNextMove($curCol,$destCol);
}否则{
$curRow=$newRow;
}
}
}
私有函数getNextMove($cur,$dest){
如果($cur<$dest){
++$cur;
}否则如果($cur>$dest){
--$cur;
}
返回$cur;
}
我想要的结果是一个数值数组
step=>hexCoord
,显示所采用的路径。但我不确定如何采用上面的工作代码来智能地进行分支,并且在这样做之后,如何最好地形成输出数据结构


提前感谢。

我使用了两个类:一个是有列和行号的六边形隔间,另一个是有顺序的隔间列表路径。隔间有一个功能分支,用于获取通往目的地的路径上“正确方向”的所有隔间。只需一步就能从隔间直接到达

然后,我从长度为1的路径开始(仅开始),并通过所有分支稳定地扩展该路径,为每个分支生成一条路径,比旧分支长1。如果它不能再扩展,我们在$dest,可以输出这个路径

希望能有帮助。调试花了一些时间。让我知道,如果它不适用于任何情况

<?php

class Cubicle
{
    public $col;
    public $row;

    public function branch(Cubicle $dest)
    {
        $result = array();

        // move up
        if ($this->row > $dest->row)
            $result[] = new Cubicle($this->col, $this->row - 1);

        // move down
        elseif ($this->row < $dest->row)
            $result[] = new Cubicle($this->col, $this->row + 1);

        // move right
        if ($this->col < $dest->col)
        {
            // right-up
            if ($this->row >= $dest->row)
                $result[] = new Cubicle($this->col + 1, $this->row);

            // right-down
            else
                $result[] = new Cubicle($this->col + 1, $this->row - 1);
        }

        // move left
        elseif ($this->col > $dest->col)
        {
            // left-up
            if ($this->row > $dest->row)
                $result[] = new Cubicle($this->col - 1, $this->row - 1);

            // left-down
            else
                $result[] = new Cubicle($this->col - 1, $this->row);
        }

        return $result;
    }

    public function __construct($col, $row)
    {
        $this->col = $col;
        $this->row = $row;
    }
}

class Path
{
    public $cubicles = array();

    public function __construct(Cubicle $start)
    {
        $this->cubicles[] = $start;
    }

    public function getLast()
    {
        return $this->cubicles[count($this->cubicles)-1];
    }

    public function append($nextCubicle)
    {
        $clone = clone $this;
        $clone->cubicles[] = $nextCubicle;
        return $clone;
    }
}

function walk(Cubicle $start, Cubicle $dest) {
    $process = array(new Path($start));
    $output = array();

    while(count($process) > 0)
    {
        $currentPath = array_pop($process);

        $branches = $currentPath->getLast()->branch($dest);

        if (count($branches) == 0)
            $output[] = $currentPath;

        foreach ($branches as $branch)
            $process[] = $currentPath->append($branch);
    }

    return $output;
}

$start = new Cubicle(4, 6);
$dest = new Cubicle(5, 5);


$paths = walk($start, $dest);
var_dump($paths);
?>

这是一种非常低效的方法,因为如果有重叠的路径,算法将为每个路径重新计算这些路径的一部分。如果您想要一个性能良好的算法,您将需要创建某种图形,它只包含有效路径,并且深度优先搜索它以输出所有可能的路径

我使用了两类:一类是有列和行号的六边形隔间,另一类是有顺序的隔间列表路径。隔间有一个功能分支,用于获取通往目的地的路径上“正确方向”的所有隔间。只需一步就能从隔间直接到达

然后,我从长度为1的路径开始(仅开始),并通过所有分支稳定地扩展该路径,为每个分支生成一条路径,比旧分支长1。如果它不能再扩展,我们在$dest,可以输出这个路径

希望能有帮助。调试花了一些时间。让我知道,如果它不适用于任何情况

<?php

class Cubicle
{
    public $col;
    public $row;

    public function branch(Cubicle $dest)
    {
        $result = array();

        // move up
        if ($this->row > $dest->row)
            $result[] = new Cubicle($this->col, $this->row - 1);

        // move down
        elseif ($this->row < $dest->row)
            $result[] = new Cubicle($this->col, $this->row + 1);

        // move right
        if ($this->col < $dest->col)
        {
            // right-up
            if ($this->row >= $dest->row)
                $result[] = new Cubicle($this->col + 1, $this->row);

            // right-down
            else
                $result[] = new Cubicle($this->col + 1, $this->row - 1);
        }

        // move left
        elseif ($this->col > $dest->col)
        {
            // left-up
            if ($this->row > $dest->row)
                $result[] = new Cubicle($this->col - 1, $this->row - 1);

            // left-down
            else
                $result[] = new Cubicle($this->col - 1, $this->row);
        }

        return $result;
    }

    public function __construct($col, $row)
    {
        $this->col = $col;
        $this->row = $row;
    }
}

class Path
{
    public $cubicles = array();

    public function __construct(Cubicle $start)
    {
        $this->cubicles[] = $start;
    }

    public function getLast()
    {
        return $this->cubicles[count($this->cubicles)-1];
    }

    public function append($nextCubicle)
    {
        $clone = clone $this;
        $clone->cubicles[] = $nextCubicle;
        return $clone;
    }
}

function walk(Cubicle $start, Cubicle $dest) {
    $process = array(new Path($start));
    $output = array();

    while(count($process) > 0)
    {
        $currentPath = array_pop($process);

        $branches = $currentPath->getLast()->branch($dest);

        if (count($branches) == 0)
            $output[] = $currentPath;

        foreach ($branches as $branch)
            $process[] = $currentPath->append($branch);
    }

    return $output;
}

$start = new Cubicle(4, 6);
$dest = new Cubicle(5, 5);


$paths = walk($start, $dest);
var_dump($paths);
?>

这是一种非常低效的方法,因为如果有重叠的路径,算法将为每个路径重新计算这些路径的一部分。如果您想要一个性能良好的算法,您将需要创建某种图形,它只包含有效路径,并且深度优先搜索它以输出所有可能的路径

我注意到,目前,您的路径选择只是“到达正确的行,然后到达正确的列”。我意识到您仍在起步,但您可能希望提前考虑如何将成本计算到路径中,并让它告诉您的数据结构


例如,您可以使用标记地图上从该点到给定目的地的每个点,以最小的成本标记该点。然后,找到一条路径就是选择一个原点,并以最小的代价重复移动到相邻的十六进制,在移动过程中构建所需的路径数组。如果在任何一点上有两条最优路径,您将看到它是一个十六进制,有两个最便宜的邻居——您将为每个路径数组创建一个新副本,并独立完成它们。采用这种方法,您将使用(并返回)一个路径数组数组。

我注意到,目前,您的路径选择只是“到达正确的行,然后到达正确的列”。我意识到您仍在开始,但是,您可能希望提前考虑如何将成本分摊到路径中,并让它告诉您有关数据结构的信息


例如,您可以使用标记地图上从该点到给定目的地的每个点,以最小的成本标记该点。然后,找到一条路径就是选择一个原点,并以最小的代价重复移动到相邻的十六进制,在移动过程中构建所需的路径数组。如果在任何一点上有两条最优路径,您将看到它是一个十六进制,有两个最便宜的邻居——您将为每个路径数组创建一个新副本,并独立完成它们。采用这种方法,您将使用(并返回)一个路径数组数组。

路径
0406->0507->0506->0505
是否因为比其他路径长而无效?你只想搜索最短路径吗?@Basti-是的,总是最短路径。路径
0406->0507->0506->0505
是否因为比其他路径长而无效?你只想搜索最短路径吗?@Basti-是的,总是最短路径。