私は2つのクラスを使用しました。列と行の番号を取得した六角形のものであるCubiclesと、Cubiclesの順序付きリストであるPathsです。キュービクルには、宛先へのパス上で「正しい方向」にあるすべてのキュービクルを取得するための関数ブランチがあります。一歩を踏み出すだけで、キュービクルから直接アクセスできます。
次に、長さ1のパス(開始のみ)から開始し、このパスをすべてのブランチで着実に拡張して、ブランチごとに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);
?>
出力
array
0 =>
object(Path)[8]
public 'cubicles' =>
array
0 =>
object(Cubicle)[1]
public 'col' => int 4
public 'row' => int 6
1 =>
object(Cubicle)[5]
public 'col' => int 5
public 'row' => int 6
2 =>
object(Cubicle)[3]
public 'col' => int 5
public 'row' => int 5
1 =>
object(Path)[9]
public 'cubicles' =>
array
0 =>
object(Cubicle)[1]
public 'col' => int 4
public 'row' => int 6
1 =>
object(Cubicle)[4]
public 'col' => int 4
public 'row' => int 5
2 =>
object(Cubicle)[7]
public 'col' => int 5
public 'row' => int 5
パスが重複している場合、アルゴリズムはパスごとにそれらのパスの一部を再計算するため、これは非常に非効率的なアプローチです。優れたパフォーマンスのアルゴリズムが必要な場合は、有効なパスのみを含むある種のグラフを作成し、可能なすべてのパスを出力するために深さ優先探索を行う必要があります。