0

I'm working on pathfinding for a 2D tile game. I've found this similar answer, but I'm not sure how to do create the comparison operator when heap compares i <> i+i, when i need manhattan(i) <> manhattan(i+1)? I'm insanely rusty with cpp so go easy on me.

typedef std::tuple<int, int> coord;

int manhattan(coord start, coord goal){
    return (std::abs(start.get<0> - goal.get<0>) + \ 
            std::abs(start.get<1> - goal.get<1>) )
}

bool operator()((const coord& left, const coord& right){
   return manhattan(left, ???) < manhattan(right, ???);    
}

vector pathfinding(coord start, coord goal){
  //using A* format
  vector<coord> open;

  while(open){
      //how can I compare indexes to goal parameter?
      std::sort_heap(open.begin(), open.end()); 

      current = open.front();
  }

}
Community
  • 1
  • 1
Tony
  • 1,318
  • 1
  • 14
  • 36

1 Answers1

1

I'd suggest using a lambda function to create a local comparator for each call of pathfinding. Also, don't forget to pass it to std::sort_heap. Try this:

vector pathfinding(coord start, coord goal) {
  // using A* format
  vector<coord> open;
  auto comp = [&goal](const coord& lhs, const coord& rhs) {
    return manhattan(lhs, goal) > manhattan(rhs, goal); // greater-than, for a min-heap
  };

  while(open){
    std::sort_heap(open.begin(), open.end(), comp);

    ...
  }
}

comp is initialized to a lambda object (like a lambda in Python or an anonymous function in JavaScript). The [&goal] part means to "capture" the goal variable by reference for use in the lambda. It's like a custom class with a member variable that stores a reference to goal, and has an operator() that compares two coords using goal.

Also, I don't think that you should be using std::sort_heap... Use std::push_heap and std::pop_heap (see the example in the linked documentation). The idea is to call std::make_heap once at the beginning, and use push/pop_heap to maintain the heap when adding/removing. No need to sort it every iteration. Example:

// to push "direction" onto the heap:
open.push_back(direction);
std::push_heap(open.begin(), open.end(), comp);

// to pop "current" off of the heap:
std::pop_heap(open.begin(), open.end(), comp);
current = open.pop_back();
qxz
  • 3,814
  • 1
  • 14
  • 29
  • Thank you very much, that was a super helpful follow up of an explanation. And I was looking at that documentation, but I see no reason why I can't just used sort_heap and avoid the push/pops? – Tony Nov 19 '16 at 02:17
  • How are you currently pushing/popping values onto/off of the heap? – qxz Nov 19 '16 at 02:19
  • I was just using open.push_back( direction ) at the bottom and then sort_heap(), open.front(), open.erase(0) at the top of the loop? – Tony Nov 19 '16 at 02:57
  • I've edited with example usage. You don't need to sort every iteration; just use those two functions, and the heap will be maintained (largest value at `open.front()`) – qxz Nov 19 '16 at 03:22
  • Actually, you probably want a min-heap for A* instead of a max-heap... I've edited `comp` in my answer to reflect that – qxz Nov 19 '16 at 03:25