Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Algorytm szukania drogi

Ostatnio zmodyfikowano 2023-11-26 16:13
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
Algorytm szukania drogi
» 2023-11-25 18:47:15
Cześć, poszukuje algorytmu, który znajdzie drogę z punktu (x1, y1) do punktu (x2, y2). Załóżmy, że mapa jest kafelkowa prosta, jak poniżej i z każdego pola można dojść do każdego pola.

(0,4)__(1,4)__(2,4)__(3,4)__(4,4)__(5,4)
(0,3)__(1,3)__(2,3)__(3,3)__(4,3)__(5,3)
(0,2)__(1,2)__(2,2)__(3,2)__(4,2)__(5,2)
(0,1)__(1,1)__(2,1)__(3,1)__(4,1)__(5,1)
(0,0)__(1,0)__(2,0)__(3,0)__(4,0)__(5,0)

Jeżeli jest taka możliwość poproszę o przykład użycia algorytmu.
P-180488
DejaVu
» 2023-11-25 19:12:41
P-180489
tBane
Temat założony przez niniejszego użytkownika
» 2023-11-25 19:14:08
Właśnie czytam od paru dni, i trudno mi to sobie wyobrazić. Dlatego poprosiłem o przykład użycia na prostej mapie.

Poza tym, ten algorytm jest zbyt złożony. Nie rozumiem po co używać koszt przejścia kafelka skoro to prosta mapa. Nie rozumiem o co chodzi z tą heurestyką. Poza tym ten algorytm nie działa...
P-180490
DejaVu
» 2023-11-25 20:03:40
Ten kod działa i ma rysowanie mapki po każdym kroku.
C/C++
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <algorithm>

struct Point {
   
int x, y;
   
Point()
        :
x( 0 )
       
, y( 0 )
   
{ }
   
Point( int x, int y )
        :
x( x )
       
, y( y )
   
{ }
   
   
bool operator ==( const Point & other ) const {
       
return x == other.x && y == other.y;
   
}
   
   
bool operator !=( const Point & other ) const {
       
return x != other.x || y != other.y;
   
}
   
   
bool operator <( const Point & other ) const {
       
return std::tie( x, y ) < std::tie( other.x, other.y );
   
}
}
;

namespace std {
   
template < >
   
struct hash < Point > {
       
size_t operator()( const Point & p ) const {
           
return hash < int >()( p.x ) ^ hash < int >()( p.y );
       
}
    }
;
}

int heuristic( const Point & a, const Point & b ) {
   
return abs( a.x - b.x ) + abs( a.y - b.y );
}

std::vector < Point > getNeighbors( const Point & p, const std::vector < std::vector < bool >> & map ) {
   
std::vector < Point > neighbors;
   
int dx[ 4 ] = { 1, 0, - 1, 0 };
   
int dy[ 4 ] = { 0, 1, 0, - 1 };
   
for( int i = 0; i < 4; ++i ) {
       
int nx = p.x + dx[ i ], ny = p.y + dy[ i ];
       
if( nx >= 0 && nx < map.size() && ny >= 0 && ny < map[ 0 ].size() && map[ nx ][ ny ] ) {
           
neighbors.emplace_back( nx, ny );
       
}
    }
   
return neighbors;
}

std::vector < Point > aStar( const std::vector < std::vector < bool >> & map, const Point & start, const Point & goal ) {
   
std::priority_queue < std::pair < int, Point >, std::vector < std::pair < int, Point >>, std::greater < >> openSet;
   
std::unordered_map < Point, Point > cameFrom;
   
std::unordered_map < Point, int > costSoFar;
   
   
openSet.emplace( 0, start );
   
cameFrom[ start ] = start;
   
costSoFar[ start ] = 0;
   
   
while( !openSet.empty() ) {
       
Point current = openSet.top().second;
       
openSet.pop();
       
       
if( current == goal ) {
           
std::vector < Point > path;
           
while( current != start ) {
               
path.push_back( current );
               
current = cameFrom[ current ];
           
}
           
path.push_back( start );
           
std::reverse( path.begin(), path.end() );
           
return path;
       
}
       
       
for( const Point & next: getNeighbors( current, map ) ) {
           
int newCost = costSoFar[ current ] + 1;
           
if( costSoFar.find( next ) == costSoFar.end() || newCost < costSoFar[ next ] ) {
               
costSoFar[ next ] = newCost;
               
int priority = newCost + heuristic( next, goal );
               
openSet.emplace( priority, next );
               
cameFrom[ next ] = current;
           
}
        }
    }
   
   
return { }; // No path found
}

void drawMap( const std::vector < std::vector < bool >> & map, const Point & playerPos )
{
   
std::cout << "=============\n";
   
int x = 0;
   
for( const auto & row: map )
   
{
       
int y = 0;
       
for( const auto & cell: row )
       
{
           
if( playerPos.x == x && playerPos.y == y )
               
 std::cout << "* ";
           
else
               
 std::cout <<( cell ? "_ ": "X " );
           
           
++y;
       
}
       
std::cout << "\n";
       
x++;
   
}
   
std::cout << "\n";
}

int main() {
   
std::vector < std::vector < bool >> map = {
        {
true, true, true, false },
       
{ false, true, false, true },
       
{ true, true, true, true }
    }
;
   
   
Point start( 0, 0 );
   
Point goal( 2, 3 );
   
   
std::vector < Point > path = aStar( map, start, goal );
   
   
for( const auto & row: map )
   
{
       
for( const auto & cell: row )
           
 std::cout <<( cell ? "_ "
           
: "X " );
       
       
std::cout << "\n";
   
}
   
   
std::cout << "Path: ";
   
for( const Point & p: path )
       
 std::cout << "(" << p.x << ", " << p.y << ") ";
   
   
std::cout << "\n";
   
for( const Point & p: path )
       
 drawMap( map, p );
   
   
   
return 0;
}
P-180493
tBane
Temat założony przez niniejszego użytkownika
» 2023-11-26 13:17:01
Ok, dziękuję. Teraz pozostało mi kod zrozumieć.
Co oznacza ten fragment kodu

C/C++
namespace std {
   
template < >
   
struct hash < Point > {
       
size_t operator()( const Point & p ) const {
           
return hash < int >()( p.x ) ^ hash < int >()( p.y );
       
}
    }
;
}
P-180497
pekfos
» 2023-11-26 16:13:38
Specjalizacja std::hash<> dla Point. Funkcja hashująca potrzebna by można było używać Point jako klucza w tablicy hashującej std::unordered_map.
P-180499
« 1 »
  Strona 1 z 1