22

I have been working in the past weeks on a multiplayer HTML5 game, using nodejs and websockets.

I've been stuck in this problem for a little while. Imagine that I have this tilesheet map implemented with an array (as shown below).

1 or brown tiles - there is an obstacle in the way and the player can not pass through it.

0 or green tiles - are free paths where the player is allowed to move.

Access any tile on the map by calling:

 array[x][y]

tilesheet map - calculate the shortest route

I would like to create the fastest algorithm possible to find out the shortest route (if there is one) between two points of the map. How would you approach this problem? I know this is common problem.

Example:

Player at the position (1,7) fires a bullet with some AI that will toward the enemy player at the position (6,0). Bullet has to calculate the shortest route between the 2 players and if there aren´t any it would just explode against a wall.

Question:

How to efficiently find the shortest route between two points?

2
  • 1
    Check out Dijkstra's algorithm, (en.wikipedia.org/wiki/Dijkstra%27s_algorithm) as well as this question. It should help you on your way. stackoverflow.com/questions/430142/…
    – roberrrt-s
    Commented Aug 31, 2016 at 18:12
  • 2
    The A* algorithm would also be applicable here. But note that Dijkstra and AStar only have a better asymptotic complexity than some other options. For example, for a 8x8 grid, a simple Breadth-first-search is likely to be faster in practice (also because it is simpler to implement). The performance advantages of Dijkstra may show up for larger grids, maybe 20x20 or so (depending on many factors - consider profiling them for the real application case!)
    – Marco13
    Commented Sep 1, 2016 at 9:25

3 Answers 3

19

This is a common graph theory problem algorithm

In graph theory, the shortest path problem is the problem of finding a path between two vertices (or nodes) in a graph such that the sum of the weights of its constituent edges is minimized.

The problem of finding the shortest path between two intersections on a road map (the graph's vertices correspond to intersections and the edges correspond to road segments, each weighted by the length of its road segment) may be modeled by a special case of the shortest path problem in graphs.

For now exists lot of implementations of this algorithm. More simpler in implementation is a Dijkstra's algorithm with worst case performance as O(|E|+|V|log|V|) where

  • |V| is the number of nodes
  • |E| is the number of edges

Illustration of algorithm work

enter image description here

Definition of Dijkstra's Shortest Path Algorithm

  • initial node - the node at which we are starting.
  • distance of node Y - be the distance from the initial node to Y.

Algorithm will assign some initial distance values and will try to improve them step by step:

  1. Assign to every node a tentative distance value: set it to 0 for our initial node and to ∞ for all other nodes.

  2. Set the initial node as current. Mark all other nodes unvisited. Create a set of all the unvisited nodes called the unvisited set.

  3. For the current node, consider all of its unvisited neighbors and calculate their tentative distances. Compare the newly calculated tentative distance to the current assigned value and assign the smaller one.

  4. When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again.

  5. If the destination node has been marked visited (when planning a route between two specific nodes) or if the smallest tentative distance among the nodes in the unvisited set is ∞ (when planning a complete traversal; occurs when there is no connection between the initial node and remaining unvisited nodes), then stop. The algorithm has finished.

  6. Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3.

More implementations of Dijkstra algorithm you can find on github repository mburst/dijkstras-algorithm.

For example here is JavaScript implementation

2
  • 1
    If your grid was far bigger you'd have a problem using Dijkstra's algorithm. That is, dijkstra (and BFS) both "flood" the graph from the start. They often explore nodes very far from the optimal path. The alternative is to use A* which is similar to dijkstra but also uses a heuristic to help focus on nodes that are likely to be close to the destination.
    – Tom Leys
    Commented Sep 2, 2016 at 1:24
  • This video also explains a calculation example nicely.
    – J0ANMM
    Commented Jan 26, 2017 at 18:17
3

While dijkstra algorithm definitely works, in your case the graph is an unweighted graph, so a simple BFS should suffice.

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

The prev array can also be used to check if a point is visited.

1
  • For me it seems that your answer is closest to OP needs, mine too...can you give me, please, more refferences about BFS? I am not sure if I found the right one... Commented Jan 1, 2018 at 4:52
1

Here there is no condition of calculating path cost because all path cost is 1. So you can run here normal 2D BFS algorithm and the complexity will be O(V+E)(vertex and edge).

Here every node has two property. One is row and other is column. So u can create a pair for denoting the value of a cell. Here is the c++ code and explanation:

#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
            }
        }
    }
}

Now you can easily find your shortest path from the d[x][y] cell.

Not the answer you're looking for? Browse other questions tagged or ask your own question.