Zainspirowany tym tematem, nie patrząc na kod który bim2 podał, stworzyłem też swoją klasę szukającą najkrótszą drogę (też żadnego książkowego algortmu nie znałem na ten problem). Oto kod, jeśli ktoś by chciał go wykorzystać to brać śmiało (IMG:
http://forum.php.pl/style_emoticons/default/tongue.gif) Nie sprawdzałem go dokładnie, ale faktycznie zwraca najkrótszą drogę.
<?php
class Path{
/**
* Map
*
* example:
* $map = array(
* array(0, 1, 0, 0, 0, 0),
* array(0, 1, 0, 1, 0, 1),
* array(1, 1, 1, 1, 0, 1),
* array(1, 1, 1, 1, 1, 1),
* array(1, 0, 1, 0, 1, 1),
* array(0, 1, 1, 0, 0, 0)
* );
*
*
* @var array
*/
/**
* Size of map
*
* @var array
*/
private $mapSize = array();
/**
* Coordinates of start field ($sx, $sy) and
* destination field ($dx, $dy)
*
* @var integer
*/
private $sx, $sy, $dx, $dy;
/**
* Generated shortest way
*
* @var array
*/
/**
* Number of footsteps
*
* @var int
*/
private $minFootsteps = null;
/**
* Constructor
*
* @param array Map
*/
public function __construct
(array $map){ $this->setMap($map);
}
/**
* Setter
*
* @param array Map
* @return boolean
*/
private function setMap
(array $map){
//validation
$size = null;
foreach($map as $line){
$size = ($size === null ?
count($line) : $size);
if(count($line) != $size){ throw new Exception('Wymiary kazdego wiersza maja byc takie same!');
}
foreach($line as $element){
if($element != 0 && $element != 1){
throw new Exception('Wartosci pojedynczego pola musza miec wartosc 0 lub 1');
}
}
}
$this->map = $map;
return true;
}
throw new Exception('Podano pusta mape');
}
/**
* Getter
*
* @return array
*/
public function getMapSize(){
return $this->mapSize;
}
/**
* Set start field
*
* @param integer $x
* @param integer $y
* @return boolean
*/
public function setStart($x, $y){
if($this->validatePoint($x, $y)){
$this->sx = $x;
$this->sy = $y;
return true;
}
return false;
}
/**
* Set destination field
*
* @param integer $x
* @param integer $y
* @return boolean
*/
public function setDestination($x, $y){
if($this->validatePoint($x, $y)){
$this->dx = $x;
$this->dy = $y;
return true;
}
return false;
}
/**
* Get generated the shortest way
*
* @return array
*/
public function getPath(){
return $this->path;
}
/**
* Start searching
*/
public function search(){
$this->walk($this->sx, $this->sy);
}
public function isWay(){
return (count($this->path) > 0 ?
true : false); }
/**
* Main method
*
* @param integer x coordinate of current field
* @param integer y coordinate of current field
* @param integer number of footsteps
* @param array path
* @param array visited fields
* @return boolean
*/
private function walk
($x, $y, $footsteps = 0
, $path = array(), $visited = array()){
if($x == $this->dx && $y == $this->dy){
if(($this->minFootsteps == null) || ($this->minFootsteps > $footsteps)){
$this->minFootsteps = $footsteps;
$this->path = $path;
}
return true;
}
$visited[$x.'x'.$y] = 1;
$footsteps += 1;
//Próbuj wejść na każde sąsiednie pole (nie na skos)
//i kontynuuj podróżowanie :]
if(isset($this->map[$y][$x-1
])){ $this->walk($x-1, $y, $footsteps, $path, $visited);
}
}
if(isset($this->map[$y][$x+1
])){ $this->walk($x+1, $y, $footsteps, $path, $visited);
}
}
if(isset($this->map[$y-1
][$x])){ $this->walk($x, $y-1, $footsteps, $path, $visited);
}
}
if(isset($this->map[$y+1
][$x])){ $this->walk($x, $y+1, $footsteps, $path, $visited);
}
}
return false;
}
private function validatePoint($x, $y){
if($x > ($this->mapSize[0] - 1) || $y > ($this->mapSize[1] - 1)){
return false;
}
if($this->map[$y][$x] == 0){
return false;
}
return true;
}
}
//użycie
);//1 - da się przejść, 0 - nie da się przejść
$o = new Path($map);
$o->setStart(1,1);
$o->setDestination(2,2);
$o->search();
$path = $o->getPath();
?>
Przeprowadziłem też testy porównawcze mojej klasy i klasy bim2. Aby był sens tego porównania (czyli porównanie samego algorytmu porównania) z klasy bim2 wywaliłem możliwość chodzenia na skos (w mojej klasie to nie jest uwzględnione), a z mojej wywaliłem walidację mapy (bo u bim2 nie ma tego, a jest cholernie zasobożerne). Wynik testów wskazał, że moja klasa jest 40 razy wydajniejsza. Pewnie to z tego względu, że (wnioskuję z powieszchownego rzucenia okiem) klasa bim2 ustala ilość koniecznych kroków, które trzeba wykonać dla każdego pola z podanej mapki, a algorytm mojej klasy polega na tym aby wygenerować wszystkie możliwe drogi z punktu do punktu i wybrać najkrótszą.
Może trochę chamsko (wg niektórych?) się podpiąłem pod ten temat, no ale równie dobrze mógłbym nic nie napisać i zostawić to dla siebie, a tak to przynajmniej są podane dwa trochę różne sposoby rozwiązania podobnego/tego samego problemu (IMG:
http://forum.php.pl/style_emoticons/default/tongue.gif) (IMG:
http://forum.php.pl/style_emoticons/default/tongue.gif) Może komuś się to kiedyś sprzyda.
Ten post edytował -=Peter=- 2.01.2009, 18:51:18