A_Star算法C++实现

时间:2024-11-21 07:46:05
  • #include <iostream>
  • #include <algorithm>
  • #include <queue>
  • #include <vector>
  • #include <cmath>
  • #define N 6 // 棋盘/迷宫 的阶数
  • using namespace std;
  • class Node {
  • public:
  • int x, y; // 节点坐标
  • //f=g+h,总代价;
  • //g,上个点到该点的代价;
  • //h,该点到终点的估计值
  • int f, g, h;
  • Node(int a, int b) {
  • this->x = a;
  • this->y = b;
  • }
  • //重载'<'运算符,因为队列不知道怎么对Node排序
  • bool operator < (const Node& a)const {
  • //优先队列是大顶堆,因此这里反过来成为小顶堆。Set是小顶堆,如果用Set,这里的判定用'<'
  • return this->f > ;
  • }
  • };
  • bool visit[N][N]; //记录节点是否访问过
  • int path[N][N][2]; //记录父节点坐标,用于找路径
  • int realF[N][N]; //记录节点的实际f值
  • int addr[N][N]= { {0,0,0,0,0,0},//环境二维矩阵
  • {0,1,1,0,1,1},
  • {0,0,1,0,0,0},
  • {0,0,1,1,1,0},
  • {0,1,1,0,0,0},
  • {1,1,0,0,0,0} };
  • int att[8][2]= { {-1,-1}, {-1, 0}, {-1, 1}, {0, -1},//八个方向
  • {0, 1}, {1, -1}, {1, 0}, {1, 1} };
  • priority_queue<Node>que;
  • void PrintPath(int a, int b); //打印函数
  • void AStar(int x0, int y0, int x1, int y1); //A星算法部分
  • bool NodeIsLegal(int x, int y, int x0, int y0); //合理性检验
  • int Mahuattan(int x, int y, int x1, int y1); //启发性估值,曼哈顿函数
  • int main() {
  • //初始化填充
  • fill(visit[0],visit[0]+N*N,false);
  • fill(path[0][0], path[0][0] + N * N * 2, -1);
  • fill(realF[0], realF[0] + N * N, 0);
  • int x0, y0, x1, y1;
  • cout << "请输入起点:" << endl;
  • cin >> x0 >> y0;
  • cout << "请输入重点:" << endl;
  • cin >> x1 >> y1;
  • if (!NodeIsLegal(x0, y0, x0, y0)) {
  • cout << "输入有误!" << endl;
  • return 0;
  • }
  • AStar(x0, y0, x1, y1);
  • PrintPath(x1, y1);
  • return 0;
  • }
  • void AStar(int x0, int y0, int x1, int y1) {
  • //初始化起点
  • Node node(x0, y0);
  • = 0;
  • = Mahuattan(x0, y0, x1, y1);
  • = + ;
  • realF[x0][y0] = ;
  • (node); //加入队列
  • while (!()) {
  • //大循环,队列的Top节点即为代价最小点。
  • Node node_top = que.top();
  • visit[node_top.x][node_top.y] = true; //设置访问
  • if (node_top.x == x1 && node_top.y == y1) { //终止条件之一,已经到达
  • break;
  • }
  • ();//从待处理队列中删掉
  • //循环处理八个方向相邻的节点
  • for (int i = 0; i < 8; i++) {
  • Node node_next(node_top.x + att[i][0], node_top.y + att[i][1]);
  • // 该节点坐标合法 且 未加入close
  • if (NodeIsLegal(node_next.x, node_next.y, node_top.x, node_top.y)) {
  • // 计算从起点并经过node_top节点到达该节点所花费的代价
  • node_next.g = node_top.g + int(10 * (sqrt(pow(att[i][0], 2) + pow(att[i][i], 2))));
  • // 计算该节点到终点的曼哈顿距离
  • node_next.h = Mahuattan(node_next.x, node_next.y, x1, y1);
  • node_next.f = node_next.g + node_next.h;
  • // node_next.F < valF[node_next.x][node_next.y] 说明找到了更优的路径,则进行更新
  • // valF[node_next.x][node_next.y] == 0 说明该节点还未加入open表中,则加入
  • if (node_next.f < realF[node_next.x][node_next.y] || !visit[node_next.x][node_next.y]) {
  • realF[node_next.x][node_next.y] = node_next.f;
  • //设置父节点坐标信息
  • path[node_next.x][node_next.y][0] = node_top.x;
  • path[node_next.x][node_next.y][1] = node_top.y;
  • (node_next);//加入队列
  • }
  • }
  • }
  • }
  • }
  • void PrintPath(int x1, int y1) {
  • if (path[x1][y1][0] == -1 || path[x1][y1][1] == -1) {
  • cout << "没有可行路径!" << endl;
  • return;
  • }
  • int x = x1, y = y1;
  • int a, b;
  • while (x != -1 && y != -1) {
  • addr[x][y] = 2;// 将可行路径上的节点赋值为2
  • a = path[x][y][0];
  • b = path[x][y][1];
  • x = a;
  • y = b;
  • }
  • // □表示未经过的节点, █表示障碍物, ☆表示可行节点
  • string s[3] = { "□", "█", "☆" };
  • for (int i = 0; i < N; i++)
  • {
  • for (int j = 0; j < N; j++)
  • cout << s[addr[i][j]];
  • cout << endl;
  • }
  • }
  • bool NodeIsLegal(int x0, int y0, int x1, int y1) {
  • //边界判断
  • if (x0<0 || y0<0 || x0>N - 1 || y0>N - 1) return false;
  • //障碍物判断
  • if (addr[x0][y0] == 1) return false;
  • // 两节点成对角型且它们的公共相邻节点存在障碍物 ,就是移动不能穿模
  • if (x0 != x1 && y0 != y1 && (addr[x0][y1]==1||addr[x1][y0]==1))return false;
  • return true;
  • }
  • int Mahuattan(int x, int y, int x1, int y1) {
  • return (abs(x - x1) + abs(y - y1))*10;
  • }