A 2D Pathfinder written in C++ using the stb_image library for image rendering. The pathfinder utlizes the A* algorithm to find the optimal path between any 2 nodes on the grid.
The pathfinder needs to be given a map, starting and target point. Based on this data and pathfinder configurations, it will output a map along with the solution.
If we change the target node, a new optimal path will be calculated and shown in the output image.
Specifications of the pathfinder:-
// main.cpp int gridState[NUMBER_ROWS * NUMBER_COLUMNS] = {0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// grid.h struct GridNode { Position pos; // Position of node NODE_STATE state; // State of Grid Node std::vector<GridNode *> neighbours; // List of Neighbour Nodes int neighbourCount; // Neighbour Count GridNode *parent; // The node which comes before this node int gCost; // Distance from start Node int hCost; // Distance from target Node int index; // Index in the heap ... // Checks if Node is Traversable or not bool is_traversable() { return (state != BLOCKED); } // Returns the sum of gCost and hCost for the node int get_fcost() { return gCost + hCost; } // Compare Node with Item i.e. (Item - Node) int compare_item(GridNode *item) { int deltaF = (item->get_fcost() - get_fcost()); return ((deltaF == 0) ? (item->hCost - hCost) : deltaF); } };
// path.h Path find_path(Grid *grid) { ... // Setup open and closed list while (openList.count > 0) { // Find Current Node GridNode *currentNode = openList.remove_first(); closedList.add_to_heap(currentNode); if (currentNode == targetNode) { break; } // Check Neighbours for (int i = 0; i < currentNode->neighbourCount; i++) { GridNode *neighbour = currentNode->neighbours[i]; if (neighbour->is_traversable() && !closedList.has_node(neighbour)) { int moveCost = currentNode->gCost + get_distance_bw_nodes(currentNode, neighbour); if (!openList.has_node(neighbour) || moveCost < neighbour->gCost) { neighbour->gCost = moveCost; neighbour->hCost = get_distance_bw_nodes(targetNode, neighbour); neighbour->parent = currentNode; if (!openList.has_node(neighbour)) { neighbour->state = (neighbour != targetNode) ? NEIGHBOUR : neighbour->state; openList.add_to_heap(neighbour); } else { openList.update_item(neighbour); } } } } if (currentNode != startNode) { currentNode->state = CHECKED; } } std::cout << "Path Found!!!" << std::endl; // Setup Path Path p; ... // Retrace path and store all nodes return p; }