明星不可预测的错误

时间:2012-06-27 15:36:31

标签: c++ algorithm path-finding a-star

我对A *算法的微弱尝试产生了不可预测的错误。 我的FindAdjacent()函数显然是一团糟,当我单步执行它时它实际上不起作用。这是我第一次尝试路径查找算法,所以这对我来说都是新的。

当应用程序实际设法找到目标节点和路径(或者我认为)时,它永远不会设置路径(通过按Enter键从main内部调用)。我不知道为什么它不能通过查看SetPath()函数来做到这一点。

非常感谢任何帮助,这是我的代码:

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;
};

寻找路径

/**
 *  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;
}

1 个答案:

答案 0 :(得分:0)

一些建议:

ADJACENCY TEST

FindAdjacent中的测试目前只能找到对角线邻居

 if (i != 0 && j != 0)

如果您还想找到左/右/上/下邻居,您可以使用

 if (i != 0 || j != 0)

ADJACENCY LOOP

我认为你的代码在的行中看起来很可疑

for (vector<Node*>::iterator iter = mClosedList.begin(); iter != mClosedList.end(); iter++)

我真的不明白这里的意图。我原本期望mClosedList开始为空,所以这个循环永远不会执行,所以什么都不会被添加到mOpenList。

我对算法的这一部分的期望是让你测试每个邻居是否应该添加到开放列表中。

OPENLIST CHECK

如果您查看A* algorithm on wikipedia,您会发现自己也错过了

部分
if neighbor not in openset or tentative_g_score < g_score[neighbor]  

你还应该在添加它之前检查FindAdjacent你的新节点是否已经在OpenSet中,如果是,那么只有在得分更好时才添加它。