mrDIMAS

A* Pathfinding

Dec 19th, 2016
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.37 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <float.h>
  4. #include <math.h>
  5.  
  6. typedef struct Vec3 {
  7.     float x, y, z;
  8. } Vec3;
  9.  
  10. typedef struct GraphVertex {
  11.     float gScore;
  12.     float fScore;
  13.     struct GraphVertex * ancestor;
  14.     Vec3 position;
  15.     struct GraphVertex ** neighbours;
  16.     int neighbourCount;
  17. } GraphVertex;
  18.  
  19. typedef struct Path {
  20.     GraphVertex ** vertices;
  21.     int count;
  22. } Path;
  23.  
  24. #define Array_Append(elements,elementCounter,newElement) \
  25.     do { \
  26.         ++elementCounter; \
  27.         elements = realloc( elements, elementCounter * sizeof( *elements )); \
  28.         elements[elementCounter - 1] = newElement; \
  29.     } while( 0 ); \
  30.  
  31.  
  32. #define Array_GetIndex(elements,elementCounter,element,outIndex) \
  33.     do { \
  34.         int _k; \
  35.         outIndex = -1; \
  36.         for( _k = 0; _k < elementCounter; ++_k ) { \
  37.             if( elements[_k] == element ) { \
  38.                 outIndex = _k; \
  39.             } \
  40.         } \
  41.     } while( 0 ); \
  42.    
  43. #define Array_Remove(elements,element,elementCounter) \
  44.     do { \
  45.         int ____aIndex; \
  46.         Array_GetIndex(elements,elementCounter,element, ____aIndex ); \
  47.         if( ____aIndex >= 0 && ____aIndex < elementCounter ) { \
  48.             int k; \
  49.             --elementCounter; \
  50.             for( k = ____aIndex; k < elementCounter; ++k ) { \
  51.                 elements[ k ] = elements[ k + 1 ]; \
  52.             } \
  53.             elements = realloc( elements, elementCounter * sizeof( *elements )); \
  54.         } \
  55.     } while( 0 ); \
  56.      
  57. GraphVertex * GraphVertexCreate(const Vec3 * position) {
  58.     GraphVertex * g = calloc(1, sizeof(GraphVertex));
  59.     g->gScore = FLT_MAX;
  60.     g->fScore = FLT_MAX;
  61.     g->position = *position;
  62.     return g;
  63. }
  64.  
  65. void GraphVertexLink(GraphVertex * a, GraphVertex * b) {
  66.     int i, f;
  67.    
  68.     f = 0;
  69.     for(i = 0; i < a->neighbourCount; ++i) {
  70.         if(a->neighbours[i] == b) {
  71.             f = 1;
  72.         }
  73.     }
  74.     if(!f) {
  75.         Array_Append(a->neighbours, a->neighbourCount, b);
  76.     }
  77.    
  78.    
  79.    
  80.     f = 0;
  81.     for(i = 0; i < b->neighbourCount; ++i) {
  82.         if(b->neighbours[i] == a) {
  83.             f = 1;
  84.         }
  85.     }
  86.     if(!f) {
  87.         Array_Append(b->neighbours, b->neighbourCount, a);
  88.     }
  89. }
  90.  
  91. float Heuristic(GraphVertex * a, GraphVertex * b) {
  92.     float dx = a->position.x - b->position.x;
  93.     float dy = a->position.y - b->position.y;
  94.     float dz = a->position.z - b->position.z;
  95.     return dx * dx + dy * dy + dz * dz;
  96. }
  97.  
  98. float Distance(GraphVertex * a, GraphVertex * b) {
  99.     float dx = a->position.x - b->position.x;
  100.     float dy = a->position.y - b->position.y;
  101.     float dz = a->position.z - b->position.z;
  102.     return sqrt(dx * dx + dy * dy + dz * dz);
  103. }
  104.  
  105. Path * AStar(GraphVertex * start, GraphVertex * goal) {
  106.     Path * path = calloc(1, sizeof(Path));
  107.     GraphVertex ** closedSet = NULL;
  108.     int closedSetSize = 0;
  109.     GraphVertex ** openSet = NULL;
  110.     int openSetSize = 0;
  111.  
  112.    
  113.     Array_Append(openSet, openSetSize, start);
  114.  
  115.     start->gScore = 0;
  116.     start->fScore = Heuristic(start, goal);
  117.  
  118.     while(openSetSize > 0) {
  119.         int i, j;
  120.         GraphVertex * current = openSet[0];
  121.         for(i = 1; i < openSetSize; ++i) {
  122.             if(current->fScore < openSet[i]->fScore) {
  123.                 current = openSet[i];
  124.             }
  125.         }
  126.  
  127.         if(current == goal) {
  128.             GraphVertex * v = goal;
  129.             while(v != start) {
  130.                 Array_Append(path->vertices, path->count, v);              
  131.                 v = v->ancestor;
  132.             }
  133.            
  134.             Array_Append(path->vertices, path->count, start);
  135.            
  136.             break;
  137.         }
  138.  
  139.         Array_Remove(openSet, current, openSetSize);       
  140.         Array_Append(closedSet, closedSetSize, current);
  141.        
  142.         for(i = 0; i < current->neighbourCount; ++i) {
  143.             int neighbourInOpenSet = 0;
  144.             int neighbourInClosedSet = 0;
  145.             GraphVertex * neighbour = current->neighbours[i];
  146.            
  147.            
  148.             for(j = 0; j < closedSetSize; ++j) {
  149.                 if(neighbour == closedSet[j]) {
  150.                     neighbourInClosedSet = 1;
  151.                     break;
  152.                 }
  153.             }
  154.            
  155.             if(neighbourInClosedSet) {
  156.                 continue;
  157.             }
  158.            
  159.             float tentative_gScore = current->gScore + Distance(current, neighbour);
  160.            
  161.             for(j = 0; j < openSetSize; ++j) {
  162.                 if(neighbour == openSet[j]) {
  163.                     neighbourInOpenSet = 1;
  164.                     break;
  165.                 }
  166.             }
  167.            
  168.             if(!neighbourInOpenSet) {
  169.                 Array_Append(openSet, openSetSize, neighbour);
  170.             } else if(tentative_gScore >= neighbour->gScore) {
  171.                 continue;
  172.             }
  173.            
  174.             neighbour->ancestor = current;
  175.             neighbour->gScore = tentative_gScore;
  176.             neighbour->fScore = neighbour->gScore + Heuristic(neighbour, goal);
  177.         }
  178.     }
  179.    
  180.     free(openSet);
  181.     free(closedSet);
  182.    
  183.     return path;
  184. }
  185.  
  186.  
  187. int main(int argc, char ** argv) {
  188.     int i;
  189.     Path * path;
  190.     GraphVertex ** vertices = NULL;
  191.     int vertexCount = 0;
  192.     Vec3 positions[] = {
  193.         {0, 0, 0}, /* 0 */
  194.         {1, 1, 0}, /* 1 */
  195.         {2, 1, 0}, /* 2 */
  196.         {3, 2, 0}, /* 3 */
  197.         {3, 3, 0}, /* 4 */
  198.         {2, 2, 0}, /* 5 */
  199.         {2, 4, 0}, /* 6 */
  200.         {1, 3, 0}, /* 7 */
  201.     };
  202.    
  203.     for(i = 0; i < sizeof(positions) / sizeof(positions[0]); ++i) {
  204.         Array_Append(vertices, vertexCount, GraphVertexCreate(&positions[i])); 
  205.     }
  206.    
  207.     GraphVertexLink(vertices[0], vertices[1]);
  208.     GraphVertexLink(vertices[1], vertices[2]);
  209.     GraphVertexLink(vertices[2], vertices[3]);
  210.     GraphVertexLink(vertices[3], vertices[4]);
  211.     GraphVertexLink(vertices[4], vertices[5]);
  212.     GraphVertexLink(vertices[5], vertices[6]);
  213.     GraphVertexLink(vertices[5], vertices[7]);
  214.     GraphVertexLink(vertices[7], vertices[1]);
  215.    
  216.  
  217.     path = AStar(vertices[6], vertices[0]);
  218.    
  219.     if(path && path->vertices) {
  220.         for(i = 0; i < path->count; ++i) {
  221.             printf("(%f; %f; %f)\n", path->vertices[i]->position.x, path->vertices[i]->position.y, path->vertices[i]->position.z);
  222.         }
  223.     }
  224.    
  225.     system("pause");
  226.    
  227.     return 0;
  228. }
Advertisement
Add Comment
Please, Sign In to add comment