In-depth A * algorithm-analysis of the application of a * Algorithm in searching for Shortest Paths

Source: Internet
Author: User
Here I will discuss the practical application of the * algorithm, and give an example of the * Algorithm in the shortest path search. It is worth noting that the basic concepts of a * are not introduced here. If you are still not clear about the * algorithm, please refer to the companion article "first understanding a * algorithm".
The example here is a source program on the Amit homepage. You can download it from the Amit website or on my website. When using this source program, you should abide by certain conventions.

1. Programming principles of a * Algorithm
As I said in "first recognized a * algorithm", a * algorithm is the best priority algorithm. There are only some constraints. Let's take a look at how the best priority algorithm is written. The following State space is available: (the starting position is A, the target position is P, and the number after the letter represents the estimated value of the node ).
The following State space is available: (the starting position is A, the target position is P, and the number after the letter indicates the estimated value of the node)

Figure 1 Status Space


Set two tables: open and closed during the search process. The Open Table stores all the nodes that have been generated but not tested. The closed table records the accessed nodes. One step in the algorithm is to rearrange the Open table based on the evaluation function. In this way, only the nodes with the best status in the Open table are considered for each step in the loop. The specific search process is as follows:

1) initial status:
Open = [A5]; closed = [];
2) estimate A5, search for sub-nodes, and put them in the Open table;
Open = [B4, C4, D6]; closed = [A5]
3) estimate B4, search for subnodes, and put them into the open table;
Open = [C4, E5, F5, D6]; closed = [B4, A5]
4) estimate C4; search for subnodes and put them into the open table;
Open = [H3, G4, E5, F5, D6] closed = [C4, B4, A5]
5) estimate H3, search for sub-nodes, and put them in the Open table;
Open = [O2, P3, G4, E5, F5, D6]; closed = h3c4, B4, A5]
6) estimate O2, search for sub-nodes, and put them into the open table;
Open = [P3, G4, E5, F5, D6]; closed = [O2, H3, C4, B4, A5]
7) estimate P3 and the solution has been obtained;

After reading the specific process, let's look at the pseudo program. The pseudo program of the algorithm is as follows:

Best_first_search ()
{
Open = [Start Node];
Closed = [];
While (Open table is not empty)
{
Obtain a node X from open and delete it from the Open table.
If (X is the target node)
{
Obtain the path;
Return path;
}
For (Y of each X subnode)
{
If (Y is not in the Open table or close table)
{
Evaluate the value of Y;
Insert Y to the Open table. // No sorting has been performed.
}
Else if (Y in the Open table)
{
If (the estimated value of Y is smaller than the estimated value of Open table)
Update the valuation value in the Open table;
}
Else // y in the close table
{
If (the estimated value of Y is less than the estimated value of close table)
{
Update the valuation value in the close table;
Remove nodes from the close table and put them in the Open table;
}
}
Insert x nodes into the close table;
Sort the nodes in the Open table according to the estimated value;
} // End
} // End while
} // End func

Ah! When the pseudo program comes out, it should not be a problem to write a source program. The program of the * algorithm is the same as that of the algorithm. You only need to pay attention to the H (n) constraints of g (n) In the evaluate function. If you are not clear about it, you can refer to the first generation of a * algorithm. Now, we can go to another important topic and use the * algorithm to search for the shortest path. Before that, you 'd better understand the previous algorithm carefully. You can contact me if you have no idea.

2. Use the * algorithm to search for the shortest path
In game design, the shortest path search is often involved. Now, a better method is to use the * Algorithm for design. We don't need to worry about the benefits of him. It's good!
Note that all of the following statements are based on the classastar program. You can download this program here. This program is a complete project. Contains an EXE file. You can check it out first.
First, review. The core of the * algorithm is the evaluation function f (n), which consists of g (N) and H (n. G (n) is the price that has passed, and H (n) is the estimated price of N to the target. In this example, g (n) indicates the depth from the starting node to N nodes in the state space, and H (n) indicates the straight line distance from the position of the map where n nodes are located to the target position. Ah! One is the state space and the other is the actual map. Do not make a mistake. In detail, there is an object A. The coordinates on the map are (XA, ya), and the coordinates of the target B to which a will arrive are (XB, Yb ). When you start searching, set a Start Node 1 to generate eight child nodes 2-9 because there are eight directions.

Figure 2 node chart


First look at the search main function:

Void astarpathfinder: findpath (INT Sx, int Sy, int dx, int Dy)
{
Node * node, * bestnode;
Int tilenumdest;

// Obtain the target location for judgment
Tilenumdest = tilenum (sx, Sy );

// Generate open and closed tables
Open = (node *) calloc (1, sizeof (node ));
Closed = (node *) calloc (1, sizeof (node ));

// Generate the Start Node and put it in the Open Table
Node = (node *) calloc (1, sizeof (node ));
Node-> G = 0;

// This is the H value.
Node-> H = (DX-SX) * (DX-SX) + (dy-sy) * (dy-sy); // shocould really use SQRT ().

// This is the calculated F value, that is, the estimated value
Node-> F = node-> G + node-> h;
Node-> nodenum = tilenum (dx, Dy );
Node-> X = DX;
Node-> Y = Dy;

Open-> nextnode = node; // make open list point to first node
For (;;)
{
// Obtain a node with the best valuation value from the Open Table
Bestnode = returnbestnode ();

// Exit if the node is the target node
If (bestnode-> nodenum = tilenumdest) // if we 've found the end, break and finish
Break;
// Otherwise, child nodes are generated.
Generatesuccessors (bestnode, Sx, Sy );
}
Path = bestnode;
}

Let's take a look at generatesuccessors:

Void astarpathfinder: generatesuccessors (node * bestnode, int dx, int Dy)
{
Int X, Y;

// Generate child nodes in eight directions in sequence, which is simple!
// Upper-left
If (freetile (x = bestnode-> X-tilesize, y = bestnode-> Y-tilesize ))
Generatesucc (bestnode, X, Y, dx, Dy );
// Upper
If (freetile (x = bestnode-> X, Y = bestnode-> Y-tilesize ))
Generatesucc (bestnode, X, Y, dx, Dy );
// Upper-right
If (freetile (x = bestnode-> X + tilesize, y = bestnode-> Y-tilesize ))
Generatesucc (bestnode, X, Y, dx, Dy );
// Right
If (freetile (x = bestnode-> X + tilesize, y = bestnode-> Y ))
Generatesucc (bestnode, X, Y, dx, Dy );
// Lower-right
If (freetile (x = bestnode-> X + tilesize, y = bestnode-> Y + tilesize ))
Generatesucc (bestnode, X, Y, dx, Dy );
// Lower
If (freetile (x = bestnode-> X, Y = bestnode-> Y + tilesize ))
Generatesucc (bestnode, X, Y, dx, Dy );
// Lower-left
If (freetile (x = bestnode-> X-tilesize, y = bestnode-> Y + tilesize ))
Generatesucc (bestnode, X, Y, dx, Dy );
// Left
If (freetile (x = bestnode-> X-tilesize, y = bestnode-> Y ))
Generatesucc (bestnode, X, Y, dx, Dy );
}

Look at the most important function generatesucc:

Void astarpathfinder: generatesucc (node * bestnode, int X, int y, int dx, int Dy)
{
Int g, tilenums, c = 0;
Node * Old, * successor;

// Calculate the G value of the subnode
G = bestnode-> G + 1; // G (successor) = g (bestnode) + cost of getting from bestnode to successor
Tilenums = tilenum (x, y); // identification purposes

// Do subnodes open the table again?
If (old = checkopen (tilenums ))! = NULL) // if equal to null then not in open list,
// Else it returns the node in old
{
// If
For (C = 0; C <8; C ++)
If (bestnode-> child [c] = NULL) // Add old to the list of bestnode's children
// (Or successors ).
Break;
Bestnode-> child [c] = old;
// Compare the estimated value in the Open table with the current estimated value (as long as the G value is compared)
If (g) // if our new G value is parent = bestnode;
Old-> G = g;
Old-> F = G + Old-> h;
}
}
Else // in the closed table?
If (old = checkclosed (tilenums ))! = NULL) // if equal to null then not in open list
// Else it returns the node in old
{
// If
For (C = 0; C <8; C ++)
If (bestnode-> child [c] = NULL) // Add old to the list of bestnode's
// Children (or successors). Break;
Bestnode-> child [c] = old;
// Compare the estimated value in the closed table with the current estimated value (as long as the G value is compared)
If (g) // if our new G value is parent = bestnode;
Old-> G = g;
Old-> F = G + Old-> H; // update the estimated values of all old subnodes in sequence.
Propagatedown (old); // since we changed the G value of old, we need
// To propagate this new value downwards, I. e.
// Do a depth-first traversal of the tree!
}
}
Else // neither in the Open Table nor in the close table
{
// Generate a new node
Successor = (node *) calloc (1, sizeof (node ));
Successor-> parent = bestnode;
Successor-> G = g;
Successor-> H = (X-dx) * (X-dx) + (Y-dy) * (Y-dy); // shocould do SQRT (), but since we
Don't really
Successor-> F = G + successor-> H; // care about the distance but just which branch
Looks successor-> X = x; // better this shocould suffice. anyayz it's faster.
Successor-> Y = y;
Successor-> nodenum = tilenums;
// Insert the table into the Open table and sort the table at the same time.
Insert (successor); // insert successor on open list WRT F
For (C = 0; C <8; C ++)
If (bestnode-> child [c] = NULL) // Add old to the list of bestnode's
Children (or successors ).
Break;
Bestnode-> child [c] = successor;
}
}

Haha. A * I understand the algorithm. Of course, I hope you will feel this way. But I have to say a few more words. Take a closer look at this program and you will find that this program is somewhat different from the pseudo program I mentioned earlier. In the generatesucc function, when the subnode is in the closed table, the child node is not deleted from the closed table and put into the Open table. Instead, it directly recalculates the estimated values of all the subnodes of the node (using the propagatedown function ). This is faster. In addition, when the subnode is in an Open table or a closed table, after the estimated value is re-calculated, the nodes in the Open table are not re-ordered. Why not? Will it be a small bug. Do you know how to tell me?
Okay. The main contents are all finished. Let's take a closer look at the source program. I hope I can help you a little bit. If you disagree with the point in the article or have a better explanation, let me know.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.