Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [class] Znajdź najkrótszą drogę
Forum PHP.pl > Forum > Gotowe rozwiązania > Algorytmy, klasy, funkcje
bim2
  1. <?php
  2. /**
  3.  * License
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2.1 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  **/
  19. /**
  20.  * @author Hernas Service <kontakt@hernass.pl>
  21.  * @copyright 2008 HernasS.pl.
  22.  * @version 2.0
  23.  */
  24. class Way {
  25.    /* Startowy punkt na osi X */
  26.    private $start_x;
  27.    
  28.    /* Startowy punkt na osi Y */
  29.    private $start_y;
  30.    
  31.    /* Mapa podana przez użytkownika */
  32.    private $aMap;
  33.    
  34.    /* Mapa wygenerowana na potrzeby skryptu */
  35.    private $aMap_;
  36.    
  37.    /* Punkt przeznaczenia na osi X */
  38.    private $destination_x;
  39.    
  40.    /* Punkt przeznaczenia na osi Y */
  41.    private $destination_y;
  42.    
  43.    /* Tablica przeszukiwania dróg */
  44.    private $aWay = array();
  45.    
  46.    /* Tablica wyjściowa z wybraną drogą */
  47.    private $aWays = array();
  48.    
  49.    /* Numer kolejnego kroku przeszukiwania */
  50.    private $fillNumber = 0;
  51.    
  52.    /* Konstruktor klasy
  53.      * @param integer $x - Startowy punkt na osi X
  54.      * @param integer $y - Startowy punkt na osi Y
  55.      * @param array $aMap - Mapa podana przez użytkownika
  56.     */
  57.    public function __construct($x, $y, $aMap)
  58.    {
  59.        $this->aMap = $aMap;
  60.        
  61.        $this->aWays[] = array($x, $y);
  62.        $this->start_x = $x;
  63.        $this->start_y = $y;
  64.        
  65.        $this->regenerateMap();
  66.        
  67.    }
  68.    /* Szuka drogi
  69.      * @param integer $x - Punkt przeznaczenia na osi X
  70.      * @param integer $y - Punkt przeznaczenia na osi Y
  71.     */
  72.    public function findWay($x, $y)
  73.    {    
  74.        $this->destination_x = $x;
  75.        $this->destination_y = $y;    
  76.        
  77.        $this->startFinding();
  78.        $this->mirrorFinding($x, $y);
  79.        return $this->aWay;
  80.    }
  81.    /* Znaczy kolejne kroki na mapie */
  82.    private function startFinding()
  83.    {
  84.        foreach($this->aWays AS $v)
  85.        {
  86.            list($x, $y) = $v;
  87.            $this->aMap_[$y][$x] = $this->fillNumber;
  88.            $new_x[] = $x+1;
  89.            $new_y[] = $y;
  90.            
  91.            $new_x[] = $x+1;
  92.            $new_y[] = $y+1;
  93.            
  94.            $new_x[] = $x+1;
  95.            $new_y[] = $y-1;
  96.            
  97.            $new_x[] = $x-1;
  98.            $new_y[] = $y;
  99.            
  100.            $new_x[] = $x-1;
  101.            $new_y[] = $y+1;
  102.            
  103.            $new_x[] = $x-1;
  104.            $new_y[] = $y-1;
  105.                    
  106.            $new_x[] = $x;
  107.            $new_y[] = $y+1;
  108.            
  109.            $new_x[] = $x;
  110.            $new_y[] = $y-1;
  111.            $paths = array();
  112.            foreach($new_x AS $i => $v)
  113.            {
  114.                if(isset($this->aMap_[$new_y[$i]][$v]) AND $this->aMap_[$new_y[$i]][$v]==-1)
  115.                {
  116.                    if($v==$this->destination_y AND $new_y[$i]==$this->destination_x)
  117.                    {
  118.                        $paths[] = array($v, $new_y[$i]);
  119.                        break;
  120.                    }
  121.                    $paths[] = array($v, $new_y[$i]);
  122.                }
  123.            }
  124.        }
  125.        
  126.        $this->fillNumber++;
  127.    if(isset($paths))
  128.    {
  129.        $this->aWays = $paths;
  130.        $this->startFinding();
  131.    }
  132.        
  133.    }
  134.    /* Szuka drogi od końca po kolejnych krokach
  135.      * @param integer $x - Punkt kolejnego kroku na osi X
  136.      * @param integer $y - Punkt kolejnego kroku na osi Y
  137.     */
  138.    private function mirrorFinding($x, $y)
  139.    {
  140.        $new_x[] = $x+1;
  141.        $new_y[] = $y;
  142.        
  143.        $new_x[] = $x+1;
  144.        $new_y[] = $y+1;
  145.        
  146.        $new_x[] = $x+1;
  147.        $new_y[] = $y-1;
  148.        
  149.        $new_x[] = $x-1;
  150.        $new_y[] = $y;
  151.        
  152.        $new_x[] = $x-1;
  153.        $new_y[] = $y+1;
  154.        
  155.        $new_x[] = $x-1;
  156.        $new_y[] = $y-1;
  157.                
  158.        $new_x[] = $x;
  159.        $new_y[] = $y+1;
  160.        
  161.        $new_x[] = $x;
  162.        $new_y[] = $y-1;
  163.        foreach($new_x AS $i => $v)
  164.        {
  165.            if(isset($this->aMap_[$new_y[$i]][$v]) AND $this->aMap_[$new_y[$i]][$v]==($this->aMap_[$y][$x]-1))
  166.            {
  167.                $this->aWay[] = array($new_y[$i], $v);
  168.                $this->mirrorFinding($v, $new_y[$i]);
  169.                break;
  170.            }
  171.        }
  172.    }
  173.    /* Generuję mapę na potrzeby skryptu    */
  174.    private function regenerateMap()
  175.    {
  176.        foreach($this->aMap AS $y => $v_)
  177.        {
  178.            foreach($v_ AS $x => $v)
  179.            {
  180.                if($this->start_x == $x AND $this->start_y == $y)
  181.                {
  182.                    $this->aMap_[$y][$x] = 0;
  183.                } elseif($v==1) {
  184.                    $this->aMap_[$y][$x] = -2;
  185.                } elseif($v==0) {
  186.                    $this->aMap_[$y][$x] = -1;
  187.                } else {
  188.                    $this->aMap_[$y][$x] = -2;
  189.                }
  190.            }            
  191.        }
  192.    }
  193.    
  194.    
  195. }
  196. ?>


Oraz przykład użycia smile.gif

  1. <?php
  2. $aMap = array(
  3. array(1,0,0,0,1,0,0,0),
  4. array(1,0,1,1,1,1,0,0),
  5. array(1,0,1,0,0,1,0,1),
  6. array(0,0,0,0,0,0,0,1),
  7. array(0,0,0,1,1,1,1,1),
  8. array(0,1,0,0,0,0,0,0),
  9. array(1,1,0,0,0,1,0,0),
  10. array(1,1,0,1,1,1,0,0),
  11. ); // 0 -można chodzić
  12. $oWay = new Way(2, 7, $aMap); //X i Y liczone od 0 (jak klucz arraya)
  13. print_r($oWay->findWay(7, 7));
  14. ?>


Oraz przykład graficzny:
http://hernass.pl/searchWay/

PS. Dziękuję wszystkim, którzy pomogli przy skrypcie snitch.gif
sticker
oho widzę że ktoś sie tu bawi w pisanie AI w PHP winksmiley.jpg
bim2
~sticker
Nie smile.gif Po prostu potrzebuję tego do gry. :]
Babcia@Stefa
Nieźle, klasa bardzo "huda" i zapewne wydajna.

Niezła robota, mówię tak choć nie testowałem - tylko ten przykład graficzny smile.gif

Chyba klasa nie była aż tak trudna jak się wydaje winksmiley.jpg

Pozdrawiam, WebNuLL
bim2
Jeśli znałeś algorytm to nie smile.gif A jak go nie znałeś, to dla mnie było ciężko. ;P Na szczęście parę osób pomogło i podało poradniki. Nie wiem czy wydajna, nie testowałem jeszcze.

PS. Nie piszę się chuda? ;P
Wicko
Hej, Bartku/Michale! czarodziej.gif
Ciekawa rzecz, ale.. nie jestem pewny czy to poprawne zachowanie?
phpion
Cytat(Wicko @ 19.11.2008, 20:26:33 ) *
Ciekawa rzecz, ale.. nie jestem pewny czy to poprawne zachowanie?

Hmmm, a czy przypadkiem nie jest to właśnie najkrótsza droga z punku Start do punktu Cel?
AxZx
ale chyba nie powinna iść po skosie. to zależy pewnie od rodzaju gry.
phpion
Cytat(AxZx @ 19.11.2008, 21:01:19 ) *
ale chyba nie powinna iść po skosie. to zależy pewnie od rodzaju gry.

Racja, jest to zapewne uzależnione od zasad gry. Jednak gdyby nie było możliwości pójścia po skosie to nie byłaby to prawdziwa "najkrótsza droga".
bim2
Jest to najkrótsza droga. Można przydzielić rangę, że po skosie jest dłużej, ale nie miałem już siły przerabiać. :] Niedługo zamieszczę z możliwością ustalenia drogi po skosie, bo jednak u mnie jest to 2 razy dłuższa droga smile.gif
wookieb
Sry za offtop ale... Dla startowego elementu 2,1 i koncowego 6,1 zaznacza dodatkowe pole jako "droga" pomimo tego ze do tej drogi nie nalezy. Czy to własciwe zachowanie?
ShadowD
Trochę pokombinowałem i znalazłem błąd a bynajmniej ja tak to rozumiem...

Start:
8*8
Cel:
1*4

I droga skręca w prawo gdzie kończy się i ponownie rozpoczyna na celu. winksmiley.jpg
bim2
@wookieb
Błąd w rysowaniu mapki, spójrz na kolejne etapy pod mapką.

@ShadowD
Mi działa normalnie nie licząc tego błędu jaki ma wookieb smile.gif Później poprawie bo narazie nie mam sił. Przygotowałem już działającą wersję w JS haha.gif
djstrong
Cytat(Wicko @ 19.11.2008, 18:26:33 ) *
Hej, Bartku/Michale! czarodziej.gif
Ciekawa rzecz, ale.. nie jestem pewny czy to poprawne zachowanie?

Nie zagłębiałem się w kod ale nie powinien "numerować" wszystkich pól tylko zatrzymać się gdy znajdzie cel. Może jest tak zrobione, tylko na potrzeby mapki puszczone dalej;)
bim2
Jest tak zrobione, ale musi numerować wszystkie kroki aż do celu. Więc jeśli cel będzie na 11 kroku, ponumeruje wszystko do 11 kroku. A co do tego co na mapce widać, nie powinien numerować do końca i mi o dziwo na localhoscie nie numeruje. Nie pamiętam jak jest na serwerze, bo zmieniałem parę rzeczy.
-=Peter=-
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 tongue.gif Nie sprawdzałem go dokładnie, ale faktycznie zwraca najkrótszą drogę.

  1. <?php
  2.  
  3. class Path{
  4.    /**
  5.      * Map
  6.      *
  7.      * example:
  8.      *  $map = array(
  9.      *         array(0, 1, 0, 0, 0, 0),
  10.      *         array(0, 1, 0, 1, 0, 1),
  11.      *         array(1, 1, 1, 1, 0, 1),
  12.      *         array(1, 1, 1, 1, 1, 1),
  13.      *         array(1, 0, 1, 0, 1, 1),
  14.      *         array(0, 1, 1, 0, 0, 0)
  15.      * );
  16.      *
  17.      *
  18.      * @var array
  19.      */
  20.    private $map = array();
  21.    
  22.    /**
  23.      * Size of map
  24.      *
  25.      * @var array
  26.      */
  27.    private $mapSize = array();
  28.    
  29.    /**
  30.      * Coordinates of start field ($sx, $sy) and
  31.      * destination field ($dx, $dy)
  32.      *
  33.      * @var integer
  34.      */
  35.    private $sx, $sy, $dx, $dy;
  36.    
  37.    /**
  38.      * Generated shortest way
  39.      *
  40.      * @var array
  41.      */
  42.    private $path = array();
  43.    
  44.    /**
  45.      * Number of footsteps
  46.      *
  47.      * @var int
  48.      */
  49.    private $minFootsteps = null;
  50.    
  51.    /**
  52.      * Constructor
  53.      *
  54.      * @param array Map
  55.      */
  56.    public function __construct(array $map){
  57.        $this->setMap($map);
  58.    }
  59.    
  60.    /**
  61.      * Setter
  62.      *
  63.      * @param array Map
  64.      * @return boolean
  65.      */
  66.    private function setMap(array $map){
  67.        
  68.        //validation
  69.        if(count($map) > 0){
  70.            $size = null;
  71.            
  72.            foreach($map as $line){
  73.                $size = ($size === null ? count($line) : $size);
  74.                
  75.                if(count($line) != $size){
  76.                    throw new Exception('Wymiary kazdego wiersza maja byc takie same!');
  77.                }
  78.                
  79.                foreach($line as $element){
  80.                    if($element != 0 && $element != 1){
  81.                        throw new Exception('Wartosci pojedynczego pola musza miec wartosc 0 lub 1');
  82.                    }
  83.                }
  84.            }
  85.            
  86.            $this->map = $map;
  87.            $this->mapSize = array($size, count($map));
  88.            return true;
  89.        }
  90.        throw new Exception('Podano pusta mape');
  91.    }
  92.    
  93.    /**
  94.      * Getter
  95.      *
  96.      * @return array
  97.      */
  98.    public function getMapSize(){
  99.        return $this->mapSize;
  100.    }
  101.    
  102.    /**
  103.      * Set start field
  104.      *
  105.      * @param integer $x
  106.      * @param integer $y
  107.      * @return boolean
  108.      */
  109.    public function setStart($x, $y){
  110.        if($this->validatePoint($x, $y)){
  111.            $this->sx = $x;
  112.            $this->sy = $y;
  113.            
  114.            return true;
  115.        }
  116.        
  117.        return false;
  118.    }
  119.    
  120.    /**
  121.      * Set destination field
  122.      *
  123.      * @param integer $x
  124.      * @param integer $y
  125.      * @return boolean
  126.      */
  127.    public function setDestination($x, $y){
  128.        if($this->validatePoint($x, $y)){
  129.            $this->dx = $x;
  130.            $this->dy = $y;
  131.            
  132.            return true;
  133.        }
  134.        
  135.        return false;
  136.    }
  137.    
  138.    /**
  139.      * Get generated the shortest way
  140.      *
  141.      * @return array
  142.      */
  143.    public function getPath(){
  144.        return $this->path;
  145.    }
  146.    
  147.    /**
  148.      * Start searching
  149.      */
  150.    public function search(){
  151.        $this->walk($this->sx, $this->sy);            
  152.    }
  153.    
  154.    public function isWay(){
  155.        return (count($this->path) > 0 ? true : false);
  156.    }
  157.    
  158.    /**
  159.      * Main method
  160.      *
  161.      * @param integer x coordinate of current field
  162.      * @param integer y coordinate of current field
  163.      * @param integer number of footsteps
  164.      * @param array path
  165.      * @param array visited fields
  166.      * @return boolean
  167.      */
  168.    private function walk($x, $y, $footsteps = 0, $path = array(), $visited = array()){
  169.        $path[] = array($x, $y);
  170.        
  171.        if($x == $this->dx && $y == $this->dy){
  172.            if(($this->minFootsteps == null) || ($this->minFootsteps > $footsteps)){
  173.                $this->minFootsteps = $footsteps;
  174.                $this->path = $path;            
  175.            }
  176.            
  177.            return true;
  178.        }
  179.        
  180.        $visited[$x.'x'.$y] = 1;
  181.        $footsteps += 1;
  182.        
  183.        //Próbuj wejść na każde sąsiednie pole (nie na skos)
  184.        //i kontynuuj podróżowanie :]
  185.                
  186.        if(isset($this->map[$y][$x-1])){
  187.            if(($this->map[$y][$x-1] == 1) && !array_key_exists(($x-1).'x'.$y, $visited)){
  188.                $this->walk($x-1, $y, $footsteps, $path, $visited);
  189.            }
  190.        }
  191.        
  192.        if(isset($this->map[$y][$x+1])){
  193.            if(($this->map[$y][$x+1] == 1) && !array_key_exists(($x+1).'x'.$y, $visited)){
  194.                $this->walk($x+1, $y, $footsteps, $path, $visited);
  195.            }
  196.        }
  197.        
  198.        if(isset($this->map[$y-1][$x])){
  199.            if(($this->map[$y-1][$x] == 1) &&  !array_key_exists($x.'x'.($y-1), $visited)){
  200.                $this->walk($x, $y-1, $footsteps, $path, $visited);
  201.            }
  202.        }
  203.        
  204.        if(isset($this->map[$y+1][$x])){
  205.            if(($this->map[$y+1][$x] == 1)  && !array_key_exists($x.'x'.($y+1), $visited)){
  206.                $this->walk($x, $y+1, $footsteps, $path, $visited);
  207.            }
  208.        }
  209.        
  210.        return false;                
  211.    }
  212.    
  213.    private function validatePoint($x, $y){
  214.        if($x > ($this->mapSize[0] - 1) || $y > ($this->mapSize[1] - 1)){
  215.            return false;
  216.        }
  217.        
  218.        
  219.        if($this->map[$y][$x] == 0){
  220.            return false;
  221.        }
  222.        
  223.        return true;
  224.    }    
  225. }
  226.  
  227. //użycie
  228. $map = array(
  229.        array(0, 1, 0),
  230.        array(0,1,0),
  231.        array(0, 1, 1),
  232. );//1 - da się przejść, 0 - nie da się przejść
  233. $o = new Path($map);
  234. $o->setStart(1,1);
  235. $o->setDestination(2,2);
  236. $o->search();
  237.  
  238. $path = $o->getPath();
  239. ?>


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 tongue.gif tongue.gif Może komuś się to kiedyś sprzyda.
bim2
Miło, pewnie sam wykorzystam twoją klasę smile.gif Jeśli jest szybsza :] Szkoda że wcześniej nie napisałęś, dzień roboty bym zaoszczędził biggrin.gif
-=Peter=-
A jednak chyba moja klasa jest z dupy tongue.gif Przy mapce o rozmiarze 8x8 jest znacznie wydajniejsza, ale przy większych wymiarach moja klasa wymięka tongue.gif Chyba algorytm jest rzędu wykładniczego ;]
bim2
Hmm. I by się zgadzało smile.gif Moja tylko ponumeruje sobie mapkę, a później szuka jednej drogi. To o wiele wydajniejsze niż szukać ileś tam dróg, co przy większej mapce rośnie ekspansyjnie. :]
bartg
Imho sprawdzanie każdej trasy przy dobrym algorytmie wydaje się trochę głupi smile.gif. Jak gdziesz jedziesz to szukasz drogi najkrótszej sprawdzając każdą trasę? ;O
djstrong
Cytat(bim2 @ 1.01.2009, 17:54:19 ) *
Jest tak zrobione, ale musi numerować wszystkie kroki aż do celu. Więc jeśli cel będzie na 11 kroku, ponumeruje wszystko do 11 kroku. A co do tego co na mapce widać, nie powinien numerować do końca i mi o dziwo na localhoscie nie numeruje. Nie pamiętam jak jest na serwerze, bo zmieniałem parę rzeczy.

Jeśli ten screen jest z Twojego algorytmu to numeracja jest niepoprawna. Np. nad niebieskim polem z '5' powinna być szóstka, a jest 7.
bim2
http://hernass.pl/searchWay/
Screen ze starej wersji skrypciku smile.gif Już ładnie działa, i rogi wykrywa :]

Drugi post, dlatego żeby każdy widział i w dużym odstępie czasowym.

Przepisałem kod pod javaScript smile.gif Dałem znacznik php, żeby było kolorowanie. Niestety przykłady nie mam, ale będzie to coś na zasadzie
Mapa jak tablica w PHP oczywiście :]
  1. <?php
  2. Map = generateMap();
  3. var oSearchWay = new SearchWay();
  4. oSearchWay.find(1,1,12,15,Map);
  5.  
  6.  
  7. /**
  8. /* A* Algorithm - SearchWay by Hernass.pl
  9. **/
  10. /**
  11. * License
  12. *
  13. * This library is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU Lesser General Public
  15. * License as published by the Free Software Foundation; either
  16. * version 2.1 of the License, or (at your option) any later version.
  17. *
  18. * This library is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  21. * Lesser General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Lesser General Public
  24. * License along with this library; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  26. **/
  27. /**
  28. * @author Hernas Service <kontakt@hernass.pl>
  29. * @copyright 2008 HernasS.pl.
  30. * @version 2.0
  31. */
  32. function SearchWay() {
  33.    var obj = new Object();
  34.    
  35.    obj.number = 0;
  36.    obj.dest = new Array();
  37.    obj.startPos = new Array();
  38.    obj.Map = new Array();
  39.    obj.Way = new Array();
  40.    obj.find = function(start_x, start_y, dest_x, dest_y, map)
  41.    {
  42.        obj.Map = map;
  43.        obj.Way = new Array();
  44.        obj.number = 0;
  45.  
  46.        obj.dest = new Array();
  47.        obj.dest[0] = dest_x; //x
  48.        obj.dest[1] = dest_y; //y
  49.  
  50.        obj.startPos = new Array();
  51.        obj.startPos[0] = new Array();
  52.        obj.startPos[0][0] = start_x; //x
  53.        obj.startPos[0][1] = start_y; //y
  54.        obj.mark(obj.startPos);
  55.        obj.searchReverse(obj.dest);
  56.        return obj.Way;
  57.    };
  58.    obj.searchReverse = function(pos) {
  59.        x = pos[0];
  60.        y = pos[1];
  61.        new_x = new Array();
  62.        new_y = new Array();
  63.        
  64.        new_x[0] = x+1;
  65.        new_y[0] = y;
  66.        
  67.        new_x[1] = x-1;
  68.        new_y[1] = y;
  69.        
  70.        new_x[2] = x;
  71.        new_y[2] = y+1;
  72.        
  73.        new_x[3] = x+1;
  74.        new_y[3] = y+1;
  75.        
  76.        new_x[4] = x-1;
  77.        new_y[4] = y+1;
  78.        
  79.        new_x[5] = x;
  80.        new_y[5] = y-1;
  81.        
  82.        new_x[6] = x+1;
  83.        new_y[6] = y-1;
  84.        
  85.        new_x[7] = x-1;
  86.        new_y[7] = y-1;
  87.        
  88.        for(ii in new_x)
  89.        {
  90.            nx = new_x[ii];
  91.            ny = new_y[ii];
  92.            if(obj.Map[ny]!=undefined && obj.Map[ny][nx]!=undefined && obj.Map[ny][nx]==(obj.Map[y][x]-1) && obj.Map[ny][nx]>-1)
  93.            {
  94.                obj.Way[(obj.Map[y][x]-1)] = new Array();
  95.                obj.Way[(obj.Map[y][x]-1)][0] = nx-x;
  96.                obj.Way[(obj.Map[y][x]-1)][1] = ny-y;
  97.                obj.searchReverse(new Array(nx, ny));
  98.            }
  99.        }
  100.    };
  101.    obj.mark = function(searching)
  102.    {
  103.        
  104.        for(i in searching)
  105.        {
  106.            x = searching[i][0];
  107.            y = searching[i][1];
  108.            if(obj.Map[y]!=undefined && obj.Map[y][x]!=undefined)
  109.            {
  110.                obj.Map[y][x] = obj.number;
  111.            }
  112.            if(obj.dest[0]==x && obj.dest[1]==y)
  113.            {
  114.                return;
  115.            }
  116.        }
  117.        
  118.        nextMark = false;
  119.        new_map = new Array();
  120.        ii_ = 0;
  121.        for(i in searching)
  122.        {
  123.        nextMark = true;
  124.            x = searching[i][0];
  125.            y = searching[i][1];
  126.                        
  127.            new_x = new Array();
  128.            new_y = new Array();
  129.            
  130.            new_x[0] = x+1;
  131.            new_y[0] = y;
  132.            
  133.            new_x[1] = x+1;
  134.            new_y[1] = y+1;
  135.            
  136.            new_x[2] = x+1;
  137.            new_y[2] = y-1;
  138.            
  139.            new_x[3] = x-1;
  140.            new_y[3] = y;
  141.            
  142.            new_x[4] = x-1;
  143.            new_y[4] = y+1;
  144.            
  145.            new_x[5] = x-1;
  146.            new_y[5] = y-1;
  147.                    
  148.            new_x[6] = x;
  149.            new_y[6] = y+1;
  150.            
  151.            new_x[7] = x;
  152.            new_y[7] = y-1;
  153.            for(ii in new_x)
  154.            {
  155.                nx = new_x[ii];
  156.                ny = new_y[ii];
  157.                if((obj.Map[ny]!=undefined && obj.Map[ny][nx]!=undefined) && obj.Map[ny][nx]==-1)
  158.                {
  159.                    new_map[ii_] = new Array();
  160.                    new_map[ii_][0] = nx;
  161.                    new_map[ii_][1] = ny;
  162.                    ii_++;
  163.                }
  164.            }
  165.        }
  166.        obj.number++;
  167.        if(nextMark)
  168.        {
  169.        obj.mark(new_map);
  170.        }
  171.    };
  172.    return obj;
  173. }
  174. /* ********************** */
  175. ?>
rzymek01
nie łatwiej przerobić z c++ na php Algorytm Dijkstry w implementacji kopca?
bim2
Dla mnie nie smile.gif jeśli jest Ci prościej to proszę napisz i zaprezentuj swój kod. Nie lubie ludzi którzy piszą "nie łatwiej by było to i to" żeby pochwalić się swoją wiedzą i nic w tym kierunku nie robić.
ucho
Przydało by się do tego ( jeśli istnieje to niech ktoś się podzieli) natywne rozszerzenie do php dodające jakąś kolejkę priorytetową, np kopiec. Dijkstra to jeden z tych nielicznych przypadków kiedy bogactwo struktur danych PHP (np. tablica, tablica czy tablica) nie wystarcza tongue.gif
Przy okazji próby implementacji dowiedziałem się w nieprzyjemny sposób, że likwidowanie, do testów, limitu na czas wykonywania skryptu PHP jest złe. Np. byle literówka może dać tyle komunikatów notice, że syslogd kompletnie zamuli system, a po resecie okaże się, że plik /var/log/user.log ma 5GB haha.gif
djstrong
Cytat(rzymek01 @ 4.02.2009, 16:21:53 ) *
nie łatwiej przerobić z c++ na php Algorytm Dijkstry w implementacji kopca?

ja bym zrobił A* na kolejce priorytetowej z odpowiednią funkcją przewidującą najkrótszą drogą (min(x,y) w tym przypadku).
rzymek01
@bim2, napisałem o algorytmie Dijkstry, bo jest prostszy w użyciu i w necie masz pełno przykładów, a A* to heura, czyli trochę wyższa szkoła jazdy
bim2
No nie wiem.
http://pl.wikipedia.org/wiki/Przeszukiwanie_wszerz
lub
tutaj ladnie wytłumaczone i z tego korzystałem:
http://www.gamedev.pl/articles.php?x=view&id=254
ShadowD
Nadal chyba jest coś nie tak.

Podałem:
88
21

I dróżka się podzieliła na dwie .;]
bim2
Mówisz o js czy php? smile.gif
ShadowD
Php js nie sprawdzałem... ;]
krriv
Witajcie,

planuję napisać aplikację w PHP służącą do wyszukiwania najkrótszej drogi między dwiema lokacjami. Zastanawia mnie fakt, czy mogę do tego wykorzystać algorytmy typu A* lub Dijkstry. Muszę przyznać, że na tym polu jestem nowicjuszem - być może problem da się rozwiązać zupełnie łatwo i prosto? Proszę o waszą pomoc i ocenę.

Zadanie polega na wyszukaniu drogi, możliwie najkrótszej między START-em a wybraną lokacją (3, 54, 32 itd itd). Ilość lokacji to 64, z czego każda jest oddzielnym polem - nie stanowi 'jednej pełnej mapy', ma po 4 połączenia ("portale") z innymi (na rysunku: zielonkawe kwadraty na obrzeżu pola). Ważne aby algorytm mógł wyszczególnić położenie (w obrębie danego pola), z którego połączenia skorzystał (o ile znalazł drogę do punktu docelowego) np: droga ze startu do lokacji '24'

[Start]->38(Prawy)->[38]->24(Dolny)->[24]



Dziękuję za ewentualną pomoc smile.gif
bim2
Może połącz na początek te 64 pola tak żeby stanowiło to mapkę jednolitą. Połącz je portalami, powiązaniami. smile.gif
krriv
Jeśli chodzi o połączenia to są nimi wspomniane wcześniej 'portale' (jasno zielone). Samej mapy nie da się fizycznie połączyć - miedzy polami można się przenosić jedynie wybierając jeden z portali. Czy możliwe jest opracowanie takiego algorytmu? Jeśli możesz daj mi wskazówkę na jakiej zasadzie 'połączyć' te lokacje?
rzymek01
zbudować graf, który będzie odzwierciedlał połacznia, np.:
[miasto] = połaczenia wychodzące (,)
[1] = 18,38,41
[2] = 51
[3] = 20,38 etc.

i potem zapuścić algorytm dijkstry i po sprawie
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.