Skip to content

Instantly share code, notes, and snippets.

@makoConstruct
Last active October 31, 2016 05:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save makoConstruct/6de61cbda99eeebd7a35c322be23f877 to your computer and use it in GitHub Desktop.
Save makoConstruct/6de61cbda99eeebd7a35c322be23f877 to your computer and use it in GitHub Desktop.
defines a graph and implements A Star pathfinding algo. Depends on a few utility functions and type aliases. It's obvious enough what they mean, so you'd have no trouble swapping them out for whatever you use.
//graph stuff
template<typename T>
struct GraphNode{
vector<GraphNode*> neighbors;
T v;
void unlink(){
for(GraphNode* neigh : neighbors){
removeEl(neigh->neighbors, this);
}
neighbors.clear();
}
~GraphNode(){
unlink();
}
};
template<typename T>
void link(GraphNode<T>* a, GraphNode<T>* b){
a->neighbors.push_back(b);
b->neighbors.push_back(a);
}
template<typename T, typedef F>
void breadthFirstTraverse(GraphNode<T>* start, F&& func){
typedef GraphNode<T> Nodep;
vector<Nodep> lista;
vector<Nodep> listb;
vector<Nodep>* currentList = &lista;
vector<Nodep>* nextList = &listb;
unrodered_set<Nodep> seen;
currentList->push_back(start);
seen.insert(start);
while(true){
for(Nodep nex : *currentList){
func(nex);
for(Nodep neighb : nex->neighbors){
if(!seen.count(neighb)){
nextList->push_back(neighb);
seen.insert(neighb);
}
}
}
if(nextList->size() == 0) return;
swap(currentList, nextList);
nextList->clear();
}
}
template<typename T>
struct FrontierEntry{
GraphNode<T>* node;
FrontierEntry* parent;
float f;
uint count;
};
template<typename T>
struct FrontierEntryComparator{
bool operator()(GraphNode<T> const* a, GraphNode<T> const* b){
return a->f < b->f;
}
};
template<typename T, typename Heuristic>
vector<GraphNode<T>*> aStar(GraphNode<T>* startNode, GraphNode<T>* target, Heuristic&& heuristic){ //return sequence will be from target to startNode, probably the reverse order from what you want but whatev
typedef GraphNode<T>* Nodep;
typedef FrontierEntry<T> Front;
vector<Front> oldFrontierEntries;
unrodered_set<Nodep> seen;
priority_queue<Front*, vector<Front*>, FrontierEntryComparator<T>> frontier;
auto newFrontierNode = [&](float distance, Nodep node, Front* parent){
Front* ret = &oldFrontierEntries.emplace_back(Front{ node, parent, distance });
seen.insert(startNode);
frontier.insert(ret);
return ret;
};
Front* cur = newFrontierNode(0, cur, nullptr);
while(true){
for(Nodep newn : cur->node->neighbors){
if(!seen.count(newn)){
if(newn == target){
vector<Nodep> ret;
ret.push_back(newn);
Front* curPushing = cur;
do{
ret.push_back(curPushing->node);
curPushing = cur->parent;
}while(curPushing);
return ret;
}else{
newFrontierNode(
cur->distance + heuristic(newn->v, cur->node->v) + heuristic(newn->v, target),
newn,
cur);
}
}
}
if(q.empty()) return vector();
cur = q.pop();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment