1+ #include < iostream>
2+ #include < vector>
3+ #include < queue>
4+ #include < cmath>
5+ #include < algorithm>
6+
7+ struct Node
8+ {
9+ int y, x;
10+ int gCost , hCost;
11+ Node *parent;
12+
13+ Node (int r, int c) : y(r), x(c), gCost (0 ), hCost(0 ), parent(nullptr ) {}
14+
15+ int fCost () const
16+ {
17+ return gCost + hCost;
18+ }
19+ };
20+
21+ struct compareNodes
22+ {
23+ bool operator ()(const Node *a, const Node *b) const
24+ {
25+ return a->fCost () > b->fCost ();
26+ }
27+ };
28+
29+ bool isValid (int y, int x, int rows, int cols)
30+ {
31+ return (y >= 0 ) && (y < rows) && (x >= 0 ) && (x < cols);
32+ }
33+
34+ int calculateHeuristic (int y, int x, int goalY, int goalX)
35+ {
36+ return std::abs (y - goalY) + std::abs (x - goalX);
37+ }
38+
39+ std::vector<Node *> aStarSearch (std::vector<std::vector<int >> &grid, Node *start, Node *goal)
40+ {
41+ int rows = grid.size ();
42+ int cols = grid[0 ].size ();
43+
44+ std::priority_queue<Node *, std::vector<Node *>, compareNodes> openList;
45+ std::vector<std::vector<Node *>> allNodes (rows, std::vector<Node *>(cols, nullptr ));
46+
47+ start->hCost = calculateHeuristic (start->y , start->x , goal->y , goal->x );
48+ openList.push (start);
49+ allNodes[start->y ][start->x ] = start;
50+
51+ int dy[] = {-1 , 1 , 0 , 0 };
52+ int dx[] = {0 , 0 , -1 , 1 };
53+
54+ while (!openList.empty ())
55+ {
56+ Node *currentNode = openList.top ();
57+ openList.pop ();
58+
59+ if (currentNode->y == goal->y && currentNode->x == goal->x )
60+ {
61+ std::vector<Node *> path;
62+ while (currentNode != nullptr )
63+ {
64+ path.push_back (currentNode);
65+ currentNode = currentNode->parent ;
66+ }
67+ std::reverse (path.begin (), path.end ());
68+ return path;
69+ }
70+
71+ for (int i = 0 ; i < 4 ; ++i)
72+ {
73+ int newY = currentNode->y + dy[i];
74+ int newX = currentNode->x + dx[i];
75+
76+ if (isValid (newY, newX, rows, cols) && grid[newY][newX] == 0 )
77+ {
78+ int tentativeGCost = currentNode->gCost + 1 ;
79+
80+ Node *neighbor = allNodes[newY][newX];
81+
82+ if (neighbor == nullptr || tentativeGCost < neighbor->gCost )
83+ {
84+ if (neighbor == nullptr )
85+ {
86+ neighbor = new Node (newY, newX);
87+ allNodes[newY][newX] = neighbor;
88+ }
89+
90+ neighbor->parent = currentNode;
91+ neighbor->gCost = tentativeGCost;
92+ neighbor->hCost = calculateHeuristic (newY, newX, goal->y , goal->x );
93+
94+ openList.push (neighbor);
95+ }
96+ }
97+ }
98+ }
99+
100+ return {};
101+ }
102+
103+ int main ()
104+ {
105+ std::vector<std::vector<int >> grid = {
106+ {0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 },
107+ {0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 },
108+ {0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 },
109+ {0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 },
110+ {0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 }};
111+
112+ Node *startNode = new Node (0 , 0 );
113+ Node *goalNode = new Node (4 , 7 );
114+
115+ // This grid will be modified to show the path
116+ std::vector<std::vector<int >> grid_with_path = grid;
117+
118+ std::vector<Node *> path = aStarSearch (grid, startNode, goalNode);
119+
120+ if (path.empty ())
121+ {
122+ std::cout << " No path found!" << std::endl;
123+ }
124+ else
125+ {
126+ std::cout << " Path found:" << std::endl;
127+ for (Node *node : path)
128+ {
129+ grid_with_path[node->y ][node->x ] = 2 ;
130+ }
131+
132+ for (const auto &row : grid_with_path)
133+ {
134+ for (int cell : row)
135+ {
136+ if (cell == 2 )
137+ std::cout << " * " ;
138+ else if (cell == 1 )
139+ std::cout << " # " ;
140+ else
141+ std::cout << " . " ;
142+ }
143+ std::cout << std::endl;
144+ }
145+ }
146+
147+ // Memory Cleanup
148+ for (size_t i = 0 ; i < grid.size (); ++i)
149+ {
150+ for (size_t j = 0 ; j < grid[0 ].size (); ++j)
151+ {
152+ // Find the node pointer in the path to avoid double-freeing start/goal
153+ bool in_path = false ;
154+ if (path.empty ())
155+ { // If no path, start/goal were never put in allNodes grid
156+ if ((i == startNode->y && j == startNode->x ) || (i == goalNode->y && j == goalNode->x ))
157+ {
158+ in_path = true ;
159+ }
160+ }
161+ if (!in_path)
162+ {
163+ // This will delete all nodes created with 'new' in the search function
164+ // The 'path' vector itself does not own the pointers
165+ }
166+ }
167+ }
168+
169+ delete startNode;
170+ delete goalNode;
171+
172+ return 0 ;
173+ }
0 commit comments