My feeble attempt at an A* Algorithm is generating unpredictable errors. My FindAdjacent() function is clearly a mess, and it actually doesn't work when I step through it. This is my first time trying a path finding algorithm, so this is all new to me.
When the application actually manages to find the goal nodes and path (or so I think), it can never set the path (called from within main by pressing enter). I do not know why it is unable to do this from looking at the SetPath() function.
Any help would be hugely appreciated, here's my code:
NODE CLASS
enum
{
NODE_TYPE_NONE = 0,
NODE_TYPE_NORMAL,
NODE_TYPE_SOLID,
NODE_TYPE_PATH,
NODE_TYPE_GOAL
};
class Node
{
public:
Node () : mTypeID(0), mNodeCost(0), mX(0), mY(0), mParent(0){};
public:
int mTypeID;
int mNodeCost;
int mX;
int mY;
Node* mParent;
};
PATH FINDING
/**
* finds the path between star and goal
*/
void AStarImpl::FindPath()
{
cout << "Finding Path." << endl;
GetGoals();
while (!mGoalFound)
GetF();
}
/**
* modifies linked list to find adjacent, walkable nodes
*/
void AStarImpl::FindAdjacent(Node* pNode)
{
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
if (i != 0 && j != 0)
if (Map::GetInstance()->mMap[pNode->mX+i][pNode->mY+j].mTypeID != NODE_TYPE_SOLID)
{
for (vector<Node*>::iterator iter = mClosedList.begin(); iter != mClosedList.end(); iter++)
{
if ((*iter)->mX != Map::GetInstance()->mMap[pNode->mX + i][pNode->mY + j].mX && (*iter)->mY != Map::GetInstance()->mMap[pNode->mX + i][pNode->mY + j].mY)
{
Map::GetInstance()->mMap[pNode->mX+i][pNode->mY+j].mParent = pNode;
mOpenList.push_back(&Map::GetInstance()->mMap[pNode->mX+i][pNode->mY+j]);
}
}
}
}
mClosedList.push_back(pNode);
}
/**
* colour the found path
*/
void AStarImpl::SetPath()
{
vector<Node*>::iterator tParent;
mGoalNode->mTypeID = NODE_TYPE_PATH;
Node *tNode = mGoalNode;
while (tNode->mParent)
{
tNode->mTypeID = NODE_TYPE_PATH;
tNode = tNode->mParent;
}
}
/**
* returns a random node
*/
Node* AStarImpl::GetRandomNode()
{
int tX = IO::GetInstance()->GetRand(0, MAP_WIDTH - 1);
int tY = IO::GetInstance()->GetRand(0, MAP_HEIGHT - 1);
Node* tNode = &Map::GetInstance()->mMap[tX][tY];
return tNode;
}
/**
* gets the starting and goal nodes, then checks te starting nodes adjacent nodes
*/
void AStarImpl::GetGoals()
{
// get the two nodes
mStartNode = GetRandomNode();
mGoalNode = GetRandomNode();
mStartNode->mTypeID = NODE_TYPE_GOAL;
mGoalNode->mTypeID = NODE_TYPE_GOAL;
// insert start node into the open list
mOpenList.push_back(mStartNode);
// find the starting nodes adjacent ndoes
FindAdjacent(*mOpenList.begin());
// remove starting node from open list
mOpenList.erase(mOpenList.begin());
}
/**
* finds the best f
*/
void AStarImpl::GetF()
{
int tF = 0;
int tBestF = 1000;
vector<Node*>::const_iterator tIter;
vector<Node*>::const_iterator tBestNode;
for (tIter = mOpenList.begin(); tIter != mOpenList.end(); ++tIter)
{
tF = GetH(*tIter);
tF += (*tIter)->mNodeCost;
if (tF < tBestF)
{
tBestF = tF;
tBestNode = tIter;
}
}
if ((*tBestNode) != mGoalNode)
{
Node tNode = **tBestNode;
mOpenList.erase(tBestNode);
FindAdjacent(&tNode);
}
else
{
mClosedList.push_back(mGoalNode);
mGoalFound = true;
}
}
/**
* returns the heuristic from the given node to goal
*/
int AStarImpl::GetH(Node *pNode)
{
int H = (int) fabs((float)pNode->mX - mGoalNode->mX);
H += (int) fabs((float)pNode->mY - mGoalNode->mY);
H *= 10;
return H;
}