Advertisement
thecplusplusguy

A* algorithm (graphical) implementation

Jul 6th, 2012
401
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.40 KB | None | 0 0
  1. //A* algorithm (might poor) implementation by http://www.youtube.com/user/thecplusplusguy
  2. //graphical, press s, to place a start point (use mouse, to place it), e for end point, w for walls, press u, and it will search the shortest path between the 2 point around the walls
  3. //SDL library used
  4. #include <iostream>
  5. #include <fstream>
  6. #include <SDL/SDL.h>
  7. #include <vector>
  8. #include <cmath>
  9. #include <map>
  10.  
  11. const int TILE_SIZE=5;
  12. const int WIDTH=128;
  13. const int HEIGHT=96;
  14.  
  15. struct Matrixindex{
  16.     int x,y;
  17.     Matrixindex(int yi,int xi) : y(yi),x(xi){};
  18.     Matrixindex() : y(0),x(0) {};
  19.     bool operator<(const Matrixindex& m2) const {return (true);};
  20. };
  21.  
  22.  
  23. std::vector<Matrixindex> comefrom;
  24. std::map<Matrixindex,Matrixindex> comefrom2;
  25. struct tableElement{
  26.     char tile;
  27.     int g_score;
  28.     int h_score;
  29.     int f_score;
  30. };
  31.  
  32. int getDistance(int x1,int y1,int x2,int y2)
  33. {
  34.     //Manhattan distance
  35. //  return abs(x2-x1)+abs(y2-y1);
  36.     return sqrt((x2-x1)*(x2-x1) + (y2-y1) * (y2-y1));
  37. }
  38.  
  39. int getSmallest(tableElement table[HEIGHT][WIDTH],std::vector<Matrixindex> mi,Matrixindex& matrixindex)
  40. {
  41.     if(mi.size()==1)
  42.     {
  43.         matrixindex=mi[0];
  44.         return 0;
  45.     }
  46.     int smallest=0;
  47.     for(int i=1;i<mi.size();i++)
  48.     {  
  49.         if(table[mi[i].y][mi[i].x].f_score<table[mi[smallest].y][mi[smallest].x].f_score)
  50.             smallest=i;
  51.     }
  52.     matrixindex=mi[smallest];
  53.     return smallest;
  54. }
  55.  
  56. bool inVector(std::vector<Matrixindex> mi,Matrixindex matrixindex)
  57. {
  58.     for(int i=0;i<mi.size();i++)
  59.         if(mi[i].x==matrixindex.x && mi[i].y==matrixindex.y)
  60.             return true;
  61.     return false;
  62. }
  63. int elementInVector(std::vector<Matrixindex> mi,Matrixindex key)
  64. {
  65.     for(int i=0;i<mi.size();i++)
  66.         if(mi[i].y==key.y && mi[i].x==key.x)
  67.             return i;
  68.     return -1;
  69. }
  70.  
  71. std::vector<Matrixindex> child;
  72. std::vector<Matrixindex> father;
  73.  
  74.  
  75. void reconstruct_path(Matrixindex current,int starty,int startx)
  76. {
  77.     Matrixindex tmp=current;
  78.     while(tmp.y!=starty || tmp.x!=startx)
  79.     {
  80.         comefrom.push_back(tmp);
  81.         tmp=father[elementInVector(child,tmp)];
  82.     }
  83. }
  84.  
  85.  
  86.  
  87.  
  88.  
  89. void findPath(tableElement table[HEIGHT][WIDTH],int startx,int starty,int endx,int endy)
  90. {
  91.         child.clear();
  92.         father.clear();
  93.         std::vector<Matrixindex> closedset;
  94.         std::vector<Matrixindex> openset;
  95.         openset.push_back(Matrixindex(starty,startx));
  96.         table[starty][startx].f_score=getDistance(endx,endy,startx,starty);
  97.         table[starty][startx].h_score=0;
  98.         table[starty][startx].g_score=table[starty][startx].f_score+table[starty][startx].h_score;
  99.         Matrixindex current(0,0);
  100.         int curindex;
  101.         while(openset.size()!=0)
  102.         {
  103.             curindex=getSmallest(table,openset,current);
  104.             if(endx==openset[curindex].x && endy==openset[curindex].y)
  105.             {
  106.                 reconstruct_path(current,starty,startx);
  107.                 std::cout << "found" << std::endl;
  108.                 break;
  109.             }
  110.             closedset.push_back(current);
  111.             openset.erase(openset.begin()+curindex);
  112.             int g_score;
  113.             bool better;
  114.             for(int i=-1;i<=1;i+=1)
  115.                 for(int j=-1;j<=1;j+=1)
  116.                 {
  117.                     Matrixindex neighbor=Matrixindex(current.y+i,current.x+j);
  118.                     if(neighbor.x<0 || neighbor.x>=WIDTH || neighbor.y<0 || neighbor.y>=HEIGHT)
  119.                         continue;
  120.                     if(inVector(closedset,neighbor))
  121.                         continue;
  122.                     if(table[neighbor.y][neighbor.x].tile==1)
  123.                         continue;
  124.                     //comment out, if diagonal movement allowed
  125.                     if(i!=0 && j!=0)
  126.                         continue;
  127.                     if(current.x==neighbor.x || current.y==neighbor.y)
  128.                         g_score=table[current.y][current.x].g_score+10;
  129.                     else
  130.                         g_score=table[current.y][current.x].g_score+14;
  131.                     if(!inVector(openset,neighbor))
  132.                     {
  133.                         openset.push_back(neighbor);
  134.                         table[neighbor.y][neighbor.x].h_score=getDistance(endx,endy,neighbor.x,neighbor.y)*10;
  135.                         better=true;
  136.                     }else if(g_score<table[neighbor.y][neighbor.x].g_score)
  137.                         better=true;
  138.                     else
  139.                         better=false;
  140.                     if(better)
  141.                     {
  142.                         child.push_back(neighbor);
  143.                         father.push_back(current);
  144.                         table[neighbor.y][neighbor.x].g_score=g_score;
  145.                         table[neighbor.y][neighbor.x].f_score=table[neighbor.y][neighbor.x].g_score+table[neighbor.y][neighbor.x].h_score;
  146.                     }          
  147.                 }
  148.         }
  149.         return;
  150. }
  151.  
  152.  
  153. int main()
  154. {
  155.     SDL_Init(SDL_INIT_EVERYTHING);
  156.     SDL_Surface* screen=SDL_SetVideoMode(TILE_SIZE*WIDTH,TILE_SIZE*HEIGHT,32,SDL_SWSURFACE);
  157.     tableElement table[HEIGHT][WIDTH];
  158.     for(int i=0;i<HEIGHT;i++)
  159.         for(int j=0;j<WIDTH;j++)
  160.         {
  161.             table[i][j].tile=0;
  162.             table[i][j].g_score=table[i][j].h_score=table[i][j].f_score=0;
  163.         }
  164.     char curtile=1;
  165.     bool running=true;
  166.     SDL_Event event;
  167.     Uint32 start;
  168.     SDL_Rect curcoord={0,0,TILE_SIZE,TILE_SIZE};
  169.     Uint32 curcolor=SDL_MapRGB(screen->format,128,128,128);
  170.     int x=0,y=0;
  171.     bool clicked=false;
  172.     int startx=-1;
  173.     int starty=-1;
  174.     int endx=-1;
  175.     int endy=-1;
  176.     while(running)
  177.     {
  178.         start=SDL_GetTicks();
  179.         while(SDL_PollEvent(&event))
  180.         {
  181.             switch(event.type)
  182.             {
  183.                 case SDL_QUIT:
  184.                     running=false;
  185.                     break;
  186.                 case SDL_KEYDOWN:
  187.                     switch(event.key.keysym.sym)
  188.                     {
  189.                         case SDLK_ESCAPE:
  190.                             running=false;
  191.                             break;
  192.                         case SDLK_w:
  193.                             curtile=1;
  194.                             break;
  195.                         case SDLK_s:
  196.                             curtile=2;
  197.                             break;
  198.                         case SDLK_e:
  199.                             curtile=3;
  200.                             break;
  201.                         case SDLK_n:
  202.                             curtile=0;
  203.                             break;
  204.                         case SDLK_u:
  205.                             comefrom.clear();
  206.                             findPath(table,startx,starty,endx,endy);
  207.                             break;
  208.                     }
  209.                     break;
  210.                 case SDL_MOUSEMOTION:
  211.                     x=event.motion.x/TILE_SIZE;
  212.                     y=event.motion.y/TILE_SIZE;
  213.                     if(clicked)
  214.                     {
  215.                         if(curtile==2)
  216.                         {
  217.                             startx=x;
  218.                             starty=y;
  219.                         }else if(curtile==3)
  220.                         {
  221.                             endx=x;
  222.                             endy=y;
  223.                         }else
  224.                             table[y][x].tile=curtile;
  225.                     }
  226.                     curcoord.x=x*TILE_SIZE;
  227.                     curcoord.y=y*TILE_SIZE;
  228.                     if(curtile==0)
  229.                         curcolor=SDL_MapRGB(screen->format,255,255,255);
  230.                     else if(curtile==1)
  231.                         curcolor=SDL_MapRGB(screen->format,128,128,128);
  232.                     else if(curtile==2)
  233.                         curcolor=SDL_MapRGB(screen->format,0,255,0);
  234.                     else
  235.                         curcolor=SDL_MapRGB(screen->format,255,0,0);
  236.                     SDL_FillRect(screen,&curcoord,curcolor);
  237.                     break;
  238.                 case SDL_MOUSEBUTTONDOWN:
  239.                     clicked=true;
  240.                     if(curtile==2)
  241.                     {
  242.                         startx=x;
  243.                         starty=y;
  244.                     }else if(curtile==3)
  245.                     {
  246.                         endx=x;
  247.                         endy=y;
  248.                     }else
  249.                         table[y][x].tile=curtile;
  250.                     break;
  251.                 case SDL_MOUSEBUTTONUP:
  252.                     clicked=false;
  253.                     break;
  254.             }
  255.         }
  256.         for(int i=0;i<HEIGHT;i++)
  257.             for(int j=0;j<WIDTH;j++)
  258.             {
  259.                 if(i==y && j==x)
  260.                     continue;
  261.                 curcoord.x=j*TILE_SIZE;
  262.                 curcoord.y=i*TILE_SIZE;
  263.                 if(table[i][j].tile==0)
  264.                     curcolor=SDL_MapRGB(screen->format,255,255,255);
  265.                 else
  266.                     curcolor=SDL_MapRGB(screen->format,128,128,128);
  267.                 SDL_FillRect(screen,&curcoord,curcolor);
  268.             }
  269.         if(startx!=-1 && starty!=-1)
  270.         {
  271.             curcolor=SDL_MapRGB(screen->format,0,255,0);
  272.             curcoord.x=startx*TILE_SIZE;
  273.             curcoord.y=starty*TILE_SIZE;
  274.             SDL_FillRect(screen,&curcoord,curcolor);
  275.         }
  276.         if(endx!=-1 && endy!=-1)
  277.         {
  278.             curcolor=SDL_MapRGB(screen->format,255,0,0);
  279.             curcoord.x=endx*TILE_SIZE;
  280.             curcoord.y=endy*TILE_SIZE;
  281.             SDL_FillRect(screen,&curcoord,curcolor);       
  282.         }
  283.        
  284.         for(int i=0;i<comefrom.size();i++)
  285.         {
  286.                 curcoord.x=comefrom[i].x*TILE_SIZE;
  287.                 curcoord.y=comefrom[i].y*TILE_SIZE;
  288.                 curcolor=SDL_MapRGB(screen->format,5,128,25);
  289.                 SDL_FillRect(screen,&curcoord,curcolor);
  290.         }
  291.        
  292.         SDL_Flip(screen);
  293.         if(1000/30>(SDL_GetTicks()-start))
  294.             SDL_Delay(1000/30-(SDL_GetTicks()-start));
  295.     }
  296.     SDL_Quit();
  297.     return 0;
  298. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement