A* Pathfinding Algorithm

Given? an ?n? x ?n ?grid ?with ?a ?person? and ?obstacles, ?how? would ?you ?find ?a? path ?for ?the? person? to? a? particular ?destination?? ?The ?person? is ?permitted? to? move ?left,?right,? up,? and? down.

Sample Input:

............
....oo..d...
....o.......
.p..oooo....
............

‘p‘ represents the start position, ‘o‘ a obstacle, d ‘ the destination.

Output: a optimal path from  ‘p‘ to ‘d‘

C++ Sample Code (using A* method to find a optimal path):

  1 #include <iostream>
  2 #include <vector>
  3 #include <unordered_set>
  4 #include <set>
  5 #include <string>
  6 #include <cstdlib>
  7 #include <climits>
  8 using namespace std;
  9
 10 struct Point {
 11     int i, j;
 12     Point(int _i = -1, int _j = -1) : i(_i), j(_j) {}
 13 };
 14
 15 int get_index(int cols, const Point& point) {
 16     return point.i * cols + point.j;
 17 }
 18
 19 vector<Point> neighbor_points(vector<vector<char>>& grid, int index) {
 20     vector<Point> result;
 21     int rows = grid.size(), cols = grid[0].size();
 22     int i = index / cols, j = index % cols;
 23     int x[4], y[4];
 24     // 0: left, 1: right, 2: top, 3: bottom
 25     x[0] = i, x[1] = i, x[2] = i-1, x[3] = i+1;
 26     y[0] = j-1, y[1] = j+1, y[2] = j, y[3] = j;
 27     for (int k = 0; k < 4; k++) {
 28         if (x[k] >= 0 && x[k] < rows && y[k] >= 0 && y[k] < cols
 29             && grid[x[k]][y[k]] != ‘o‘) {
 30             result.push_back(Point(x[k], y[k]));
 31         }
 32     }
 33     return result;
 34 }
 35
 36 int h_score_estimate(const Point& p1, const Point& p2) {
 37     return abs(p2.i - p1.i) + abs(p2.j - p1.j);
 38 }
 39
 40 void print_path(int cols, int index, const vector<int>& parent) {
 41     if (index != -1) {
 42         print_path(cols, parent[index], parent);
 43         cout << "(" << index/cols << ", " << index%cols << ") ";
 44     }
 45 }
 46
 47 class my_comp {
 48     const vector<int>& f_score;
 49 public:
 50     my_comp(const vector<int>& f_scr) : f_score(f_scr) {}
 51     bool operator() (const int i, const int j) const {
 52         if (f_score[i] != f_score[j]) {
 53             return f_score[i] < f_score[j];
 54         } else return i < j;
 55     }
 56 };
 57
 58 void A_star(vector<vector<char>>& grid, const Point& person, const Point& destination) {
 59     int rows = grid.size();
 60     int cols = grid[0].size();
 61     int size = rows * cols;
 62
 63     // cost form the start point along best known path
 64     vector<int> g_score(size, INT_MAX);
 65     // estimate total cost from the start point to the destination through a point
 66     vector<int> f_score(size, INT_MAX);
 67
 68     vector<int> parent(size, -1);
 69
 70     set<int, my_comp> open_set((my_comp(f_score))); // the set of node to be evaluated
 71     unordered_set<int> closed_set; // the set of node evaluated
 72
 73     int psn_index = get_index(cols, person);
 74     int dst_index = get_index(cols, destination);
 75
 76     g_score[psn_index] = 0;
 77     f_score[psn_index] = h_score_estimate(person, destination);
 78     open_set.insert(psn_index);
 79
 80     while (!open_set.empty()) {
 81         // get the point with minimal f_score in open_set
 82         int cur_index = *(open_set.begin());
 83         //cout << "curr : (" << cur_index/cols << ", " << cur_index%cols << ")" << endl;
 84         if (cur_index == dst_index) {
 85             cout << "destination found !!!" << endl;
 86             print_path(cols, dst_index, parent);
 87             cout << endl;
 88             return;
 89         }
 90
 91         // switch the current point from open_set to close_set
 92         open_set.erase(cur_index);
 93         closed_set.insert(cur_index);
 94
 95         auto neighbors = neighbor_points(grid, cur_index);
 96         //cout << "no. of neighbors : " << neighbors.size() << endl;
 97         for (auto& neighbor : neighbors) {
 98             //cout << "nbr : (" << neighbor.i << ", " << neighbor.j << ")" << endl;
 99             int nbr_index = get_index(cols, neighbor);
100             if (closed_set.count(nbr_index) != 0) continue;
101
102             int tentative_g_score = g_score[cur_index] + 1 /*dist_between(current, neighbor)*/;
103             if (open_set.count(nbr_index) == 0 || tentative_g_score < g_score[nbr_index]) {
104                 parent[nbr_index] = cur_index;
105                 g_score[nbr_index] = tentative_g_score;
106                 f_score[nbr_index] = g_score[nbr_index] + h_score_estimate(neighbor, destination);
107                 if (open_set.count(nbr_index) != 0) {
108                     open_set.erase(nbr_index);
109                 }
110                 open_set.insert(nbr_index);
111             }
112         }
113     }
114     cout << "destination not found !!!" << endl;
115 }
116
117 int main() {
118     vector<vector<char>> grid;
119     Point person, destination;
120     string line;
121     int i = 0;
122     while (getline(cin, line)) {
123         vector<char> row;
124         for (int j = 0; j < line.size(); j++) {
125             if (line[j] == ‘p‘) {
126                 person = Point(i, j);
127             } else if (line[j] == ‘d‘) {
128                 destination = Point(i, j);
129             }
130             row.push_back(line[j]);
131         }
132         //cout << line << endl;
133         grid.push_back(row);
134         i++;
135     }
136
137     A_star(grid, person, destination);
138     return 0;
139 }

The output of the program with the sample input above:

destination found !!!
(3, 1) (2, 1) (1, 1) (1, 2) (1, 3) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (1, 8) 

The terminologies used in A* algorithm are described on Wikipedia (https://en.wikipedia.org/wiki/A*_search_algorithm).

Summary of the A* Method (From http://www.policyalmanac.org/games/aStarTutorial.htm)

1) Add the starting square (or node) to the open list (open_set in my code).

2) Repeat the following:

a) Look for the lowest F (f_score) cost square on the open list. We refer to this as the current square.

b) Switch it to the closed list (close_set).

c) For each of the 8 squares adjacent to this current square …  (In the problem above, we just consider at most 4 neighbors)

  • If it is not walkable or if it is on the closed list, ignore it. Otherwise do the following.
  • If it isn’t on the open list, add it to the open list. Make the current square the parent of this square. Record the F, G, and H costs of the square.
  • If it is on the open list already, check to see if this path to that square is better, using G cost as the measure. A lower G cost means that this is a better path. If so, change the parent of the square to the current square, and recalculate the G and F scores of the square. If you are keeping your open list sorted by F score, you may need to resort the list to account for the change.

d) Stop when you:

  • Add the target square to the closed list, in which case the path has been found, or
  • Fail to find the target square, and the open list is empty. In this case, there is no path.

3) Save the path. Working backwards from the target square, go from each square to its parent square until you reach the starting square. That is your path.

时间: 2024-10-25 20:02:34

A* Pathfinding Algorithm的相关文章

A Brief Introduction About A-star Pathfinding Algorithm For Beginners

      英文题目,汉语内容,有点挂羊头卖狗肉的嫌疑,不过请不要打击我这颗想学好英语的心.当了班主任我才发现大一18本书,11本是英语的,能多用两句英语就多用,个人认为这样也是积累的一种方法.      Thanks open source pioneers dedicated to computer science especially A*. 一.算法简介      为什么写这个,以前学长就用这个结合MFC做了个小游戏,分为三个等级"弱智,一般,大神",分别采用不同算法来寻找迷宫

如何在Cocos2D游戏中实现A*寻路算法(一)

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流之用,请勿进行商业用途.同时,转载时不要移除本申明.如产生任何纠纷,均与本博客所有人.发表该翻译稿之人无任何关系.谢谢合作! 该篇博客由iOS课程团队的Johann Fradj发布,他现在是一个全职开发iOS的开发者.他是Hot Apps Factory(其是App Cooker的创造者)的共同创建

再译《A *路径搜索入门》之五

■实施上的注意事项 Notes on Implementation 现在您了解了基本的方法,当你编写自己的程序时,有一些额外的事情要考虑.下面给出我用C ++和Blitz Basic编写的程序,用其他语言也同样有效. Now that you understand the basic method, here are some additional things to think about when you are writing your own program. Some of the f

路径搜索相关算法

博客转载自:https://cstheory.stackexchange.com/questions/11855/how-do-the-state-of-the-art-pathfinding-algorithms-for-changing-graphs-d-d-l A lot of pathfinding algorithms have been developed in recent years which can calculate the best path in response to

SE2205: Algorithms and Data Structures

SE2205: Algorithms and Data Structures for Object-Oriented DesignLab Assignment 3Assigned: Mar 20, 2019; Due: April 8, 2019 @ 10:00 a.m.If you are working in a group of two, then indicate the associated student IDsand numbers in the Assignment3.java

A* Pathfinding for Beginners A*算法路径搜索入门

原始链接地址: http://www.gamedev.net/page/resources/_/technical/artificial-intelligence/a-pathfinding-for-beginners-r2003 Updated July 18, 2005 This article has been translated into Albanian, Chinese, French, German, Portuguese, Russian, and Spanish. Other

PLA Percentron Learning Algorithm #台大 Machine learning #

Percentron Learning Algorithm 于垃圾邮件的鉴别 这里肯定会预先给定一个关于垃圾邮件词汇的集合(keyword set),然后根据四组不通过的输入样本里面垃圾词汇出现的频率来鉴别是否是垃圾邮件.系统输出+1判定为垃圾邮件,否则不是.这里答案是第二组. 拿二维数据来做例子.我们要选取一条线来划分红色的叉叉,和蓝色的圈圈样本点(线性划分).怎么做呢?这里的困难之处就在于,其实可行的解可能存在无数条直线可以划分这些样本点.很难全部求解,或许实际生活中并不需要全部求解.于是,

STL algorithm算法is_partitioned(26)

is_partitioned原型: std::is_partitioned template <class InputIterator, class UnaryPredicate> bool is_partitioned (InputIterator first, InputIterator last, UnaryPredicate pred); 测试范围内的元素是否是以pred为准则的一个划分.如果是,则返回true,否则返回false. 划分的意思是说,对每个元素进行pred(*it),得

支付宝支付php的demo或sdk报错 Warning: openssl_sign() [function.openssl-sign]: Unknown signature algorithm. in

最近在做支付宝支付,在本地测试一切正常,上传到服务器就遇到报错: Warning: openssl_sign() [function.openssl-sign]: Unknown signature algorithm. in 后来查了查,是我的服务器上PHP环境支持openssl_sign()但却不支持 OPENSSL_ALGO_SHA256这样的参数,问了一下大佬,才发现这个参数是在php5.4.8以上版本才支持,低版本的是使用的SHA256,于是乎试了一下,搞定! 报错原因是支付宝的dem