web-dev-qa-db-fra.com

Calculer l'itinéraire le plus court entre deux points

Au cours des dernières semaines, j'ai travaillé sur un jeu HTML5 multijoueur, en utilisant nodejs et websockets.

Je suis coincé dans ce problème depuis quelque temps. Imaginez que cette mappe de tuiles soit implémentée avec un tableau (comme indiqué ci-dessous).

1 ou tuiles brunes - il y a un obstacle sur le chemin et le joueur ne peut pas le traverser.

0 ou les tuiles vertes - sont des chemins libres sur lesquels le joueur est autorisé à se déplacer. 

Accédez à n’importe quelle tuile sur la carte en appelant:

 array[x][y]

 tilesheet map - calculate the shortest route

J'aimerais créer l'algorithme le plus rapide possible pour trouver l'itinéraire le plus court (s'il en existe un) entre deux points de la carte. Comment aborderiez-vous ce problème? Je sais que c'est un problème commun. 

Exemple

Le joueur à la position (1,7) tire une balle avec une IA qui le dirigera vers le joueur ennemi à la position (6,0). Bullet doit calculer le chemin le plus court entre les 2 joueurs et s’il n’existait pas, il exploserait contre un mur.

Question

Comment trouver efficacement l'itinéraire le plus court entre deux points?

19
Daniel Oliveira

Bien que l'algorithme de dijkstra fonctionne définitivement, dans votre cas, le graphe est un graphe non pondéré, de sorte qu'un simple BFS devrait suffire.

Pseudo code:

queue = [startingposition]
prev = [-1, -1, -1 ...] (array of n elements, all -1)
while (queue not empty) 
   u <- pop(queue)
   if u = targetposition then DONE! trace the *prev* array for path
   for (v in every unvisited points adjacent to u):
      prev[v] = u
      Push v to queue
   end for
end while

Le tableau prev peut également être utilisé pour vérifier si un point est visité.

3
Can Nguyen

Ici, il n'y a pas de condition de calcul du coût de chemin car tout le coût est égal à 1. Vous pouvez donc exécuter ici l'algorithme BFS 2D normal et la complexité sera de O (V + E) (sommet et bord).

Ici, chaque noeud a deux propriétés. L'un est la ligne et l'autre est la colonne. Donc, vous pouvez créer une paire pour indiquer la valeur d'une cellule. Voici le code c ++ et l'explication:

#define pii pair<int,int>
int fx[]={1,-1,0,0}; //Direction array for moving one cell to another cell horizontaly
int fy[]={0,0,1,-1}; //Direction array for moving one cell to another cell verticaly
int cell[100][100]; //cell[x][y] if this cell is -1 then it is block (Here it is your brown cell)
int d[100][100],vis[100][100]; //d means destination from source. 
int row,col;
void bfs(int sx,int sy) //Source node is in [sx][sy] cell.
{
    memset(vis,0,sizeof vis);
    vis[sx][sy]=1;
    queue<pii>q; //A queue containing STL pairs
    q.Push(pii(sx,sy));
    while(!q.empty())
    {       
        pii top=q.front(); q.pop();
        for(int k=0;k<4;k++)
        {
            int tx=top.uu+fx[k];
            int ty=top.vv+fy[k]; //Neighbor cell [tx][ty]
            if(tx>=0 and tx<row and ty>=0 and ty<col and cell[tx][ty]!=-1 and vis[tx][ty]==0) //Check if the neighbor is valid and not visited before.
            {               
                vis[tx][ty]=1;
                d[tx][ty]=d[top.uu][top.vv]+1; 
                q.Push(pii(tx,ty)); //Pushing a new pair in the queue
            }
        }
    }
}

Maintenant, vous pouvez facilement trouver votre chemin le plus court à partir de la cellule d [x] [y].

1
rafana