Advertisement
hugol

Untitled

Mar 23rd, 2012
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.19 KB | None | 0 0
  1. // Astar.cpp
  2. // http://en.wikipedia.org/wiki/A*
  3. // Compiler: Dev-C++ 4.9.9.2
  4. // FB - 201012256
  5. #include <iostream>
  6. #include <iomanip>
  7. #include <queue>
  8. #include <string>
  9. #include <math.h>
  10. #include <ctime>
  11. using namespace std;
  12.  
  13. const int n=60; // horizontal size of the map
  14. const int m=60; // vertical size size of the map
  15. static int map[n][m];
  16. static int closed_nodes_map[n][m]; // map of closed (tried-out) nodes
  17. static int open_nodes_map[n][m]; // map of open (not-yet-tried) nodes
  18. static int dir_map[n][m]; // map of directions
  19. const int dir=8; // number of possible directions to go at any position
  20. // if dir==4
  21. //static int dx[dir]={1, 0, -1, 0};
  22. //static int dy[dir]={0, 1, 0, -1};
  23. // if dir==8
  24. static int dx[dir]={1, 1, 0, -1, -1, -1, 0, 1};
  25. static int dy[dir]={0, 1, 1, 1, 0, -1, -1, -1};
  26.  
  27. class node
  28. {
  29.     // current position
  30.     int xPos;
  31.     int yPos;
  32.     // total distance already travelled to reach the node
  33.     int level;
  34.     // priority=level+remaining distance estimate
  35.     int priority;  // smaller: higher priority
  36.  
  37.     public:
  38.         node(int xp, int yp, int d, int p)
  39.             {xPos=xp; yPos=yp; level=d; priority=p;}
  40.    
  41.         int getxPos() const {return xPos;}
  42.         int getyPos() const {return yPos;}
  43.         int getLevel() const {return level;}
  44.         int getPriority() const {return priority;}
  45.  
  46.         void updatePriority(const int & xDest, const int & yDest)
  47.         {
  48.              priority=level+estimate(xDest, yDest)*10; //A*
  49.         }
  50.  
  51.         // give better priority to going strait instead of diagonally
  52.         void nextLevel(const int & i) // i: direction
  53.         {
  54.              level+=(dir==8?(i%2==0?10:14):10);
  55.         }
  56.        
  57.         // Estimation function for the remaining distance to the goal.
  58.         const int & estimate(const int & xDest, const int & yDest) const
  59.         {
  60.             static int xd, yd, d;
  61.             xd=xDest-xPos;
  62.             yd=yDest-yPos;        
  63.  
  64.             // Euclidian Distance
  65.             d=static_cast<int>(sqrt(xd*xd+yd*yd));
  66.  
  67.             // Manhattan distance
  68.             //d=abs(xd)+abs(yd);
  69.            
  70.             // Chebyshev distance
  71.             //d=max(abs(xd), abs(yd));
  72.  
  73.             return(d);
  74.         }
  75. };
  76.  
  77. // Determine priority (in the priority queue)
  78. bool operator<(const node & a, const node & b)
  79. {
  80.   return a.getPriority() > b.getPriority();
  81. }
  82.  
  83. // A-star algorithm.
  84. // The route returned is a string of direction digits.
  85. string pathFind( const int & xStart, const int & yStart,
  86.                  const int & xFinish, const int & yFinish )
  87. {
  88.     static priority_queue<node> pq[2]; // list of open (not-yet-tried) nodes
  89.     static int pqi; // pq index
  90.     static node* n0;
  91.     static node* m0;
  92.     static int i, j, x, y, xdx, ydy;
  93.     static char c;
  94.     pqi=0;
  95.  
  96.     // reset the node maps
  97.     for(y=0;y<m;y++)
  98.     {
  99.         for(x=0;x<n;x++)
  100.         {
  101.             closed_nodes_map[x][y]=0;
  102.             open_nodes_map[x][y]=0;
  103.         }
  104.     }
  105.  
  106.     // create the start node and push into list of open nodes
  107.     n0=new node(xStart, yStart, 0, 0);
  108.     n0->updatePriority(xFinish, yFinish);
  109.     pq[pqi].push(*n0);
  110.     open_nodes_map[x][y]=n0->getPriority(); // mark it on the open nodes map
  111.  
  112.     // A* search
  113.     while(!pq[pqi].empty())
  114.     {
  115.         // get the current node w/ the highest priority
  116.         // from the list of open nodes
  117.         n0=new node( pq[pqi].top().getxPos(), pq[pqi].top().getyPos(),
  118.                      pq[pqi].top().getLevel(), pq[pqi].top().getPriority());
  119.  
  120.         x=n0->getxPos(); y=n0->getyPos();
  121.  
  122.         pq[pqi].pop(); // remove the node from the open list
  123.         open_nodes_map[x][y]=0;
  124.         // mark it on the closed nodes map
  125.         closed_nodes_map[x][y]=1;
  126.  
  127.         // quit searching when the goal state is reached
  128.         //if((*n0).estimate(xFinish, yFinish) == 0)
  129.         if(x==xFinish && y==yFinish)
  130.         {
  131.             // generate the path from finish to start
  132.             // by following the directions
  133.             string path="";
  134.             while(!(x==xStart && y==yStart))
  135.             {
  136.                 j=dir_map[x][y];
  137.                 c='0'+(j+dir/2)%dir;
  138.                 path=c+path;
  139.                 x+=dx[j];
  140.                 y+=dy[j];
  141.             }
  142.  
  143.             // garbage collection
  144.             delete n0;
  145.             // empty the leftover nodes
  146.             while(!pq[pqi].empty()) pq[pqi].pop();          
  147.             return path;
  148.         }
  149.  
  150.         // generate moves (child nodes) in all possible directions
  151.         for(i=0;i<dir;i++)
  152.         {
  153.             xdx=x+dx[i]; ydy=y+dy[i];
  154.  
  155.             if(!(xdx<0 || xdx>n-1 || ydy<0 || ydy>m-1 || map[xdx][ydy]==1
  156.                 || closed_nodes_map[xdx][ydy]==1))
  157.             {
  158.                 // generate a child node
  159.                 m0=new node( xdx, ydy, n0->getLevel(),
  160.                              n0->getPriority());
  161.                 m0->nextLevel(i);
  162.                 m0->updatePriority(xFinish, yFinish);
  163.  
  164.                 // if it is not in the open list then add into that
  165.                 if(open_nodes_map[xdx][ydy]==0)
  166.                 {
  167.                     open_nodes_map[xdx][ydy]=m0->getPriority();
  168.                     pq[pqi].push(*m0);
  169.                     // mark its parent node direction
  170.                     dir_map[xdx][ydy]=(i+dir/2)%dir;
  171.                 }
  172.                 else if(open_nodes_map[xdx][ydy]>m0->getPriority())
  173.                 {
  174.                     // update the priority info
  175.                     open_nodes_map[xdx][ydy]=m0->getPriority();
  176.                     // update the parent direction info
  177.                     dir_map[xdx][ydy]=(i+dir/2)%dir;
  178.  
  179.                     // replace the node
  180.                     // by emptying one pq to the other one
  181.                     // except the node to be replaced will be ignored
  182.                     // and the new node will be pushed in instead
  183.                     while(!(pq[pqi].top().getxPos()==xdx &&
  184.                            pq[pqi].top().getyPos()==ydy))
  185.                     {                
  186.                         pq[1-pqi].push(pq[pqi].top());
  187.                         pq[pqi].pop();      
  188.                     }
  189.                     pq[pqi].pop(); // remove the wanted node
  190.                    
  191.                     // empty the larger size pq to the smaller one
  192.                     if(pq[pqi].size()>pq[1-pqi].size()) pqi=1-pqi;
  193.                     while(!pq[pqi].empty())
  194.                     {                
  195.                         pq[1-pqi].push(pq[pqi].top());
  196.                         pq[pqi].pop();      
  197.                     }
  198.                     pqi=1-pqi;
  199.                     pq[pqi].push(*m0); // add the better node instead
  200.                 }
  201.                 else delete m0; // garbage collection
  202.             }
  203.         }
  204.         delete n0; // garbage collection
  205.     }
  206.     return ""; // no route found
  207. }
  208.  
  209. int main()
  210. {
  211.     srand(time(NULL));
  212.  
  213.     // create empty map
  214.     for(int y=0;y<m;y++)
  215.     {
  216.         for(int x=0;x<n;x++) map[x][y]=0;
  217.     }
  218.  
  219.     // fillout the map matrix with a '+' pattern
  220.     for(int x=n/8;x<n*7/8;x++)
  221.     {
  222.         map[x][m/2]=1;
  223.     }
  224.     for(int y=m/8;y<m*7/8;y++)
  225.     {
  226.         map[n/2][y]=1;
  227.     }
  228.    
  229.     // randomly select start and finish locations
  230.     int xA, yA, xB, yB;
  231.     switch(rand()%8)
  232.     {
  233.         case 0: xA=0;yA=0;xB=n-1;yB=m-1; break;
  234.         case 1: xA=0;yA=m-1;xB=n-1;yB=0; break;
  235.         case 2: xA=n/2-1;yA=m/2-1;xB=n/2+1;yB=m/2+1; break;
  236.         case 3: xA=n/2-1;yA=m/2+1;xB=n/2+1;yB=m/2-1; break;
  237.         case 4: xA=n/2-1;yA=0;xB=n/2+1;yB=m-1; break;
  238.         case 5: xA=n/2+1;yA=m-1;xB=n/2-1;yB=0; break;
  239.         case 6: xA=0;yA=m/2-1;xB=n-1;yB=m/2+1; break;
  240.         case 7: xA=n-1;yA=m/2+1;xB=0;yB=m/2-1; break;
  241.     }
  242.  
  243.     cout<<"Map Size (X,Y): "<<n<<","<<m<<endl;
  244.     cout<<"Start: "<<xA<<","<<yA<<endl;
  245.     cout<<"Finish: "<<xB<<","<<yB<<endl;
  246.     // get the route
  247.     clock_t start = clock();
  248.     string route=pathFind(xA, yA, xB, yB);
  249.     if(route=="") cout<<"An empty route generated!"<<endl;
  250.     clock_t end = clock();
  251.     double time_elapsed = double(end - start);
  252.     cout<<"Time to calculate the route (ms): "<<time_elapsed<<endl;
  253.     cout<<"Route:"<<endl;
  254.     cout<<route<<endl<<endl;
  255.  
  256.     // follow the route on the map and display it
  257.     if(route.length()>0)
  258.     {
  259.         int j; char c;
  260.         int x=xA;
  261.         int y=yA;
  262.         map[x][y]=2;
  263.         for(int i=0;i<route.length();i++)
  264.         {
  265.             c =route.at(i);
  266.             j=atoi(&c);
  267.             x=x+dx[j];
  268.             y=y+dy[j];
  269.             map[x][y]=3;
  270.         }
  271.         map[x][y]=4;
  272.    
  273.         // display the map with the route
  274.         for(int y=0;y<m;y++)
  275.         {
  276.             for(int x=0;x<n;x++)
  277.                 if(map[x][y]==0)
  278.                     cout<<".";
  279.                 else if(map[x][y]==1)
  280.                     cout<<"O"; //obstacle
  281.                 else if(map[x][y]==2)
  282.                     cout<<"S"; //start
  283.                 else if(map[x][y]==3)
  284.                     cout<<"R"; //route
  285.                 else if(map[x][y]==4)
  286.                     cout<<"F"; //finish
  287.             cout<<endl;
  288.         }
  289.     }
  290.     getchar(); // wait for a (Enter) keypress  
  291.     return(0);
  292. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement