| 
 Dijkstra's 
  Path Finding Algorithm 
  Author 
  : 
  Jack Hoxley 
  Written : 26th January 2001 
  Contact : [Web] 
  [Email] 
                                Download : GM_Dijkstra.Zip 
                                [62 Kb] 
 
Contents 
  of this lesson: 
  1. Introduction 
  2. The Problem 
  3. Solving it using a graph 
  4. The Data Structures 
  5. Dijkstra's Algorithm 
  6. Making this work in code 
  7. Enhancing the Algorithm 
 
1. 
  Introduction 
Path 
  finding is a crucial part of almost every game, and has been for a very long 
  time. Take your average strategy game - Red Alert for example - select a unit 
  and click somewhere on the map, off the unit goes until it gets to the location 
  - how did it get there, why didn't it get stuck anywhere? The reason being that 
  it used a path finding algorithm of some kind. Even games like Quake/Unreal 
  use path finding - your character may not, but how does the enemy get from A 
  to B? 
There 
  are many forms of path finding, graph based, natural, bump 'n' grind, tracing, 
  orbital... each subset with many different implementations, or complete hybrids 
  of both. Depending on the type of game and the players view point, selecting 
  a good path finding algorithm is essential - an RTS game using the bump 'n' 
  grind method (where it drives into a wall, changes angle a bit, drives into 
  the wall, changes angle again - until it gets around the object) would look 
  awful - the player would be able to watch his crack, highly trained army tanks 
  driving into rocks and trees quicker than a learner driver... Natural algorithms 
  (modelling genetics) are by far the best type of algorithm for path finding 
  - for looks anyway; they simulate (theoretically) how our minds solve the problem 
  of path finding; but unfortunately they aren't really a realistic option just 
  yet - they require vast amounts of memory and quite a bit of processing power 
  - which isn't good for the current set of computer hardware available. 
By 
  the end of this article you will be able to construct, with ease, a path finding 
  module for your game - lightning quick and very simple as well. This algorithm 
  can traverse a fairly simple map in a fraction of a millisecond - anything from 
  1/10000th to 1/1000000th of a second - which is pretty damn fast. After we have 
  our path, all we need to do is follow it... 
 
2. 
  The Problem 
Take 
  a blank map - just a flat terrain, choose a point A and B, to get from A to 
  B you just follow a vector between the two - not too complicate really. Introduce 
  something as simple as a tree in this landscape and it gets a whole lot more 
  complicated - if the line between AB is blocked by the tree we either have to 
  walk through it or walk around it - which isn't too difficult in this case, 
  just sidestep, go around and get back on course again. Introduce a more complicated 
  set of obstacles - caves, paths, forests, cliffs, buildings - and it gets even 
  more complicated; so complicated that you probably wouldn't be able to get to 
  where you want to without getting stuck somewhere. Take this picture for example... 
  
On 
  the above picture you can see two paths - "As the Crow flies" and 
  "As the Crow Walks", assuming that the unit cannot actually fly over 
  the obstructions you can instantly see the problem with the straight (red) line 
  method. Instead we would have to take the blue line - and walk around and between 
  the various obsticles on our route. 
So, 
  to put it simply, the problem is - how do we mathematically (and programmatically) 
  calculate a path from A to B in a similiar style to the blue line?  
 
3. 
  Solving it using a graph 
Now 
  we've outlined the problem we can start thinking about how to solve it. The 
  easiest, fastest and most realistic looking method is by using graphs. Not graphs 
  like bar-charts and line-graphs that you may be used to - network graphs. The 
  following illustration will explain: 
  
The 
  blue lines and red dots are the graph, and as you can see they extend to almost 
  every place on the map. A bit of terminology for you: The red dots are vertices 
  (plural of vertex) and the blue, connecting, lines are called edges. Some people 
  call them nodes and arcs, but they all mean the same thing. 
To 
  construct a graph the first thing we need to do is place the vertices, these 
  should be key points that extend into all the little nooks and crannies of our 
  world, this example uses 40 of them, but you can quite easily go into the hundreds 
  before it starts to slow down to much. The key point to remember when placing 
  these vertices is NOT to put them too close together, and not put them too far 
  apart. Each vertex needs to be able to "see" another vertex along 
  a straight line, in order to do this you may need to add additional vertices 
  to the world. The order that they are placed in doesn't really matter a great 
  deal - but some sort of logical pattern will help slightly later on. 
The 
  next step will be to work out where the edges go, if you take a quick look at 
  the above illustration you'll see that each vertex has at most 4 edges coming 
  out of it, and that all edges have a start and end vertex. I've programmed the 
  algorithm to only use 4 possible routes from one vertex purely because of processing 
  power, as we'll see later on the algorithm needs to analyse each vertex connected 
  to the current vertex before it'll move on - having 100 possible edges coming 
  from one vertex will quite obviously cause a slow down; should you need more 
  than this you can easily increase it to 5 or 6, but many more than that and 
  it might start slowing down. 
  
Just 
  a little bit more complicated now, as I said before, a logical pattern to numbering 
  is quite useful - in this case it tends to go left-right and back again. With 
  this information we can now construct our edges, we know what vertices there 
  are, we know how to identify them (through the number). Visually we can tell 
  that vertex 17 connects to vertices 10,12,20 and 21 - if we store this information 
  we can draw a line between vertex 17 and all the vertices it connects to. Do 
  this for every vertex on the map and we have ourselves a graph. This part will 
  almost certainly be done by a level designer pre-runtime and then saved out; 
  it would be fairly slow to generate them at runtime; and anyway - you fancy 
  writing an algorithm that designs a graph for the level? I didn't think so... 
 
4. 
  The Data Structures 
Now 
  we get onto the fun part, writing the code to hold all this data. At first glance 
  it looks fairly simple, but there are several ways in which it can go wrong 
  (I tried a few methods before getting one that I liked). The data that we need 
  to store can be contained in two UDT's :  
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        '//Basic 2D Point structure
 
Private Type NodePoint 
    X As Long 
    Y As Long 
End Type 
 
 
Private Const nNodes As Long = 40 
Dim NodeList(0 To nNodes - 1) As NodePoint 
 
 
'//A structure that connects everything up
 
Private Type TreeNode 
    CurrNode As Long '//Pointer to an entry in the NodePoint Structure
 
    NextNode(0 To 3) As Long '//Pointer to 4 attached nodes
 
    Dist(0 To 3) As Double '//The weight of the edge CurrNode -> NextNode(n)
 
End Type 
 
 
Dim TreeNodeList(0 To nNodes - 1) As TreeNode | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
Not 
  too complicated really, but some explaining is required. The type NodePoint 
  could probably be integrated into the TreeNode structure, but I prefer it this 
  way around, makes things slightly easier I think. First we create an array of 
  nodes based on the constant nNodes (40 in this case), this array represents 
  the red dots on the diagrams above. Next we create a TreeNode structure, this 
  acts as a set of extended information on the red dots, where each node connects 
  and how far. The CurrNode member points to an entry in the NodeList( ) array, 
  so if we want to find the actual coordinates of the point we could use something 
  like: 
NodeList(TreeNodeList(n).CurrNode).X 
  , NodeList(TreeNodeList(n).CurrNode).Y 
and 
  if we wanted to look at a node that this one connects to we can analyse the 
  the NextNode( ) property: 
TreeNodeList(TreeNodeList(n).NextNode(0)).CurrNode 
Which 
  will query the node connected to the current node n for which NodePoint 
  it's using.  
Lastly 
  we create an array of these tree nodes the same size as the number of actual 
  nodes there are - effectively saying, one tree node per node. You may well think 
  that some nodes, on the very edge of the graph, dont need a TreeNode structure 
  - that's wrong. If we know how to get there we also need to know how to get 
  back, when we're sitting on this node we'll have no information about any other 
  nodes that we can get to - even though we just travelled here. In general each 
  node will reference the one it's come from and the one it's going to - so that 
  we can go back and forth around the graph quite easily... 
Filling 
  these structure is quite easy, the sample code (and this article) wont go into 
  how you can load/save the data, or let the user decide where the nodes are, 
  all of it is hardcoded into the Form_Load procedure. This should be avoided 
  at all costs for a proper game, but for this example it really doesn't matter 
  a great deal. It looks like this though: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        NodeList(0).X
                                                                          = 10 
                                                                          NodeList(0).Y
                                                                          = 10 
                                                                          NodeList(1).X
                                                                          = 175 
                                                                          NodeList(1).Y
                                                                          = 10 
                                                                          NodeList(2).X
                                                                          = 340 
                                                                          NodeList(2).Y
                                                                          = 10 
                                                                          NodeList(3).X
                                                                          = 430 
                                                                          NodeList(3).Y
                                                                          = 10 
                                                                          NodeList(4).X
                                                                          = 470 
                                                                          NodeList(4).Y
                                                                          = 60 
 ...
  TreeNodeList(0).CurrNode = 0 
                                                                             
                                                                          TreeNodeList(0).NextNode(0)
                                                                          = 1 
                                                                             
                                                                          TreeNodeList(0).NextNode(1)
                                                                          = -1 
                                                                             
                                                                          TreeNodeList(0).NextNode(2)
                                                                          = -1 
                                                                             
                                                                          TreeNodeList(0).NextNode(3)
                                                                          = -1 
                                                                          TreeNodeList(1).CurrNode
                                                                          = 1 
                                                                             
                                                                          TreeNodeList(1).NextNode(0)
                                                                          = 0 
                                                                             
                                                                          TreeNodeList(1).NextNode(1)
                                                                          = 2 
                                                                             
                                                                          TreeNodeList(1).NextNode(2)
                                                                          = 11 
                                                                             
                                                                          TreeNodeList(1).NextNode(3)
                                                                          = -1 
                                                                          TreeNodeList(2).CurrNode
                                                                          = 2 
                                                                             
                                                                          TreeNodeList(2).NextNode(0)
                                                                          = 1 
                                                                             
                                                                          TreeNodeList(2).NextNode(1)
                                                                          = 3 
                                                                             
                                                                          TreeNodeList(2).NextNode(2)
                                                                          = 12 
                                                                             
                                                                          TreeNodeList(2).NextNode(3)
                                                                          = -1 | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
The 
  only thing to note about this is the inclusion of -1 in the NextNode( ) properties. 
  As explained, the NextNode( ) member points to an entry in it's own array - 
  therefore it must be a + real number and within the array boundaries - which 
  makes -1 an error (you dont have a -1 entry in an array). Later on we'll be 
  including logic that ignores any NextNode( ) entries with a value of -1, which 
  will signify that there is no node to go to from there, which if you think about 
  it is perfectly reasonable, not every node should have or need 4 subsequent 
  edges coming out of it... 
Lastly 
  we need to fill in the Dist( ) members, the reason that these are included will 
  become clear later on, but the calculation for getting the distance between 
  two points isn't as fast as I'd like, so pre-calculating it is preferable. So 
  after we've filled out all the data structures we need to run a loop through 
  all the TreeNodeList( ) entries calculating the distance between it and the 
  connected node. The code for doing this looks like: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        Dim
                                                                          I As
                                                                          Long 
                                                                          For I
                                                                          = 0 To
                                                                          nNodes
                                                                          - 1 
                                                                                 
                                                                          If Not
                                                                          (TreeNodeList(I).NextNode(0)
                                                                          = -1)
                                                                          Then
                                                                          TreeNodeList(I).Dist(0)
                                                                          = _ 
                                                                          GetDist2D(NodeList(TreeNodeList(I).CurrNode).X,
                                                                          NodeList(TreeNodeList(I).CurrNode).Y,
                                                                          _ 
                                                                          NodeList(TreeNodeList(I).NextNode(0)).X,
                                                                          NodeList(TreeNodeList(I).NextNode(0)).Y) 
                                                                                 
                                                                          If Not
                                                                          (TreeNodeList(I).NextNode(1)
                                                                          = -1)
                                                                          Then
                                                                          TreeNodeList(I).Dist(1)
                                                                          = _ 
                                                                          GetDist2D(NodeList(TreeNodeList(I).CurrNode).X,
                                                                          NodeList(TreeNodeList(I).CurrNode).Y,
                                                                          _ 
                                                                          NodeList(TreeNodeList(I).NextNode(1)).X,
                                                                          NodeList(TreeNodeList(I).NextNode(1)).Y) 
                                                                                 
                                                                          If Not
                                                                          (TreeNodeList(I).NextNode(2)
                                                                          = -1)
                                                                          Then
                                                                          TreeNodeList(I).Dist(2)
                                                                          = _ 
                                                                          GetDist2D(NodeList(TreeNodeList(I).CurrNode).X,
                                                                          NodeList(TreeNodeList(I).CurrNode).Y,
                                                                          _ 
                                                                          NodeList(TreeNodeList(I).NextNode(2)).X,
                                                                          NodeList(TreeNodeList(I).NextNode(2)).Y) 
                                                                                 
                                                                          If Not
                                                                          (TreeNodeList(I).NextNode(3)
                                                                          = -1)
                                                                          Then
                                                                          TreeNodeList(I).Dist(3)
                                                                          = _ 
                                                                          GetDist2D(NodeList(TreeNodeList(I).CurrNode).X,
                                                                          NodeList(TreeNodeList(I).CurrNode).Y,
                                                                          _ 
                                                                          NodeList(TreeNodeList(I).NextNode(3)).X,
                                                                          NodeList(TreeNodeList(I).NextNode(3)).Y) 
                                                                          Next I 
                                                                           
                                                                           
 '//The above code uses this function for calculating the distance:
  Private
                                                                          Function
                                                                          GetDist2D(X
                                                                          As
                                                                          Long,
                                                                          Y As
                                                                          Long,
                                                                          X1 As
                                                                          Long,
                                                                          Y1 As
                                                                          Long)
                                                                          As
                                                                          Long 
                                                                             
                                                                          GetDist2D
                                                                          =
                                                                          Sqr(((X
                                                                          - X1)
                                                                          ^ 2) +
                                                                          ((Y -
                                                                          Y1) ^
                                                                          2)) 
                                                                          End
                                                                          Function | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
Looks 
  quite complicated doesn't it - well it isn't. The GetDist2D( ) call is so long 
  partly because of the long names of variables I've used and partly because it 
  requires 4 parameters. Also note the precursor to each calculation: If Not 
  (TreeNodeList(I).NextNode(0) = -1) Then which basically says "If the 
  next node is anything other than -1 we'll calculate the distance", as mentioned 
  above, -1 indicates that the branch does not go anywhere. 
 
5. 
  Dijkstra's Algorithm 
In 
  1959 Dijkstra designed an algorithm to solve such a problem. Take a series of 
  vertices interconnected by edges, each edge has a weight (in this case the distance) 
  and we know the start vertex and the end vertex. 
Before 
  we begin to think about making some code for this algorithm we need to understand 
  how it works, which fortunately is very simple - I picked it up in 15 minutes 
  from my maths book. First I'll explain the stages required to find the path, 
  then I'll run through a simple mathmatical example: 
Step 
  0: Preparation 
  We're going to be doing several calculations and needing to store numbers. These 
  can be setup in the following table: 
 
  
     
      | Vertex Number | 
      Visit Number | 
      Distance | 
      Temporary | 
     
     
      |   | 
        | 
        | 
        | 
     
   
  Step 
    1: Draw out the graph 
    Quite obviously we're going to need to have the graph drawn out in front of 
    us. Draw out the table as well with all the vertex numbers in place, but the 
    rest blank. 
  Step 
    2: Label the start vertex with Distance 0, Visit Number 1 and leave temporary 
    blank. 
  Step 
    3: Update the temporary variable 
    Choose all vertices that are connected to the current vertex and work out 
    the temporary variable by adding the distance in the current node to the distance 
    along the edge to the next node. Place this number in the temporary box ONLY 
    if it is lower than any existing value - if there's nothing there then this 
    will become the first one. We only calculate the temporary value if the vertex 
    DOESN'T have a vist number of distance number. 
  Step 
    4: Choose the next vertex to visit 
    Look through all the vertices in our list, pick the vertex with the lowest 
    temporary value that HASN'T been visited (it doesn't have a visit number of 
    distance value). If there are multiple-identical lowest values you can take 
    your pick. Increment the visit number by one (where the first vertex was 1, 
    we'll go up 2, 3, 4, 5 etc...), and copy the temporary value to the distance 
    box. 
  Step 
    5: Repeat 
    Repeat steps 3 and 4 until the destination vertex has been given a visit number 
    and a distance.  
  Step 
    6: Work out the path 
    The distance value on the destination vertex will be the shortest route from 
    source-destination. But the actual path isn't as simple as reading back through 
    the visit numbers (9, 8, 7, 6, 5...). We have to run another loop through 
    to find the shortest path. It is as simple as this: If vertex A lies on the 
    route then vertex B is the previous vertex if Distance at A - Distance at 
    B = Distance of edge AB. So we scan through all the visited vertices connected 
    to the destination and find which is the correct one, then we scan all visited 
    vertices connected to that vertex for the correct one, then again and again 
    until we reach the place we started from. The list of values we have will 
    be a route from End to Start, all we need to do is reverse this and we have 
    a path going from Start - Finish along the shortest possible route. 
  Simple 
    really. If your still scratching your head I'll run through a simple example 
    for you. 
 
Take 
  the following graph network, okay, you can probably calculate the shortest route 
  easily, but we want to do it using Dijkstra's algorithm. 
  
Task: 
  Find the shortest route from 1 to 5, where the black lines are edges, red dots 
  are vertices, blue numbers are vertex numbers and the green dots are the distances 
  (made up) along the edge. 
Step 
  0 & 2: Draw our table, and add the first vertex 
 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         3 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         8 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         9 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
   
 
  
Step 
  3 ( i ) : Vertices 2, 8 and 9 can be reached from vertex 1, we need to work 
  out their temporary variables and add them to the table: 
  Vertex 2 Temp = 0 + 2 = 2 
  Vertex 8 Temp = 0 + 3 = 3 
  Vertex 9 Temp = 0 + 3 = 3 
 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
        
       | 
       
        
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         8 
       | 
       
        
       | 
       
        
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
        
       | 
       
        
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
   
 
  
Step 
  4 ( i ) : Choose the lowest temporary value from all the unvisited vertices. 
  In this case it will be 2. We move here. 
 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         8 
       | 
       
        
       | 
       
        
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
        
       | 
       
        
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
   
  Step 
    3 ( ii ) : Vertices 1, 3 and 9 can be reached from vertex 2. Vertex 1 
    has already been visited so we ignore that one. Calculate the temporary variables 
    for vertices 3 and 9. 
    Vertex 3 = 2 + 3 = 5 
    Vertex 9 = 2 + 1 = 3 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
        
       | 
       
        
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         8 
       | 
       
        
       | 
       
        
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
        
       | 
       
        
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
   
  Step 
    4 ( ii ) : Choose the lowest temporary value from all the unvisted vertices, 
    we have a choice this time: 8 or 9. I'm going to Choose vertex 9 - as it'll 
    probably get us there quicker. 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
        
       | 
       
        
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         8 
       | 
       
        
       | 
       
        
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
   
  Step 
    3 ( iii ) : Vertices 1, 2 and 10 can all be reached from vertex 9. Calculate 
    their temporary variables and update the table. 
    Vertex 10 = 3 + 4 = 7 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
        
       | 
       
        
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         8 
       | 
       
        
       | 
       
        
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
         7 
       | 
     
   
  Step 
    4 ( iii ) : Choose the lowest temporary variable from all unvisited vertices. 
    In this case it's vertex 8, with a value of 3. Update our table: 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
        
       | 
       
        
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
         7 
       | 
     
   
  Step 
    3 ( iv ) : Vertices 1 and 7 can be reached from vertex 8, having already 
    visited vertex 1 we only need to calculate a temporary value for vertex 7. 
    Vertex 7 = 3 + 5 = 8 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
        
       | 
       
        
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
         7 
       | 
     
   
  Step 
    4 ( iv ) : Choose the lowest temporary value, which in this case is vertex 
    3 with temporary value 5. 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
         5 
       | 
       
         5 
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
         7 
       | 
     
   
  Step 
    3 ( v ) : Vertices 2 and 4 can be visited from vertex 3, having already 
    visited vertex 2 we can ignore it and only calculate vertex 4. 
    Vertex 4 = 5 + 4 = 9 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
         5 
       | 
       
         5 
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
         9 
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
        
       | 
       
        
       | 
       
         7 
       | 
     
   
  Step 
    4 ( v ) : Choose the lowest value, in this instance it's going to be vertex 
    10 with a temporary value of 7. 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
         5 
       | 
       
         5 
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
         9 
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
         6 
       | 
       
         7 
       | 
       
         7 
       | 
     
   
  Step 
    3 ( vi ) : Vertices 4, 7 and 9 can be reached from vertex 10, having already 
    visited vertex 9 we only need to calculate vertices 4 and 7, both of which 
    already have a temporary value (so we may not need to replace it). 
    Vertex 4 = 7 + 1 = 8 
    Vertex 7 = 7 + 1 = 8 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
         5 
       | 
       
         5 
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
         8 
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
        
       | 
       
        
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
         6 
       | 
       
         7 
       | 
       
         7 
       | 
     
   
  Step 
    4 ( vi ) : Choose the lowest temporary value of any unvisited vertex. 
    The only two we can choose from are 4 and 7, both of which have the same value. 
    I'm going to choose vertex 7 to goto next. 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
         5 
       | 
       
         5 
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
         8 
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
         7 
       | 
       
         8 
           
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
         6 
       | 
       
         7 
       | 
       
         7 
       | 
     
   
  Step 
    3 ( vii ) : Vertices 8 and 6 can be visited from vertex 7, vertex 8 having 
    already been visited leaves only vertex 6 to be calculated. 
    Vertex 6 = 8 + 1 = 9 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
         5 
       | 
       
         5 
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
        
       | 
       
        
       | 
       
         8 
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
         9 
       | 
     
     
      |  
         7 
       | 
       
         7 
       | 
       
         8 
           
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
         6 
       | 
       
         7 
       | 
       
         7 
       | 
     
   
  Step 
    4 ( vii ) : Choose the lowest temporary value (getting bored yet. I am) 
    - vertex 4 with a value of 8. 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
         5 
       | 
       
         5 
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
         8 
       | 
       
         8 
       | 
       
         8 
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
         9 
       | 
     
     
      |  
         7 
       | 
       
         7 
       | 
       
         8 
           
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
         6 
       | 
       
         7 
       | 
       
         7 
       | 
     
   
  Step 
    3 ( viii ) : Vertices 3, 5 and 10 can be visited from vertex 4, vertex 
    3 and 10 have already been visited, so we only need to calculate vertex 5. 
    Vertex 5 = 8 + 1 = 9 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
         5 
       | 
       
         5 
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
         8 
       | 
       
         8 
       | 
       
         8 
       | 
     
     
      |  
         5 
       | 
       
        
       | 
       
        
       | 
       
         9 
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
         7 
       | 
       
         8 
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
         6 
       | 
       
         7 
       | 
       
         7 
       | 
     
   
  Step 
    4 ( viii ) : Oh look, we're at the destination - vertex 5. No more calculating 
    required, just fill in the visit number and distance. 
  
     
      |  
         Vertex 
          Number 
       | 
       
         Visit 
          Number 
       | 
       
         Distance 
       | 
       
         Temporary 
       | 
     
     
      |  
         1 
       | 
       
         1 
       | 
       
         0 
       | 
       
         0 
       | 
     
     
      |  
         2 
       | 
       
         2 
       | 
       
         2 
       | 
       
         2 
       | 
     
     
      |  
         3 
       | 
       
         5 
       | 
       
         5 
       | 
       
         5 
       | 
     
     
      |  
         4 
       | 
       
         8 
       | 
       
         8 
       | 
       
         8 
       | 
     
     
      |  
         5 
       | 
       
         9 
       | 
       
         9 
       | 
       
         9 
       | 
     
     
      |  
         6 
       | 
       
        
       | 
       
        
       | 
       
        
       | 
     
     
      |  
         7 
       | 
       
         7 
       | 
       
         8 
       | 
       
         8 
       | 
     
     
      |  
         8 
       | 
       
         4 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         9 
       | 
       
         3 
       | 
       
         3 
       | 
       
         3 
       | 
     
     
      |  
         10 
       | 
       
         6 
       | 
       
         7 
       | 
       
         7 
       | 
     
   
  Finally 
    we've completed the first part of the search. On larger networks you'll very 
    rarely visit such a high proportion of the vertices (90% here), but as it 
    was quite small we've only not visited vertex 6. It's useful to note that 
    it took us only 8 iterations to collect all the information, even if we quadruple 
    this number a computer will make easy work of this algorithm. 
  The 
    last part - deciphering the data so that we're left with a path from vertex 
    1 to 5 isn't too difficult, and goes like this: 
  Vertex 
    5 Distance - Vertex 4 Distance = 9 - 8 = 1 
    Vertex 5 Distance - Vertex 6 Distance = Cant do, didn't visit vertex 6 
     
  So 
    the next vertex back from the destination is 4, path is currently 5-4 
     
  Vertex 
    4 Distance - Vertex 10 Distance = 8 - 7 = 1 'Correct, same as edge length 
    Vertex 4 Distance - Vertex 3 Distance = 8 - 5 = 3 'Incorrect, edge length 
    is 4 
  So 
    vertex 10 is the next one back, path is currently 5-4-10 
  Vertex 
    10 Distance - Vertex 7 Distance = 7 - 8 = -1 'Definately not correct 
    Vertex 10 Distance - Vertex 9 Distance = 7 - 3 = 4 'Correct route 
  Vertex 
    9 is on the route home as well then, path is currently 5-4-10-9 
  Vertex 
    9 Distance - Vertex 2 Distance = 3 - 2 = 1 
    Vertex 9 Distance - Vertex 1 Distance = 3 - 0 = 3 
  Now 
    this is a funny one, both vertices can be on the path, but we'll choose vertex 
    1 - as it's the source vertex. But if we had of chosen vertex 2 instead we'd 
    still get home, just not on the most direct route (from vertex 9 it's 3 units 
    both ways back to node 1). I hadn't actually planned for this to happen, and 
    we're lucky that both ways still yield a valid result. As you'll see in the 
    sample code (you can download it above) I've included a bench mark tool that 
    checks if the graph is a complete graph (a mathematical term for a graph where 
    from every vertex you can get to every other vertex), and out of 10,000 attempts 
    on a 40 vertex graph it's never failed to find a path... 
  So 
    the final path from the finish to the start is 5-4-10-9-1 or 5-4-10-9-2-1, 
    but the first one uses less nodes... As you may well have noticed the path 
    is in the wrong direction, so if we reverse it, travelling from the start 
    (vertex 1) we take the route 9 to 10 to 4 to 5 (destination), which looks 
    like this: 
    
  Which 
    if you think about it looks like the shortest and most direct route from vertex 
    1 to vertex 5. 
 
 
6. 
  Making this work in code 
As 
  you'll agree (I hope), it's much better to let the computer work out the path 
  for us - there's probably about 5 A4 pages of tables and workings in the previous 
  section - and for a relatively simple graph. Fancy calculating the path around 
  an office block? 1000's of nodes? didn't think so.... 
Also, 
  considering the fact that the computer would of done all the above work in under 
  1ms .... 
Onto 
  the main feature then - converting this algorithm to visual basic code. We already 
  have the data structures setup (section 4), so all we really need to do is design 
  a function that takes a start and finish vertex index, and spits out a path 
  that we can follow from A to B. 
The 
  first thing we need to do is update our TreeNode structure so that we can store 
  the table information. We also need to setup an open ended array where we can 
  dump the finalised path in. The updated structures look like: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        '//A structure that connects everything up
 
Private Type TreeNode 
    CurrNode As Long '//Pointer to an entry in the NodePoint Structure
 
    NextNode(0 To 3) As Long '//Pointer to 4 attached nodes
 
    Dist(0 To 3) As Double '//The weight of
the arc CurrNode - NextNode(n) 
    '## DIJKSTRAs ALGORITHM ##
 
    VisitNumber As Long '//What order was this node visited
 
    Distance As Double '//What the current distance was at this point
 
    TmpVar As Double '//Temporary area for storing distance data...
 
End Type
  Dim nPathList As Long '//How many entries are in our path...
 
Dim PATHLIST() As Long | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
Everything 
  else remains the same. Now we move onto the actual pathfinding code. Before 
  we start doing the proper searching we need to lay the ground work: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        Private
                                                                          Function
                                                                          DijkstraPathFinding(NodeSrc
                                                                          As
                                                                          Long,
                                                                          NodeDest
                                                                          As
                                                                          Long)
                                                                          As
                                                                          Boolean 
'//0. Any variables required
                                                                           
                                                                             
                                                                          Dim I
                                                                          As
                                                                          Long 
                                                                             
                                                                          Dim
                                                                          bRunning
                                                                          As
                                                                          Boolean 
                                                                             
                                                                          Dim
                                                                          CurrentVisitNumber
                                                                          As
                                                                          Long '//Which visit the current node will be
                                                                           
                                                                             
                                                                          Dim
                                                                          CurrNode
                                                                          As
                                                                          Long '//Which node we are scanning...
                                                                           
                                                                             
                                                                          Dim
                                                                          LowestNodeFound
                                                                          As
                                                                          Long '//For when we are searching for the lowest temporary value
                                                                           
                                                                             
                                                                          Dim
                                                                          LowestValFound
                                                                          As
                                                                          Double '//For above variable
                                                                           
                                                                               
                                                                             
                                                                          If
                                                                          NodeSrc
                                                                          =
                                                                          NodeDest
                                                                          Then 
        'we're already there...
                                                                           
                                                                                 
                                                                          nPathList
                                                                          = 2 
                                                                                 
                                                                          ReDim
                                                                          PATHLIST(2)
                                                                          As
                                                                          Long 
                                                                                 
                                                                          PATHLIST(1)
                                                                          =
                                                                          NodeSrc 
                                                                                 
                                                                          PATHLIST(2)
                                                                          =
                                                                          NodeDest 
                                                                                 
                                                                          DijkstraPathFinding
                                                                          = True 
                                                                                 
                                                                          Exit
                                                                          Function 
                                                                             
                                                                          End If 
                                                                           
'//1. Setup all the data we need
                                                                           
                                                                             
                                                                          For I
                                                                          = 0 To
                                                                          nNodes
                                                                          - 1 
                                                                                 
                                                                          TreeNodeList(I).VisitNumber
                                                                          = -1 '//-1 indicates not visited
                                                                           
                                                                                 
                                                                          TreeNodeList(I).Distance
                                                                          = -1 '//Unknown distance
                                                                           
                                                                                 
                                                                          TreeNodeList(I).TmpVar
                                                                          =
                                                                          99999 '//A high number that can easily be beaten
                                                                           
                                                                             
                                                                          Next I 
                                                                               
    '//Set the first variable
                                                                           
                                                                             
                                                                          TreeNodeList(NodeSrc).VisitNumber
                                                                          = 1 
                                                                                 
                                                                          CurrentVisitNumber
                                                                          = 1 '//Initialise
                                                                           
                                                                                 
                                                                          CurrNode
                                                                          =
                                                                          NodeSrc 
                                                                             
                                                                          TreeNodeList(NodeSrc).Distance
                                                                          = 0 
                                                                             
                                                                          TreeNodeList(NodeSrc).TmpVar
                                                                          = 0 | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
Above 
  is the function header, the variables that are required and the ground work 
  that needs to be done. The first stage is to check if where we're going is where 
  we're at - in this case it just returns a path starting and finishing in the 
  same place; hopefully the calling function will have checked this already (and 
  decide not to call the function). Next we run through each node setting some 
  default values for the table entries - in particular the .TmpVar value is set 
  very high, hopefully we wont get a graph where we're using edges 100,000 or 
  more in length (cant imagine what would really make use of something like that). 
  Then we do stage 2, make the source node the first visited with distance and 
  temporary variables of 0. 
As 
  you've already seen, the Dijkstra algorithm comes in two parts, visiting and 
  marking the vertices and then tracing the route back. The first part of marking 
  the vertices is shown here. Note that it's effectively an infinite loop, whilst 
  it's unlikely to get stuck on a complete graph if you start modifying the algorithm 
  (see the next section) you could introduce states where the destination cannot 
  be reached - in this case the loop would never terminate. The next section uses 
  a time-out clause that breaks out after a certain time period if no path can 
  be found, if we dont have this the loop could continue for ever (or until windohs 
  crashes). If you think that your implementation will incur this scenario then 
  you should include a time-out clause in this loop as well. 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        Do
                                                                          While
                                                                          bRunning
                                                                          =
                                                                          False
 
'//2a. Go to each node that the current one touches 
        'and make it's temporary variable =
source distance + weight of the arc
                                                                           
                                                                                 
                                                                          If Not
                                                                          (TreeNodeList(CurrNode).NextNode(0)
                                                                          = -1)
                                                                          Then
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(0)).TmpVar
                                                                          = _ 
                                                                          MIN(TreeNodeList(CurrNode).Dist(0)
                                                                          +
                                                                          TreeNodeList(CurrNode).Distance,
                                                                          _ 
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(0)).TmpVar) 
                                                                                 
                                                                          If Not
                                                                          (TreeNodeList(CurrNode).NextNode(1)
                                                                          = -1)
                                                                          Then
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(1)).TmpVar
                                                                          = _ 
                                                                          MIN(TreeNodeList(CurrNode).Dist(1)
                                                                          +
                                                                          TreeNodeList(CurrNode).Distance,
                                                                          _ 
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(1)).TmpVar) 
                                                                                 
                                                                          If Not
                                                                          (TreeNodeList(CurrNode).NextNode(2)
                                                                          = -1)
                                                                          Then
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(2)).TmpVar
                                                                          = _ 
                                                                          MIN(TreeNodeList(CurrNode).Dist(2)
                                                                          +
                                                                          TreeNodeList(CurrNode).Distance,
                                                                          _ 
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(2)).TmpVar) 
                                                                                 
                                                                          If Not
                                                                          (TreeNodeList(CurrNode).NextNode(3)
                                                                          = -1)
                                                                          Then
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(3)).TmpVar
                                                                          = _ 
                                                                          MIN(TreeNodeList(CurrNode).Dist(3)
                                                                          +
                                                                          TreeNodeList(CurrNode).Distance,
                                                                          _ 
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(3)).TmpVar) 
                                                                                   
'//2b. Decide which node has the lowest temporary variable (Free choice if multiple)
                                                                           
                                                                                 
                                                                          LowestValFound
                                                                          =
                                                                          100999 'Hopefully the graph isn't this big :)
                                                                           
                                                                                 
                                                                          For I
                                                                          = 0 To
                                                                          nNodes
                                                                          - 1 '//If we have more than 1000-2000 nodes this part will be horribly slow...
                                                                           
                                                                                     
                                                                          If (TreeNodeList(I).TmpVar
                                                                          <=
                                                                          LowestValFound)
                                                                          And (TreeNodeList(I).TmpVar
                                                                          >=
                                                                          0) And
                                                                          _ 
                                                                          (TreeNodeList(I).VisitNumber
                                                                          <
                                                                          0)
                                                                          Then
                                                                          'make
                                                                          sure
                                                                          we
                                                                          ignore
                                                                          the
                                                                          -1's
                                                                          and
                                                                          visited
                                                                          nodes 
                                                                                         
                                                                          'We
                                                                          have a
                                                                          new
                                                                          lowest
                                                                          value 
                                                                                         
                                                                          LowestValFound
                                                                          =
                                                                          TreeNodeList(I).TmpVar 
                                                                                         
                                                                          LowestNodeFound
                                                                          = I 
                                                                                     
                                                                          End If 
                                                                                 
                                                                          Next I 
        '**NB: If there are multiple lowest values then this method will choose the last one found...
                                                                           
                                                                           
'//2c. Mark this node with the next visit number and copy the tmpvar -> distance
                                                                           
                                                                                 
                                                                          CurrentVisitNumber
                                                                          =
                                                                          CurrentVisitNumber
                                                                          + 1 
                                                                                 
                                                                          TreeNodeList(LowestNodeFound).VisitNumber
                                                                          =
                                                                          CurrentVisitNumber 
                                                                                 
                                                                          TreeNodeList(LowestNodeFound).Distance
                                                                          =
                                                                          TreeNodeList(LowestNodeFound).TmpVar 
                                                                                 
                                                                          CurrNode
                                                                          =
                                                                          LowestNodeFound '//Copy the variable for next time...
                                                                           
                                                                           
'//2d. If this node IS NOT the destination then go onto the next iteration...
                                                                           
                                                                                 
                                                                          If
                                                                          CurrNode
                                                                          =
                                                                          NodeDest
                                                                          Then 
                                                                                     
                                                                          bRunning
                                                                          = True '//We've gotten to the destination
                                                                           
                                                                                 
                                                                          Else 
                                                                                     
                                                                          bRunning
                                                                          =
                                                                          False '//Still not there yet
                                                                           
                                                                                 
                                                                          End If 
                                                                          Loop
 | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
the 
  above is fairly explanatory, and identical to the worked example above. The 
  only reason it looks complicated is because of the large identifiers/names used 
  and the large number of logic statements that need to be evaluated. 
The 
  next part of the function looks equally scary, but is actually very simple. 
  The core code is actually repeated 4 times for each of the possible child nodes, 
  so you only need to understand the first one and you'll understand all the others. 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                          bRunning
                                                                          =
                                                                          False 
                                                                             
                                                                          CurrNode
                                                                          =
                                                                          NodeDest '//Start at the end, and work backwards...
                                                                           
                                                                             
                                                                          Dim
                                                                          lngTimeTaken
                                                                          As
                                                                          Long 
                                                                             
                                                                          lngTimeTaken
                                                                          =
                                                                          GetTickCount 
                                                                               
                                                                             
                                                                          nPathList
                                                                          = 1 
                                                                             
                                                                          ReDim
                                                                          PATHLIST(nPathList)
                                                                          As
                                                                          Long 
                                                                             
                                                                          PATHLIST(1)
                                                                          =
                                                                          NodeDest '//Put the first node in...
                                                                           
                                                                               
                                                                                 
                                                                          Do
                                                                          While
                                                                          bRunning
                                                                          =
                                                                          False 
                                                                                     
            '//First we check that the current node isn't
            actually the start 
                           
            'because if it is then we've found the path already
                                                                           
                                                                                         
                                                                          If
                                                                          CurrNode
                                                                          =
                                                                          NodeSrc
                                                                          Then 
                                                                                             
                                                                          bRunning
                                                                          = True 
                                                                                             
                                                                          GoTo
                                                                          SkipToEnd: 
                                                                                         
                                                                          ElseIf
                                                                          GetTickCount
                                                                          -
                                                                          lngTimeTaken
                                                                          >
                                                                          1000
                                                                          Then 
                    'Break out if we haven't found a solution in under 1 second
                                                                           
                                                                                             
                                                                          bRunning
                                                                          = True 
                                                                                             
                                                                          DijkstraPathFinding
                                                                          =
                                                                          False 
                                                                                             
                                                                          Exit
                                                                          Function 
                                                                                             
                                                                          GoTo
                                                                          SkipToEnd: 
                                                                                         
                                                                          End If 
                                                                                   
            '//Scan through each node that we visited
                                                                           
                                                                                     
                                                                          If (TreeNodeList(CurrNode).NextNode(0)
                                                                          >=
                                                                          0)
                                                                          Then '//Only if there is a node in this direction
                                                                           
                                                                                         
                                                                          If (TreeNodeList(TreeNodeList(CurrNode).NextNode(0)).VisitNumber
                                                                          >=
                                                                          0)
                                                                          Then   
                                                                          
                                                                          
                                                                          '//Only
                                                                          if we
                                                                          visited
                                                                          this
                                                                          node...
                                                                           
                                                                                             
                                                                          If
                                                                          TreeNodeList(CurrNode).Distance
                                                                          -
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(0)).Distance
                                                                          = _ 
                                                                          TreeNodeList(CurrNode).Dist(0)
                                                                          Then 
                        'NextNode(0) is part of the route home
                                                                           
                                                                                                     
                                                                          nPathList
                                                                          =
                                                                          nPathList
                                                                          + 1 
                                                                                                     
                                                                          ReDim
                                                                          Preserve
                                                                          PATHLIST(nPathList)
                                                                          As
                                                                          Long 
                                                                                                     
                                                                          PATHLIST(nPathList)
                                                                          =
                                                                          TreeNodeList(CurrNode).NextNode(0) 
                                                                                                     
                                                                          CurrNode
                                                                          =
                                                                          TreeNodeList(CurrNode).NextNode(0) 
                                                                                                     
                                                                          GoTo
                                                                          SkipToEnd: 
                                                                                             
                                                                          End If 
                                                                                         
                                                                          End If 
                                                                                     
                                                                          End If 
                                                                                       
                                                                                     
                                                                          If (TreeNodeList(CurrNode).NextNode(1)
                                                                          >=
                                                                          0)
                                                                          Then   '//Only if there is a node in this direction
                                                                           
                                                                                         
                                                                          If (TreeNodeList(TreeNodeList(CurrNode).NextNode(1)).VisitNumber
                                                                          >=
                                                                          0)
                                                                          Then     
                                                                          
                                                                          
                                                                          '//Only
                                                                          if we
                                                                          visited
                                                                          this
                                                                          node...
                                                                           
                                                                                             
                                                                          If
                                                                          TreeNodeList(CurrNode).Distance
                                                                          -
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(1)).Distance
                                                                          = _ 
                                                                          TreeNodeList(CurrNode).Dist(1)
                                                                          Then 
                        'NextNode(1) is part of the route home
                                                                           
                                                                                                     
                                                                          nPathList
                                                                          =
                                                                          nPathList
                                                                          + 1 
                                                                                                     
                                                                          ReDim
                                                                          Preserve
                                                                          PATHLIST(nPathList)
                                                                          As
                                                                          Long 
                                                                                                     
                                                                          PATHLIST(nPathList)
                                                                          =
                                                                          TreeNodeList(CurrNode).NextNode(1) 
                                                                                                     
                                                                          CurrNode
                                                                          =
                                                                          TreeNodeList(CurrNode).NextNode(1) 
                                                                                                     
                                                                          GoTo
                                                                          SkipToEnd: 
                                                                                             
                                                                          End If 
                                                                                         
                                                                          End If 
                                                                                     
                                                                          End If 
                                                                                       
                                                                                     
                                                                          If (TreeNodeList(CurrNode).NextNode(2)
                                                                          >=
                                                                          0)
                                                                          Then   '//Only if there is a node in this direction
                                                                           
                                                                                         
                                                                          If (TreeNodeList(TreeNodeList(CurrNode).NextNode(2)).VisitNumber
                                                                          >=
                                                                          0)
                                                                          Then     
                                                                          
                                                                          
                                                                          '//Only
                                                                          if we
                                                                          visited
                                                                          this
                                                                          node...
                                                                           
                                                                                             
                                                                          If
                                                                          TreeNodeList(CurrNode).Distance
                                                                          -
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(2)).Distance
                                                                          =
                                                                          _  
                                                                          TreeNodeList(CurrNode).Dist(2)
                                                                          Then 
                        'NextNode(2) is part of the route home
                                                                           
                                                                                                     
                                                                          nPathList
                                                                          =
                                                                          nPathList
                                                                          + 1 
                                                                                                     
                                                                          ReDim
                                                                          Preserve
                                                                          PATHLIST(nPathList)
                                                                          As
                                                                          Long 
                                                                                                     
                                                                          PATHLIST(nPathList)
                                                                          =
                                                                          TreeNodeList(CurrNode).NextNode(2) 
                                                                                                     
                                                                          CurrNode
                                                                          =
                                                                          TreeNodeList(CurrNode).NextNode(2) 
                                                                                                     
                                                                          GoTo
                                                                          SkipToEnd: 
                                                                                             
                                                                          End If 
                                                                                         
                                                                          End If 
                                                                                     
                                                                          End If 
                                                                                       
                                                                                     
                                                                          If (TreeNodeList(CurrNode).NextNode(3)
                                                                          >=
                                                                          0)
                                                                          Then   '//Only if there is a node in this direction
                                                                           
                                                                                         
                                                                          If (TreeNodeList(TreeNodeList(CurrNode).NextNode(3)).VisitNumber
                                                                          >=
                                                                          0)
                                                                          Then     
                                                                          
                                                                          
                                                                          '//Only
                                                                          if we
                                                                          visited
                                                                          this
                                                                          node...
                                                                           
                                                                                             
                                                                          If
                                                                          TreeNodeList(CurrNode).Distance
                                                                          -
                                                                          TreeNodeList(TreeNodeList(CurrNode).NextNode(3)).Distance
                                                                          = _ 
                                                                          TreeNodeList(CurrNode).Dist(3)
                                                                          Then 
                        'NextNode(3) is part of the route home
                                                                           
                                                                                                     
                                                                          nPathList
                                                                          =
                                                                          nPathList
                                                                          + 1 
                                                                                                     
                                                                          ReDim
                                                                          Preserve
                                                                          PATHLIST(nPathList)
                                                                          As
                                                                          Long 
                                                                                                     
                                                                          PATHLIST(nPathList)
                                                                          =
                                                                          TreeNodeList(CurrNode).NextNode(3) 
                                                                                                     
                                                                          CurrNode
                                                                          =
                                                                          TreeNodeList(CurrNode).NextNode(3) 
                                                                                                     
                                                                          GoTo
                                                                          SkipToEnd: 
                                                                                             
                                                                          End If 
                                                                                         
                                                                          End If 
                                                                                     
                                                                          End If 
                                                                                       
                                                                          SkipToEnd: 
                                                                                       
                                                                                 
                                                                          Loop | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
Looks 
  complicated doesn't it. After we've decided that the vertex is part of the path 
  we increase the size of the pathlist by 1 and add the entry in the new space, 
  before setting the current node to be the new path entry we found - and then 
  carrying on. If we get a situation (as in the worked example) where there are 
  two possible paths to take this code will take the first found, as you can see, 
  when it finds a valid vertex it skips straight to the end of the loop, so if 
  there is a valid vertex on NextNode(0) and NextNode(3) it'll evaluate (0) and 
  then skip straight to the end - it wont even look at (3). 
The 
  final part of the code is to reverse the function, if you were really looking 
  to save time and speed up this algorithm (as if it isn't fast enough already) 
  you could remove this next part and read the array backwards - but I find it 
  easier to read it start-finish. 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                           
                                                                          Dim
                                                                          TmpArray()
                                                                          As
                                                                          Long 
                                                                             
                                                                          ReDim
                                                                          TmpArray(nPathList)
                                                                          As
                                                                          Long 
                                                                             
                                                                          For I
                                                                          =
                                                                          nPathList
                                                                          To 1
                                                                          Step
                                                                          -1 
                                                                                 
                                                                          TmpArray(I)
                                                                          =
                                                                          PATHLIST(((nPathList
                                                                          - I) +
                                                                          1)) 
                                                                             
                                                                          Next I 
                                                                             
                                                                          For I
                                                                          = 1 To
                                                                          nPathList 
                                                                                 
                                                                          PATHLIST(I)
                                                                          =
                                                                          TmpArray(I) 
                                                                             
                                                                          Next I 
                                                                               
                                                                          DijkstraPathFinding
                                                                          = True 
                                                                          End
                                                                          Function | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
Not 
  too complicated really, we create an array the same size as the path list, run 
  through the original array backwards copying the data in the correct order into 
  the temporary array, then we copy the temporary array back to the main array. 
  And then we've finished. 
At 
  this point in time we have our path finding algorithm completed, if we feed 
  in two indices to nodes, and the relevent structures are filled out correctly 
  it'll fill out an array with the path to take - what more could you want? The 
  code in it's current form is extremely simple to adapt (see the next section) 
  and easy to implement into other projects - just copy the code and structures 
  across, fill them as you require and off you go.... 
 
7. 
  Enhancing the Algorithm 
In 
  the final section of this mammoth article I want to discuss improvements and 
  alterations that you can make to this algorithm. Whilst it is a perfectly functional 
  algorithm and works 100% of the time on all properly created graphs there are 
  several things that I thought about changing - and it is quite possible you 
  have several adaptations you may want to add. Here's my list: 
Edge 
  Weighting 
  Currently the "weight" of an edge is just the distance between it's 
  start and end vertex. This is fine, but what if we want to disuade the player 
  from going down one route - or in certain circumstances stop them going down 
  a route altogether. One example of this would be a landscape with a swamp and 
  a path. You're standing on one side of the swamp and you want to get across 
  to the other side, if you make a network that joins you directly to the destination, 
  but also goes around the swamp as well, it's almost garaunteed that the path 
  across the swamp will be shorter, therefore the chosen route; but in real life 
  it would be easier to walk around the swamp than walk through it. You could 
  decide on a weighting system so that any edge going over a swamp gets a weight 
  2x the distance, which will almost always make the Dijkstra algorithm choose 
  the path around the edge, even more so if you weighted that path with a 0.5x 
  multiplier. You could also include conditional logic for an edge, if the player 
  has wading boots let him/her use the path across the swamp, or if the player 
  is in a hurry / running away from something let him/her use the path across 
  the swamp. 
Moving 
  the Player 
  This article as only covered finding a route from one point on the graph to 
  another. Unless you have a pointlessly complex graph 99% of the time the player 
  will not be standing on top of a node. Hopefully the player will be standing 
  quite close to one though - and if you scan the network to find the closest 
  node you can vector the player towards that node, then once on the graph you 
  can move them around using interpolation, then once at the end you can do the 
  reverse of getting onto the network. You may well want to set it up so that 
  the player has to choose a node within n distance of itself, otherwise 
  you may well get natural pathfinding problems just getting it to the network. 
  Take a couple of steps back and I mentioned interpolation - whats that then? 
  If you haven't heard of it before it's the process of blending a set of values 
  between the start and end values by a given amount. Use the formula (B * V) 
  + A * (1.0 - V) for this, where A is the source, B is the destination and V 
  is the distance between on a 0.0 to 1.0 scale, where 0.0 is at A and 1.0 is 
  at B. In order to follow the path decide what the start vertex is and the end 
  vertex is, then frame-by-frame move between them, when you're at the destination 
  switch it so that the previous destination is now the start and the destination 
  is now the next vertex in the path list... 
Path 
  Variation 
  You may also encounter the problem of predictabilty when using any graph based 
  algorithm, if the player can see a birds-eye view (as in Red Alert) he/she may 
  well be able to remember the exact route that the AI characters take (or their 
  own), in doing this it can look very unnatural or can lead to poor gameplay 
  (or advantages to the player). To combat this you could either make more could 
  make more complex graphs, but this wouldn't actually work, the algorithm would 
  still pick the same shortest path every time; alternatively when moving along 
  the path you could add or subtract a random amount from the start/finish nodes 
  - this way it wouldn't always end in the same place or start in the same place; 
  this would have to be carefully controlled - small variation in confined spaces, 
  large variation in wide open landscapes. 
Beyond 
  linear 
  Currently the lines drawn between the nodes are always straight lines. If you 
  wanted to make it more natural you could use curved lines between the nodes 
  - but these would have to be closely checked in the editor - the whole point 
  is that the lines dont intersect with any un-passable objects, which is quite 
  likely to happen with curves when in confined areas. If you're using this method 
  with DirectX8 you can make use of the D3DXVec3Hermite or D3DXVec2Hermite to 
  do curved interpolation for you. 
C/C++ 
  DLL 
  Whilst not everyone can also program in C/C++ this algorithm would be very easy 
  to port to a C/C++ DLL for use in VB. Whilst it's already quite fast I haven't 
  tried it on networks with 1000's of vertices in them - if you do find it slows 
  down to much you may well want to consider this option. 
Generating 
  the Graph 
  One very easy way of generating a graph network that I believe Half-Life uses 
  (and probably others as well), is to make the level editor only have to place 
  the vertices, the editor then runs through the 4 closest vertices and puts an 
  edge in - whilst checking if the edge intersects with any solid/impassable objects. 
  Whilst not entirely necessary, it does make it easier for the level designer. 
Storing 
  the graph 
  As mentioned above, the graphs will probably be generated by an editor and saved, 
  rather than generated at runtime. Storing them using VB's binary file access 
  is extremely extremely simple. Use this code snippet to save all the data that 
  this example uses, and to load it again: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        Open
                                                                          FileName
                                                                          For
                                                                          Binary
                                                                          Access
                                                                          Write
                                                                          As #32 
                                                                             
                                                                          Put
                                                                          #32, ,
                                                                          nNodes 
                                                                             
                                                                          Put
                                                                          #32,
                                                                          1,
                                                                          NodeList 
                                                                             
                                                                          Put
                                                                          #32,
                                                                          1,
                                                                          TreeNodeList 
                                                                          Close
                                                                          #32 
                                                                           
                                                                           
                                                                          Open
                                                                          FileName
                                                                          For
                                                                          Binary
                                                                          Access
                                                                          Read
                                                                          As #33 
                                                                             
                                                                          Get
                                                                          #33, ,
                                                                          nNodes            
                                                                          ReDim
                                                                          NodeList(0
                                                                          to
                                                                          nNodes
                                                                          - 1)
                                                                          as
                                                                          Long 
                                                                             
                                                                          Get
                                                                          #33,
                                                                          1,
                                                                          NodeList            
                                                                          ReDim
                                                                          TreeNodeList(0
                                                                          to
                                                                          nNodes
                                                                          -1) as
                                                                          Long 
                                                                             
                                                                          Get
                                                                          #33,
                                                                          1,
                                                                          TreeNodeList 
                                                                          Close
                                                                          #33 | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
You 
  could also save a matrix of possible routes, depending on your graph size it 
  would not be very big at all. In this example I've used 40 nodes, if each of 
  these nodes can visit 39 other nodes (40 including itself) then a simple 2D 
  array would be capable of holding all the possible paths. On average each path 
  appears to pass through 8 vertices, if these are stored as integers (2 bytes) 
  that would require 16 bytes per path stored; 40x40 is 1600 possible paths, which 
  if 16 bytes in length would add up to 25600 bytes, or 25kb - not a particularly 
  large file. This would then require that you never needed to search for a path 
  during the actual game - just look it up in our table; this is fine if the weights 
  of the edges never change - but as mentioned above you may well want to dynamically 
  affect the paths chosen, in which case this method would be useless. For your 
  information, a 100 vertex graph would require 156kb to be stored, maybe less 
  if compression was used. 
Things 
  to bare in mind when designing the graph 
  There are several things that you should bare in mind when designing the graphs 
  for this algorithm, whilst writing the sample code for this I made a couple 
  of mistakes with the edges and it made areas of the graph inaccessable and certain 
  nodes could not be reached. To guarantee that you'll have no problems write 
  a test that checks if every node can be reached by every other node - similar 
  to the 2D lookup table mentioned above, if this is satisfied we call it a Complete 
  Graph. The other thing you need to bare in mind are cycles - or loops. If you 
  design your graph so that there are cycles in it you may well find in the odd 
  situation an area of the graph that once entered cannot be exited, or as far 
  as the algorithm is concerned a solution will not be found. 
   
Directional 
  graphs 
  Something that I haven't covered yet are diagraphs - directional graphs. Currently, 
  as long as the vertices are connected we can travel both ways - from and to. 
  Whilst it's perfectly possible with the current code to design a graph like 
  this, you may well want to add an option so that you can only travel one way 
  along an edge. During the Dijkstra search you can add additional logic in the 
  same place as it checks if "NextNode(0) = -1". If you decide to add 
  this option you have to be aware of two potential problems - sinks and sources. 
  A sink is a vertex where all edges come into it, but none leave it, so once 
  your at that vertex you cant leave again, and with sources you cant get there 
  because all edges point away from it (the only way you can get there is if you 
  start there). 
3D 
  graphs 
  The final thing I can think of is changing this so that it's in 3 dimensions, 
  which is actually so simple it hurts. Change the NodePoint structure to include 
  a Z value, then alter the GetDist2D to be GetDist3D and thats it - the algorithm 
  will adapt fine and carry on working as per normal. 
 
Well 
  done, you've survived a mamoth 24 (A4) page article. If you liked this or found 
  it useful drop me an email at the address at the top of the page (if you can 
  be bothered to scroll up again). If you do you can pick up the source code while 
  you're there... 
                                       |