2016-12-09 4 views
0

パスの精度を比較する方法として次のA星の視覚化を使用すると、私の実装と今回のものとの間に大きな変化が見られました。最短経路を見つけても正しく計算しない星アルゴリズム

Path I'm comparing to

私のテストパス:私はと比較してる

https://qiao.github.io/PathFinding.js/visual/

パス

アルゴリズムがあまりにもチェックしているようにそれはそう時があります

img

いくつかのノード(すなわち、テスト#6)。これが期待されるのか、それとも正しくないのでしょうか?アルゴリズムで

重要な変数:オープンリストをソートするための

TileMap* m_tileMap; 
vector<Tile*> m_openList; 
vector<Tile*> m_path; 

// Direct mapping of 2D tile map. 
// Stores the list type for the same-indexed tile 
vector<vector<int>> m_listMap; 

コンパレータ:

struct CompareNodes 
{ 
    // sorts lowest F cost to end of vector 
    bool operator() (Tile* lhs, Tile* rhs) 
    { 
     return lhs->getFCost() > rhs->getFCost(); 
    } 
}; 

ハイレベルの実装:

vector<Tile*> PathGenerator::generatePath(Tile* startNode, Tile* endNode) 
{ 
    setUpListMap(); 

    startNode->setGCost(0); 
    startNode->setHCost(calculateHCost(startNode, endNode)); // Manhattan (no diagonal). { abs(y2 - y1) + abs(x2 - x1) } 
    startNode->calculateFCost(); // calculates G+H internally 

    m_openList.push_back(startNode); 
    Vector2D startNodePos = startNode->getMapPos(); 
    m_listMap[startNodePos.x][startNodePos.y] = LIST_TYPES::OPEN; 

    Tile* currentNode; 


    while (m_openList.empty() == false) 
    { 
     currNode = m_openList[m_openList.size() - 1]; 
     m_openList.pop_back(); 

     Vector2D currNodePos = currNode->getMapPos(); 
     m_listMap[currNodePos.x][currNodePos.y] = LIST_TYPES::CLOSED; 

     if (currNode != endNode) 
     { 
      vector<Tile*> neighbours = findNeighbours(currNode); 
      removeUnnecessaryNodes(&neighbours); // remove walls and closed nodes 
      computeCosts(&neighbours, currNode, endNode); 
      addUniqueNodesToOpenList(&neighbours); // ignores duplicates and then sorts open list 
     } 
     else 
     { 
      m_path = getPath(currNode); 
      resetLists(); // erases all vectors 
     } 
    } 

    return m_path; 
} 

void PathGenerator::computeCosts(vector<Tile*>* nodes, Tile* current, Tile* end) 
{ 
    int newGCost = current->getGCost() + 1; 

    for (int i = 0; i < nodes->size(); i++) 
    { 
     Tile* node = nodes->at(i); 
     unsigned int nodeGCost = node->getGCost(); // G cost defaults to max int limit 

     if (newG < nodeGCost) 
     { 
      // set up node costs like above 
      node->setParentNode(current); 
     } 
    } 
} 

私が最も重要なコードを追加しました。上位レベルの関数が問題の原因を見つけるのに役立たない場合は、私に知らせてください。私はそれらの実装も追加します。

ヘルプありがとうございます。

+0

私は視覚的に理解することができる唯一の違いは、対角... –

+0

@Boiethiosに沿って移動していないということです:追加質問 – sookie

+0

@PatrickTrentin:私も対角線を使用しないように – sookie

答えて

0

並べ替えの部分は正しいようですが、ベクトルなので確認するのは非常に簡単です。

代わりに、あなたは本当に最低のF-コストのノードを取得していることを確認するためのテストケースとして、forループ使用してみてください:それはそれを修正する場合

Tile* currnode = m_openlist[0]; 
for (int i = 0; i < m_openList.size() i++) 
{ 
    if (m_openList[i]->getFCost() < currnode->getFCost()) 
     currnode = m_openList[i]; 
} 

を参照してください。もしそうなら、あなたの問題には問題がありますが、私はその問題がどうなるか分かりません。

また、あなたのcomputeCosts機能では、あなたが実行します。

for (int i = 0; i < nodes->size(); i++) 
    { 
     Tile* node = nodes->at(i); 
     //.. other code 
    } 

あなたはなぜその機能を利用すること、およびイテレータを使用するか、範囲ベースのループではない、のstd ::ベクトルを使用しているので:

// Iterators 
for (auto it = nodes->begin(); it != nodes->end(); it++) 
{ 
    Tile* node = *it; 
    //.. other code 
} 

// Range based loop 
for (auto node : *nodes) 
{ 
    //.. other code 
} 
+0

ここでのアイデアは、現在のパスがそのノードに対してより良いFコストを生成する場合、以前に計算されたノードを更新することです。最初は 'numeric_limits :: max()'のGコストですべてのタイルを初期化するので、 'newG'はそのノードが最初に遭遇したときに常にそのノードのG Costより小さくなります。そのノードとのさらなる遭遇は、そのif文を正しく利用するでしょう。 – sookie

+0

私の悪いことが分かります!とにかく、何かが間違っている可能性がある実際の唯一の場所は、開いているリストからのノードの選択です。他の場所のエラーは間違ったパスを計算するか、まったく見つけられません。開いているリストからノードを削除するときに、ノードがソートされていることを確認できますか?あなたはすべてを正しくレンダリングしていますか? –

+0

ここにテスト#4の最後のセクションがありますhttp://i.imgsafe.org/ab65330c78.png ...黄色の部分は私が話していたギャップです - 彼らは未踏のノードです。 A-starの実装では、その数の未踏のノードは見たことがなく、問題があるのか​​、それとも問題ないのだろうかと思います。また、イテレータをインデックスベースのループよりも使用すると、パフォーマンス上の利点がありますか? – sookie

関連する問題