About A * algorithm on the internet there are a lot of, I just looked at the algorithm with C write a bit, and the test is correct upload to share, please correct me! Here is an introduction I found, and mainly based on this implementation.
Search algorithm more than a * this one, there are recursion, not recursion, breadth first, depth first, using the stack, etc., interested can study ~ ~
Simple map
As shown in the simple map, where the green box is the starting point (in A), the middle of the blue is an obstacle, red squares (in B) is the destination. In order to represent a map with a two-dimensional array, we divide the map into small squares.
Two-dimensional arrays in the game's application is a lot of, such as the greedy snake and Tetris basic principle is to move the square. And the map of large game, it is to be all sorts of "landform" spread on such small square.
Steps to find a way
1. Starting from start a, put it into a "open list" as a box to be processed, and the open list is a list of waiting checks.
2. Find the squares that can be reached around the beginning of a, put them in the "open list" and set their "parent squares" to be a.
3. Remove start a from the open list and add the start a to "close list", and the "close list" is a box that doesn't need to be checked again.
The squares of light green strokes in the figure indicate that you have added the open list to wait for the check. The start of a light blue stroke indicates that it has been placed in the close list, and it does not need to perform a check again.
From the "open list" to find the relatively most reliable box, what is the most reliable? They are computed by formula F=g+h.
F = G + H
G means moving from start A to the grid to specify the movement of the squares (which can be moved in the oblique direction).
H represents the estimated cost of moving from a specified square to a terminal B (H has a number of calculations, where we can only move up and down).
We assume that the cost of moving a grid horizontally is 10, and to make it easier to compute, it is 14 to move one grid along the oblique direction. For a more intuitive display of how to operate FGH, the upper-left corner of the square in the figure indicates F, the lower-left corner represents G, and the lower-right corner represents H. See if it's what you think it is?
From the open list, select the square C with the lowest F value (the square to the right of Green start square A), and then treat it as follows:
4. Remove it from the open list and put it in the close list.
5. Check all the squares that are adjacent and can be reached (the obstructions and the "close list" are not considered). If the squares are not in the open list, add them to the open list, calculate the G, H, and F values of the squares, and set their "parent squares" to C.
6. If an adjacent square D is already in the "Open list", check if the G value is lower if you reach it with the new path (that is, the path through C), and if the new G is lower, change its "parent square" to the currently selected square C and recalculate its F and G values. (H values do not need to be recalculated, because the H value is invariant for each square). If the new G-value is higher, it means that it is not a wise choice to go through C again, because it requires a farther way, at which point we do nothing.
As shown in the figure, we select C because its F value is minimal, we remove it from the open list, and add it to the "close list." Three of them are walls on the right, so they are not considered. It has a starting square on the left and has been added to the "close list" and is not considered. So there are only 4 candidates around it. Let's take a look at the lattice below C, which is now G 14, and if we get to it by C, G will be 10 + 10, which is bigger than 14, so we don't do anything.
Then we continue to find the F-value smallest from the "open list", but we find that the top and bottom of C are 54 at the same time. At this point, whichever is OK, for example, we chose the box D below C.
D on the right side is the wall, so do not consider, but why the lower right corner is not added to the "open list"? Because if the block below C can not go, want to reach the lower right corner of the box will need to go from the "corner of the Box" away, in the program to set whether to allow such a walk. (the example in the figure is not allowed to go this way)
So, let's find out the F value from the open list, remove it from the open list, and add it to the close list. Then continue to find the square around it, so the cycle ...
So when does it stop? --When we find the target end box in the "Start list", the path is found.
How to find the path
As shown in the figure above, in addition to the starting box, each box that once or now is in the "open list" has a "parent box" that can be indexed to the original "Starting Square" by "parent", which is the path.
Above transferred from http://www.cnblogs.com/technology/archive/2011/05/26/2058842.html
Here's My Code (c):
Total three files: Apath.h, apath.c, MAIN.C code with detailed comments (I'm lazy, I don't say much).
Apath.h
#include <stdio.h> #include <stdlib.h> #include <string.h> #include < stddef.h> #include <stdbool.h> #ifndef apath_h #define &NBSP;APATH_H #endif #define ture 1 #define &NBSP;FAULT&NBSP;0//convention: 0 is removable, 1 means not to walk, 2 for starting point, 3 for end point, 4 for path #define &NBSP;INT_0&NBSP;0 #define Int_1 1 #define &NBSP;INT_2&NBSP;2 #define &NBSP;INT_3&NBSP;3 #define &NBSP;INT_4&NBSP;4 #define map_max_x
10 //map boundary, two-dimensional array size #define &NBSP;MAP_MAX_Y&NBSP;10 typedef struct lnode { int data; //the values in the corresponding array int F;
//F = G + H; int g; //g: Moves from the start A move to the specified squares, along the paths to the squares that are generated int h; //h: The estimated cost of moving from the specified squares to the endpoint B int x, y; //the coordinates in the corresponding array bool open_flag; //is 1 in the Open list, not 0 bool close_flag; // In the closed list is 1, not 0 struct LNode* next; //for linked list ordering struct lnode* path_next; //
The path used to eventually find}lnode, *linklist;
Linklist initlist (); //returns an initialized linked list lnode** malloc_array2d (Int row, int col);
Void free_array2d (Lnode **arr); Lnode** translate_array (Int array[10][10], int row, int col);
//an ordinary array into an array void output (LNODE&NBSP;**ARRAY,&NBSP;INT&NBSP;ROW,&NBSP;INT&NBSP;COL) of a single linked table node; Lnode* find_start_lnode (lnode** arr, int row, int col); / /Find the starting point from the array lnode* find_end_lnode (LNODE**&NBSP;ARR,&NBSP;INT&NBSP;ROW,&NBSP;INT&NBSP;COL); //find the end point from the array forget what's going on, rewrite it. Bool isexist_alnode_in_list (lnode* curlnode, linklist l_openlist); To see if a node is in a linked list, in return ture, do not return fault//check the current node in the close list to see if the nodes around it are in the openlist chain, not in: added; Check the minimum of G that passes it to the beginning, is: Modify, not: Do not modify// Lnode* check_closelist_curlnode (Lnode* curlnode, lnode* endlnode, linklist l_ Openlist, linklist l_closelist, lnode** arr); LNode* pop_OpenList_ Minnode (linklist l_openlist); //returns the node with the lowest F value in the Open list void Push_openlist_node (Linklist l, lnode *elem); //inserts a node and sorts bool insert_Into_ Closelist (lnode* min_open, linklist l_closelist)//Insert the node with the smallest F value in the openlist to Closelist Int count _lnode_g (Lnode* curlnode, lnode* aheadlnode); // Compute the G-value of a node INT&NBsp;count_lnode_h (Lnode* curlnode, lnode* endlnode); //Compute the H-value int count_lnode_f (lnode* curlnode) of the node; //
Compute the F-value bool isexist_openlist (lnode* curlnode) of the node, //see if the node is in the list, return ture, not return fault
Bool isexist_closelist (Lnode* curlnode);
Bool isobstacle (Lnode* curlnode); Void check_around_curnode (lnode* cur, lnode* endlnode, linklist open_list, Lnode** arr); //Check the surrounding nodes to see if it is appropriate to join the open list
Apath.c
#include "APATH.H" Linklist initlist () { LinkList L = (linklist)
malloc (sizeof (Lnode)); if (l == null) {
printf ("defeat!");
exit (1);
&NBSP;&NBSP;&NBSP;&NBSP} memset (L,0,sizeof (Lnode));
return L; }//linklist () lnode** malloc_array2d (int row, int col) { lnode**
map = (lnode**) malloc (row*sizeof (lnode*) + row*col*sizeof (Lnode));
LNode* head = (lnode*) (Map + row); for (int i = 0; i < row; ++i)
map[i] = head + i*col;
return map; } Lnode** translate_array(Int array[][10], int row, int col) { lnode **map = malloc_array2d (10, 10); for (int i = 0; i < row; ++i) for (INT&NBSP;J&NBSP;=&NBSP;0;&NBSP;J&NBSP;<&NBSP;COL;&NBSP;++J) { (map[i]
+&NBSP;J)->data = array[i][j]; (MAP[I]&NBSP;+&NBSP;J)->g =
0; (MAP[I]&NBSP;+&NBSP;J)->h =
0; (MAP[I]&NBSP;+&NBSP;J)->f =
0; //(map[i] + j)->g + (map[i] + j)->H; (MAP[I]&NBSP;+&NBSP;J)->x = i; (MAP[I]&NBSP;+&NBSP;J)->y =
j; (MAP[I]&NBSP;+&NBSP;J)->close_flag
= 0; (MAP[I]&NBSP;+&NBSP;J)->open_flag
= 0; (MAP[I]&NBSP;+&NBSP;J)->next =
NULL; (MAP[I]&NBSP;+&NBSP;J)->path_next
= NULL;
} return map; }//translate_array () void free_array2d (Lnode **arr) { free (arr);} void Output (Lnode** array, int row, int col) //two-dimensional arrayThe access must indicate the number of digits, or the compiler cannot parse { //for (int i = 0; i < row; ++i) // for (int j = 0; j <&NBSP;COL;&NBSP;++J) // { //
(ARRAY[I]&NBSP;+&NBSP;J)->f = j; &NBSP;&NBSP;&NBSP;&NBSP;//&NBSP;&NBSP;&NBSP;&NBSP} for (int i = 0; i < row; ++i) { for (INT&NBSP;J&NBSP;=&NBSP;0;&NBSP;J&NBSP;<&NBSP;COL;&NBSP;++J) { printf ("%d\t", (
ARRAY[I]&NBSP;+&NBSP;J)->data); &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP} printf ("\ n"); &NBSP;&NBSP;&NBSP;&NBSP}} lnode* find_start_lnode (Lnode** arr, int row, int col) //from the array to find the starting point { LNode* start_LNode = NULL; for (int i = 0; i < row; ++i) { for (int j = 0; j < &NBSP;COL;&NBSP;++J) { if (2 == (arr[i] + j)->data) {
start_LNode = (ARR[I]&NBSP;+&NBSP;J); //starting point h=0,g=0,f= 0 start_LNode->G = 0; start_lnode-
>H = 0; start_lnode- >f = 0; //starting point, the default value is 0 return start_LNode; //return node } }
return null; } lnode* find_end_lnode (Lnode** arr, int row, int col) //from the array to find the endpoint { LNode* end_LNode = NULL; for (int i = 0; i < row; ++i) { for (int j = 0; j < &NBSP;COL;&NBSP;++J) { if (3 == (arr[i] + j)->data) {
end_LNode = (* (arr + i) + j); end_LNode->
f = 0; end_LNode->
g = 0; end_lnode->h = 0; return end_lnode; //return node
} } }
return NULL; } int count_lnode_g (Lnode* curlnode, lnode* aheadlnode) //Compute the G-value of the node { if curlnode->x == aheadlnode->y & & curlnode->y == aheadlnode->y) return
0; if (aheadlnode->x - curlnode->x != 0 && aheadlnode->y - curlnode->y !=0) curlnode->g = aheadlnode->g + 14; else curLNode->G =
aheadlnode->g + 10;
return curLNode->G; } int count_lnode_h (Lnode* curlnode, lnode* endlnode) //compute the H value of the node { curlnode->h = abs (endlnode->x -
curlnode->x) * 10 + abs (endlnode->y - curlnode->y) * 10;
return curLNode->H; } int count_lnode_f (Lnode* curlnode) //compute the F value of the node {
curLNode->F = curLNode->G + curLNode->H;
return curLNode->F; } void push_openlist_node (Linklist l, lnode *elem) //in a small to large order { LNode *p, *q;
p = q = L; while (p->next != null && p->f < ELEM->F) { q = p;
p = p->next; &NBSP;&NBSP;&NBSP;&NBSP} if (p->f < elem->f) q =
p;
elem->next = q->next;
q->next = elem; //Insert succeeded, change property value open_flag = 1 elem->open_flag =
1; } lnode* pop_openlist_minnode (linklist l_openlist ) //returns the node with the lowest F value in the Open list { LNode *elem = NULL; if (L_openlist->next) //to prevent access to empty fingers for security purposesNeedle { l_openlist->next->open_flag
= 0;
elem = L_OpenList->next;
L_OpenList->next = L_OpenList->next->next;
elem->next = NULL; &NBSP;&NBSP;&NBSP;&NBSP} else printf ("
Have a null point in pop_openlist_mimnode () ");
return elem; } bool insert_into_closelist (Lnode* min_open, linklist l_closelist)// Insert the openlist of the lowest F value in the Closelist to go { //does not need to be sorted for nodes in Closelist, using head interpolation
min_open->next = l_closelist->next;
L_CloseList->next = min_Open; min_open->close_flag = 1;
return TURE;
} bool isexist_openlist (Lnode* curlnode) { return curLNode->OPen_flag;}
Bool isexist_closelist (Lnode* curlnode) { return curLNode->Close_flag;}
Bool isobstacle (Lnode* curlnode) { if (curlnode->data == 1)
return TURE;
else return FAULT; Bool isjoin (lnode* cur) //whether the node can join the open list { if (cur->x > -1 && cur->y > -1) //Boundary Detection { if (!isexist_closelist (cur) && !isobstacle (cur)) & nbsp //is neither in the closed list nor the barrier {
return TURE; &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP} else
return FAULT;
} return FAULT; } void insert_open (Lnode *node, lnode* ahead, lnode* endlnode, linklist open_list, lnode** arr) { if (Isjoin (Node)) { if (Isexist_openlist (Node)) { if ( Node->x - ahead->x != 0 && node->y - ahead->y ! = 0) { if (node->f > (ahead->f + 14)) {
count_lnode_g (Node, ahead); count_lnode_f (Node); //h value not changed, so it's still the same value node->path_next = ahead; //also no longer have to insert } } else { if (node- >F > (ahead->f + 10)) {
count_lnode_g (Node, ahead); count_lnode_f (Node); //h value not changed, so it's still the same value node->path_next = ahead; //also no longer have to insert } }
} else {
count_lnode_g (Node, ahead);
count_lnode_h (Node, endLNode);
count_lnode_f (Node);
Node->path_next = ahead; push_openlist_node (open_list,
Node); &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP}  } void check_around_curnode ( Lnode* cur, lnode* endlnode, linklist open_list, lnode** arr) { int x = cur->x;
int y = cur->y; insert_open (Arr[x] + y - 1, cur, endlnode, open_
List, arr); insert_open (Arr[x] + y + 1, cur, endlnode, open_
List, arr); insert_open (Arr[x + 1] + y, cur, endlnode, open_
List, arr); insert_open (Arr[x + 1] + y - 1, cur, endlnode,
open_list, arr); insert_open (Arr[x + 1] + y + 1, cur, endlnode,
open_list, arr); insert_open (Arr[x - 1] + y, cur, endlnode, open_
List, arr); insert_open (Arr[x - 1] + y + 1, cur, endlnode,
open_list, arr); &nBsp; insert_open (Arr[x - 1] + y - 1, cur, endlnode, open_
List, arr); }
Main.c
#include <stdio.h>//#ifndef apath_h #include "Apath.h"//#endif//For simplicity, simply convert the array below into a list of linked lists// Convention: 0 is removable, 1 means that obstacles can not go, 2 for the beginning, 3 for the end, 4 for the path int array[10][10] = { { 0, &NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0&NBSP}, { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, { &NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;1,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0&NBSP}, &NBSP;{&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;1,&NBSP;1,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0&NBSP}, &NBSP;&NBSP;{&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;1,&NBSP;3,&NBSP;0,&NBSP;0,&NBSP;0&NBSP},
{ 0, 0, 2, 0, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, &NBSP;&NBSP;&NBSP;&NBSP; { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, &NBSP;{&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;1,&NBSP;1,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0,&NBSP;0&NBSP},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
Int main () { int row = MAP_MAX_X, col = MAP_MAX_Y;
printf ("hello world!\n"); lnode **map = translate_array (array,row, col); //
Here the map of the array is converted to the map output (map,10,10) of the node map; linklist open_list = initlist (); // Defines and initializes an open list linklist close_list = initlist (); //
A closed list lnode* startlnode = find_start_lnode (Map, row, col); lnode* endlnode = find_end_lnode (Map, row, col); LNode* curLNode = startLNode; //current node = start node curLNode->G = 0;
//compute the three values of the node count_lnode_h (Curlnode, endlnode);
count_lnode_f (Curlnode); push_openlist_node (Open_list, curlnode); //first insert the start node into the Open list while (curlnode->data != 3) { //LNode *e = NULL;
curlnode = pop_openlist_minnode (open_List);
insert_into_closelist (curlnode, close_list); &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;//2, see if the points around the starting point are in the open list, is not added, in the detection after the point F value is the smallest; check_around_curnode (curlnode,
ENDLNODE,&NBSP;OPEN_LIST,&NBSP;MAP);
&NBSP;&NBSP;&NBSP;&NBSP} while (Endlnode->path_next) { printf ("x:%d---y:%d\n", endlnode->path_next->x,
Endlnode->path_next->y); endLNode->path_next = endLNode->path_next->
Path_next;
} return 0; }
Test results (Red Line is the route to find):
Classification