c++ - 在寻路中对 std::vector 进行排序

Posted

技术标签:

【中文标题】c++ - 在寻路中对 std::vector 进行排序【英文标题】:c++ - sorting std::vector in pathfinding 【发布时间】:2014-12-09 05:58:22 【问题描述】:

我正在尝试在我正在开发的游戏中实现一个粗略的寻路示例。我正处于需要对std::vector<Tile*> 进行排序的地步,并且我尝试使用以下方法进行排序,但出现了一堆我无法弄清楚的错误。我还尝试将 sortF 结构中的引用更改为指针,但出现另一个错误 - Comparison between pointer and integer ('Tile *' and 'int')

有问题的错误是:No matching function for call to object of type 'Stage::sortF'

想知道我到底做错了什么。

(如果有人在寻路中有任何 cmets 也很好)

在 Stage.h 中公开

struct sortF

    bool operator()(const Tile& a, const Tile& b) const
    
        return a.f > b.f;
    
;

在 Stage.cpp 中

bool Stage::tilePath(Tile* start, Tile* end)

    std::vector<Tile*> path;
    std::vector<Tile*> open;
    std::vector<Tile*> closed;
    start->previousTile = start;
    start->g = 0;
    start->h = 0;
    start->f = 0;

    int i, j;
    float g, h, f;

    int sx, sy, ex, ey;

    int cost;

    Tile* current = start;
    Tile* neighbor = NULL;
    Tile* previous = NULL;
    std::cout << neighbor << std::endl;

    while(current != end) 
        sx = fmaxf(0, current->x - 1);
        sy = fmaxf(0, current->y - 1);
        ex = fminf(17 - 1, current->x + 1);
        ey = fminf(6 - 1, current->y + 1);

        for(i = sx; i <= ex; i++) 
            for(j = sy; j <= ey; j++) 
                neighbor = tiles[((j - 1) * 17) + i - 1];
                if(neighbor == current || !neighbor->walkable) continue;
                previous = current;
                if(false /* raytrace */) 

                 else 
                    cost = (current->x != neighbor->x || current->y != neighbor->y) ? 1.4 : 1;
                    g = current->g + cost;
                    h = euclidian(neighbor, end);
                    f = g + h;
                

                if(std::find(open.begin(), open.end(), neighbor) != open.end() ||
                   std::find(closed.begin(), closed.end(), neighbor) != closed.end()) 
                    if(neighbor->f > f) 
                        neighbor->f = f;
                        neighbor->g = g;
                        neighbor->h = h;
                        neighbor->previousTile = current;
                    
                 else 
                    neighbor->f = f;
                    neighbor->g = g;
                    neighbor->h = h;
                    neighbor->previousTile = current;
                    open.push_back(current);
                
            
        

        closed.push_back(current);
        if(open.size() == 0) 
            return false;
        
        std::sort(open.begin(), open.end(), sortF());
        current = open[0];
        std::remove(open.begin(), open.end(), 0);
    
    return true;

【问题讨论】:

请发布您遇到的错误。顺便说一句,使用堆结构比每次迭代都排序要好得多。 好点,我可能会改用那个,但我仍然想弄清楚这个错误。 请删除所有与排序无关的代码,然后发布您从该版本代码中得到的错误。 如果你想对一个X的向量进行排序,你的比较器必须接受两个Xs。如果XT*,您的比较器必须接受两个T*s。这通常通过bool operator()(const T*, const T*) 之类的方式完成。 @Javi V:实际上,堆数据结构在现代 CPU 上通常非常慢。因此,作为一阶近似值,我们宁愿改变算法,这样数据就不必一直保持有序。 【参考方案1】:

注意:您没有包含错误消息,因此以下答案或多或少基于视图编译:

sortF(),不是sortF

错误:“)”标记之前的预期主表达式 std::sort(open.begin(), open.end(), sortF); ^

您需要sortF 的实例,而不是struct sortF 类型。要么使用sortF() 创建临时对象,要么使用函数而不是仿函数:

bool sortF(const Tile& a, const Tile& b)

    return a.f > b.f;

Tile*const Tile&amp;

您在std::vector&lt;Tile*&gt; 上使用std::sort,但您的比较函数使用const Tile&amp; 作为参数。使用std::vector&lt;Tile&gt; 或更正函数中的类型:

bool sortF(const Tile* a, const Tile* b)

    return a->f > b->f;

【讨论】:

【参考方案2】:

由于std::vector 的元素属于Tile* 类型,因此比较std::vector 的两项的函数必须取两个Tile*s。

struct sortF

    bool operator()(Tile* ap, Tile* bp) const
    
        return a->f > b->f;
    
;

【讨论】:

【参考方案3】:

您绝对必须更改对比较器函数中指针的引用。你没有告诉你究竟在哪里得到了关于指针和整数比较的错误,但我相信它发生在这一行:

std::remove(open.begin(), open.end(), 0);

std::remove() 采用容器的值类型,而不是索引。你想做的大概是

open.pop_front()

也就是说,这个操作以及排序需要相当长的时间,正如 Javi V 所说,这里最好使用堆结构。

【讨论】:

以上是关于c++ - 在寻路中对 std::vector 进行排序的主要内容,如果未能解决你的问题,请参考以下文章

在c ++中对向量的向量进行排序

构造过程中对向量中元素的引用

在 C++ 中对向量进行分组排序

A* 寻路学习

C++随机选择std::vector的非空元素<std::vector>>

C++:使用 OpenMP 插入 std::vector