⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 astar.cpp

📁 我自己编写的A*搜索算法
💻 CPP
字号:
#include <cmath>
#include <stack>
#include "AStar.hpp"

using namespace std;

/*
Author : WB
*/

//初始化地图
AStar::AStar(char *m, const int &rows, const int &cols)
    : map_(m),rows_(rows), cols_(cols){
        init();
}

//释放所有分配的资源
AStar::~AStar(){
	for(ClosedTable::iterator itr=ct_.begin(); itr!=ct_.end(); ++itr){
		delete (*itr);
	}
	while(!ot_.empty()){
		delete ot_.top();
		ot_.pop();
	}
}

//一个简易的ID生成算法
int AStar::generateId(const int &x, const int &y) const{
    return x * 18 + y;
}

//确定地图中的初始点和终点坐标
void AStar::findSourceAndDestination(){
    for(int i=0; i<rows_; ++i){
        for(int j=0; j<cols_; ++j){
            if(map_[i * cols_ + j] == 's'){
                source_.x = i;
                source_.y = j;
            }
            if(map_[i * cols_ + j] == 'd'){
                destination_.x = i;
                destination_.y = j;
            }
        }
    }
}

//判断地图上某点是否可以到达
bool AStar::canAccess(const int &x, const int &y) const{
    return map_[x * cols_ + y] != 'o';
}

void AStar::initStartPoint(){
    PNode start = new ANode;
    start->x = source_.x;
    start->y = source_.y;
    start->childNum = 0;
    start->id = generateId(start->x, start->y);
    start->parent = 0;
    start->g = 0;
    start->h = abs(start->x - destination_.x) + abs(start->y - destination_.y);
    start->f = start->g + start->h;
    ot_.push(start);
}

void AStar::init(){
    findSourceAndDestination();
    initStartPoint();
}

//判断某个Node是否在ClosedTable中
AStar::PNode AStar::isInClosedTable(const int &id){
    for(ClosedTable::iterator itr=ct_.begin(); itr!= ct_.end(); ++itr){
        if((*itr)->id == id)
            return *itr;
    }
    return 0;
}

//判断某个Node是否在OpenTable中
AStar::PNode AStar::isInOpenTable(const int &id){
    return ot_.contain(id);
}

//采用类似深度优先搜索的算法更新Node的所有子节点及其后继节点
void AStar::updateNodes(PNode p){
    stack<PNode> pStack;
    PNode temp = 0;
    for(int i=0; i<p->childNum; ++i){
        temp = p->children[i];
        if((p->g + 1) < temp->g){
			reCombine(temp, p);
            pStack.push(temp);
        }
    }
    while(!pStack.empty()){
        temp = pStack.top();
        pStack.pop();
        PNode tempChild = 0;
        for(int i=0; i<temp->childNum; ++i){
            tempChild = temp->children[i];
            if((temp->g + 1) < tempChild->g){
				reCombine(tempChild, temp);
                pStack.push(tempChild);
            }
        }
    }
}

//重新关联父子Node的关系
void AStar::reCombine(PNode child, PNode parent){
	child->g = parent->g + 1;
	child->f =child->g + child->h;
	child->parent = parent;
}

//算法的核心,寻找最短路径
//如果找到最短路径,就将路径存储在path中,并且返回true
//否则返回false表示没有路径可达
bool AStar::findPath(vector<Point> &path){
    PNode node = ot_.top();
	//A*搜索算法
    while(!ot_.empty() && !(node->x == destination_.x && node->y == destination_.y)){
		ot_.pop();
		//向8个方向搜索节点
        for(int m=-1; m<2; ++m)
            for(int n=-1; n<2; ++n){
                if(m|n){
                    int tempx = node->x + m;
                    int tempy = node->y + n;
                    int tempid = generateId(tempx, tempy);
                    if(canAccess(tempx, tempy)){
                        PNode temp;
                        if((temp = isInOpenTable(tempid)) != 0){
                            node->children[node->childNum++] = temp;
                            if((node->g + 1) < temp->g){
								reCombine(temp, node);
                            }
                        }else if((temp = isInClosedTable(tempid)) != 0){
                            node->children[node->childNum++] = temp;
                            if((node->g + 1) < temp->g){
								reCombine(temp, node);
                                updateNodes(temp);
                            }
                        }else{
                            temp = new ANode;
                            temp->x = tempx;
                            temp->y = tempy;
                            temp->childNum = 0;
                            temp->id = tempid;
                            temp->parent = node;
                            temp->g = node->g + 1;
                            temp->h = abs(temp->x - destination_.x) + abs(temp->y - destination_.y);
                            temp->f = temp->g + temp->h;
							node->children[node->childNum++] = temp;
                            ot_.push(temp);
                        }
                    }
                }
            }
//        ot_.pop();
        ct_.push_back(node);
		node = ot_.top();
    }
    if(ot_.empty())
        return false;
	//将找到的路径存储在path中
    PNode bestNode = node->parent;
    while(bestNode->parent != 0){
        Point t;
        t.x = bestNode->x;
        t.y = bestNode->y;
        path.insert(path.begin(),t);
        bestNode = bestNode->parent;
    }
    return true;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -