#include #include #include #include #include #include #include "WindowCode.h" #define TILE_COST 1 class AStarNode; typedef std::shared_ptr AStarNodePtr; class AStarNode { public: int x, y; int g, score; AStarNodePtr parent; AStarNode(int x, int y, int cost, AStarNodePtr p, int score = 0) : x(x), y(y), g(cost), score(score), parent(p) {} static AStarNodePtr makePtr(int x, int y, int cost, AStarNodePtr p, int score = 0) { return AStarNodePtr(new AStarNode(x, y, cost, p, score)); } int heuristic(const int destx, int desty) const { int xd = destx - x; int yd = desty - y; return abs(xd) + abs(yd); } void updateScore(int endx, int endy) { auto h = this->heuristic(endx, endy) * TILE_COST; this->score = g + h; } AStarNodePtr getCopy() { return AStarNode::makePtr(x, y, g, parent, score); } std::vector getChildren(int width, int height) { std::vector ret; auto copy = getCopy(); if (x > 0) ret.push_back(AStarNode::makePtr(x - 1, y, g + TILE_COST, copy)); if (y > 0) ret.push_back(AStarNode::makePtr(x, y - 1, g + TILE_COST, copy)); if (x < width - 1) ret.push_back(AStarNode::makePtr(x + 1, y, g + TILE_COST, copy)); if (y < height - 1) ret.push_back(AStarNode::makePtr(x, y + 1, g + TILE_COST, copy)); return ret; } }; bool operator<(const AStarNodePtr &a, const AStarNodePtr &b) { return a->score > b->score; } bool operator==(const AStarNodePtr &a, const AStarNodePtr &b) { return a->x == b->x && a->y == b->y; } template void makeList(AStarNodePtr end, std::vector nodes, int path[WIDTH][HEIGHT]) { for (auto n = nodes.begin(); n != nodes.end(); n++) path[(*n)->x][(*n)->y] = 2; AStarNodePtr node = end; while (node.get() != nullptr) { path[node->x][node->y] = 1; node = node->parent; } } template bool doAStarSearch( int map[WIDTH][HEIGHT], int startx, int starty, int endx, int endy, int path[WIDTH][HEIGHT]) { std::priority_queue frontier; std::vector allNodes; auto node = AStarNode::makePtr(startx, starty, 0, nullptr); node->updateScore(endx, endy); allNodes.push_back(node); while (true) { if (node->x == endx && node->y == endy) { makeList(node, allNodes, path); return true; } auto children = node->getChildren(WIDTH, HEIGHT); for (auto c = children.begin(); c != children.end(); c++) { if (map[(*c)->x][(*c)->y] == BLOCKING) continue; auto found = std::find(allNodes.rbegin(), allNodes.rend(), *c); if (found != allNodes.rend()) { if (*found > *c) { (*found)->g = (*c)->g; (*found)->parent = (*c)->parent; (*found)->updateScore(endx, endy); } } else { (*c)->updateScore(endx, endy); frontier.push(*c); allNodes.push_back(*c); } } if (frontier.size() == 0) return false; node = frontier.top(); frontier.pop(); } } int main (int argc, char *argv[]) { searchFunction = doAStarSearch; showWindow(); return 0; }