簡體   English   中英

如何為std :: map實現std :: map的比較邏輯,該邏輯包含兩個“ Pos”結構,每個結構均包含x和y坐標

[英]How to implement std::map::find comparison logic for a std::map containing two 'Pos' structs that each contain x and y coordinates

我正在重新創建《吃豆人》,目前正在實現幽靈的尋路。 我正在使用BFS。 我在實現“ Pos”類比較邏輯時遇到麻煩,因此我的std :: map :: find可以按預期工作。

'BFS'地圖

std::map<Pos, Pos> bfs;

Pos結構

struct Pos {
    int x_;
    int y_;

    bool operator==(const Pos &rhs) const { return (x_ == rhs.x_ && y_ == rhs.y_); };
    bool operator<(const Pos &rhs)  const { return (x_ < rhs.x_); };
};

函數的使用std :: map :: find的部分來檢查未訪問的XY位置。

if (bfs.find(neighbors.at(i)) == bfs.end()) {
    frontier.push(neighbors.at(i));
    bfs[neighbors.at(i)] = current;

    if (bfs[neighbors.at(i)] == end_tile) {
        quit = true;
    }
}

我使用此網站來學習如何使用BFS進行尋路: https : //www.redblobgames.com/pathfinding/a-star/implementation.html#cpp-early-exit

我已經嘗試了<和>的多個變體來比較x和或y,但是它似乎無法正常工作,導致生成空的地圖或地圖中的值很少-遠非所需。

考慮到您對正在使用的算法已作了充分的考慮,為了將Pos對象用作std::map鍵,您需要找到滿足您要求的正確的嚴格弱排序准則(operator <) 。

bool operator<(const Pos& rhs) const {
    if(x_ < rhs.x_) return true;
    if(x_ > rhs.x_) return false;

    //x == coord.x
    if(y_ < rhs.y_) return true;
    if(y_ > rhs.y_) return false;

    //*this == pos
    return false;
}

您還可以使用std::tie類的東西(在C ++ 11中),它首先比較x,然后比較y:

bool operator<(const Pos& rhs) const
{
    // compare x_ to rhs.x_,
    // then y_ to rhs.y_
    return std::tie(x_,y_) < std::tie(rhs.x_, rhs.y_);
}

用於映射鍵的比較必須遵守一些規則。 有關更多信息,請參見文檔: http : //www.cplusplus.com/reference/map/map/

本質上,在您的情況下,因為您的operator<僅比較x值而不是y值,具有相同x的任何位置都將被視為等效,因此,如果您擁有多個具有相同x但y與鍵不同的位置,則將僅存在一個在地圖上。

當您使用bfs[neighbors.at(i)] = current; 要更新該值,您將獲得特定x的最后一個current值,而不是特定{x,y}的最后一個值。

您的比較應該確實像

 return x_ < rhs.x_ || x_ == rhs.x_ && y_ < rhs.y_;

本質上,當搜索插入位置時,該算法將僅使用operator<而不是operator==

假設您的地圖位置為{3,5},並且您想插入{3,4}。

{3,5} <{3,4}為假

{3,4} <{3,5}為假(因為您僅檢查x)

由於兩者都是錯誤的,因此它們被認為是等效的,並且現有項目已更新(而不是根據需要添加新項目)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM