C Language of A * algorithm principle and source code

Source: Internet
Author: User

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  APATH_H #endif #define  ture  1 #define  FAULT 0//convention: 0 is removable, 1 means not to walk, 2 for starting point, 3 for end point, 4 for path #define  INT_0 0 #define   Int_1 1 #define  INT_2 2 #define  INT_3 3 #define  INT_4 4 #define  map_max_x
 10   //map boundary, two-dimensional array size #define  MAP_MAX_Y 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 **ARRAY, INT ROW, INT 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** ARR, INT ROW, INT 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}     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 J = 0; J < COL; ++J)          {             (map[i] 
+ J)->data = array[i][j];              (MAP[I] + J)->g =
 0;              (MAP[I] + J)->h =
 0;              (MAP[I] + J)->f =
 0;    //(map[i] + j)->g +  (map[i] + j)->H;              (MAP[I] + J)->x = i;              (MAP[I] + J)->y =
 j;              (MAP[I] + J)->close_flag
 = 0;              (MAP[I] + J)->open_flag
 = 0;              (MAP[I] + J)->next =
 NULL;              (MAP[I] + 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  < COL; ++J)     //    {    // 
        (ARRAY[I] + J)->f = j;     //   &NBSP}     for  (int i = 0;  i < row; ++i)     {         for  (INT J = 0; J < COL; ++J)          {            printf ("%d\t",  (
ARRAY[I] + J)->data);        &NBSP}         printf ("\ n");    &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 <  COL; ++J)         {             if  (2 ==  (arr[i] + j)->data)              {         
       start_LNode =  (ARR[I] + 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 <  COL; ++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}     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}     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}         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} 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,  0, 0, 0, 0, 0, 0, 0, 0, 0&NBSP},     {  0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },     {  0, 0, 0, 0, 1, 0, 0, 0, 0, 0&NBSP},      { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0&NBSP},      { 0, 0, 0, 0, 0, 1, 3, 0, 0, 0&NBSP},  
   { 0, 0, 2, 0, 0, 1, 0, 0, 0, 0 },     { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0  },      { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },      { 0, 0, 0, 1, 1, 0, 0, 0, 0, 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);         //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, OPEN_LIST, MAP);
   &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


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.