It could be you have just confused the compiler.
Alas, I have never played with A* and cannot intelligently comment on your implementation of the algorithm. But it does not look quite right to me — you are mixing types of things and their containers in a way that makes me nervous.
One of the main problems is all the bookkeeping you have mixed into the code that can be simplified by making a few helper functions. For example, a lot of your function could be reduced to something like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
NODE* aStar(int startX, int startY, int goalX, int goalY)
{
int xAxe = (GAME_RES_WIDTH / SCALE_FACTOR);
int yAxe = (GAME_RES_HEIGHT / SCALE_FACTOR);
// These are all nodes touched or examined in the search
NODE*** allNodes = alloc_node_array(xAxe, yAxe);
if (!allNodes) return NULL;
// These are nodes that have been examined
bool** closedSet = alloc_closed_set(xAxe, yAxe);
if (!closedSet) goto lerror;
// These are nodes that have yet to be examined
MINI_HEAP openSet;
initHeap(&openSet);
// Add the initial node
NODE* start = alloc_node(startX, startY, 0, manhattanDistance(startX, startY, goalX, goalY), NULL);
if (!start) goto lerror;
pushHeap(&openSet, start);
allNodes[startX][startY] = start;
// While there are nodes to be examined:
while (!isEmpty(&openSet))
{
...
}
lerror:
free_closed_set(closedSet, xAxe);
free_all_nodes(allNodes, xAxe, yAxe);
cleanupHeap(&openSet); // (did you forget to clean up the min heap?)
return NULL; // No path found
}
| |
The helper functions do all the work of allocating and freeing memory. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
bool** free_closed_set(bool** closedSet, int xAxe)
{
if (closedSet)
{
for (int x = 0; x < xAxe; x++)
free(closedSet[x]);
free(closedSet);
}
return NULL;
}
bool** alloc_closed_set(int xAxe, int yAxe)
{
bool** closedSet = calloc(xAxe, sizeof(bool*));
if (closedSet)
{
for (int x = 0; x < xAxe; x++)
{
closedSet[x] = calloc(yAxe, sizeof(bool));
if (!closedSet[x])
return free_closed_set(closedSet, xAxe);
}
}
return closedSet;
}
| |
This frees you from having to do it (over and over and
over) in your A* function, thus making it much easier for you to follow what you are doing.
I see that you have not as-yet added code to properly return a path. I would personally not return the
NODE
type directly to the caller, since it is essentially a linked list from the goal point to the start point. Instead I would use another type, such as:
1 2 3 4 5
|
struct aStarPath
{
int x, y;
struct aStarPath* next;
};
| |
This can easily be constructed by following the parent nodes back to the start to produce a linked list of (x,y) coordinates from start to goal. The upsides of this approach are:
• You also need to provide the caller with a function to delete the returned linked list.
• You do not need to either remove nodes from
allNodes
or duplicate nodes in order to return something you have not
free()
ed during proper cleanup. The existing cleanup methods can be used simply.
You could also just allocate and return an array of (x,y) pairs, where the last element is the goal point. The user can then just iterate through the returned array with an index and simply
free()
it when finished with it.
So, your function would become either one of:
struct aStarPath * aStar(int startX, int startY, int goalX, int goalY);
struct points * aStar(int startX, int startY, int goalX, int goalY);
Anyway, sorry I don’t have a sure answer for the actual question. Without a complete example code I can compile and mess with, I cannot answer it.
Hopefully all the other notes help you.