C++ 周围物体算法
我正在制作一个游戏,其中只有一个对象可能存在于位置C++ 周围物体算法,c++,C++,我正在制作一个游戏,其中只有一个对象可能存在于位置(x,y),其中x和y是int。例如,一个对象可能存在于(0,0)处,也可能不存在,但不可能同时存在多个对象 我正在尝试决定使用哪个STL容器来解决手头的问题,以及解决这个问题的最佳方法 基本上,我从一个对象及其(x,y)位置开始。目标是根据对象周围的对象确定最高的、可能最大的矩形。必须使用当前对象上方和下方的所有对象创建矩形。也就是说,它必须是基于起始对象位置可能达到的最高点 例如,假设以下内容表示我的对象网格,我从位置(3,4)处的绿色对象开
(x,y)
,其中x
和y
是int
。例如,一个对象可能存在于(0,0)
处,也可能不存在,但不可能同时存在多个对象
我正在尝试决定使用哪个STL容器来解决手头的问题,以及解决这个问题的最佳方法
基本上,我从一个对象及其(x,y)
位置开始。目标是根据对象周围的对象确定最高的、可能最大的矩形。必须使用当前对象上方和下方的所有对象创建矩形。也就是说,它必须是基于起始对象位置可能达到的最高点
例如,假设以下内容表示我的对象网格,我从位置(3,4)
处的绿色对象开始:
然后,我要查找的矩形将由下面的粉色正方形表示:
因此,假设我从(3,4)
处的对象开始,如示例所示,我需要检查(2,4)
、(4,4)
、(3,3)
和(3,5)
处是否也存在对象。如果一个对象存在于这些位置中的任何一个,我需要重复这个过程,让该对象找到可能的最大矩形
这些物品非常罕见,游戏世界非常庞大。对于整个游戏世界来说,仅仅new
一个2D数组似乎并不实用,因为大多数元素都是空的。但是,我需要索引到任何位置,以检查对象在任何时候是否存在
相反,我考虑使用std::map
如下:
std::map< std::pair<int, int>, ObjectData> m_objects;
如果我决定这样做,我可能会对map::find()
进行大量调用,但与使用整个世界的二维数组相比,map占用的内存要少得多
有没有人对一个简单的算法有什么建议,我可以用它来找到我要找的东西?我是否应该继续使用
std::map
,或者是否有更好的容器来处理此类问题?如果可能的话,改进方法是使用hashmap。这将允许您至少以O(1)的预期时间复杂度进行潜在的广泛搜索
这里有一个线程()详细介绍了如何将两个整数散列在一起
如果编译器支持C++11,则可以使用std::无序_映射。如果不是,Boost基本上是一样的:你可能想考虑一个空间数据结构。如您所说,如果数据是“稀疏的”,那么进行四叉树邻域搜索可能会节省大量处理能力。我个人会使用R-tree,但这很可能是因为我有一个R-tree库,我已经编写好了,可以很容易地导入 例如,假设您有一个包含10000个元素的
1000x1000
网格。假设目前是均匀随机分布,我们(基于密度)预计不会超过,比如。一个由三到五个物体组成的链在任一维度上接触(在这个密度下,一个由三个垂直方向的物体组成的链发生的概率为0.01%)。假设所考虑的对象位于(x,y)
。从(x-5,y-5)
开始并转到(x+5,y+5)
的窗口搜索将提供最多121个元素的列表,以执行线性搜索。如果您的矩形拾取算法注意到可能会形成一个更高的矩形(即,如果正在考虑的矩形接触此11x11
边界框的边缘),只需在原始矩形的一个方向上重复窗口搜索另一个5x5
区域。必要时重复
当然,这只有在数据非常稀疏的情况下才有效。可能需要调整R树,使叶子成为一个关联的数据结构(即Int->Int->Object
),但在这一点上,可能最好只找到一个适用于更密集数据的解决方案
我可能想得太多了;可能有一个更简单的解决方案
关于R-树的一些参考:
- ,对于原始算法
- ,它对该主题有一些不错的概述
- ,用于与R-树相关的数据集和算法
如果我有时间清理一下,我会用我自己的R-tree实现(公共域)的链接编辑它。每个网格位置需要存储多少数据?如果你只是在寻找一个标志,表明你至少有两个“低技术”的解决方案 a) 如果你的网格是稀疏的,那么每个正方形都有一个邻居列表怎么样?所以每个方块都知道哪些相邻的方块被占据。当一个广场被占用或腾空时,您需要做一些工作来维护列表。但是邻居列表意味着你根本不需要网格地图
b) 如果栅格地图位置实际上只是点,则每个栅格位置使用1位。结果映射将比为每个网格点使用字节的映射小8x8=64倍。比特运算速度很快。10000x1000映射需要100000000位或12.5MB(约)这听起来像是一个家庭作业问题(因为它有一个奇怪的条件“必须使用当前对象上下的所有对象创建矩形”,这使得解决方案变得微不足道)。不过我还是要试一试。为了方便起见,我将使用“像素”一词而不是“对象” 如果您的应用程序真的值得重量级解决方案,您可以尝试将像素存储在四叉树中(四叉树的叶子包含普通的二维数组,每个数组只有几千个像素)。或者,您可以将相邻像素组合成“形状”(例如,您的示例仅包含一个“形状”,即使它包含24个单独的像素)。给定初始非结构化
if(m_objects.find(std::pair<3, 4>) != m_objects.end())
{
//An object exists at (3, 4).
//Add it to the list of surrounding objects.
}
typedef std::pair<int, int> Pt;
typedef std::pair<Pt, Pt> Rectangle;
std::unordered_map<Pt, ObjectData *> myObjects;
/* This helper function checks a whole vertical stripe of pixels. */
static bool all_pixels_exist(int x, int min_y, int max_y)
{
assert(min_y <= max_y);
for (int y = min_y; y <= max_y; ++y) {
if (myObjects.find(Pt(x, y)) == myObjects.end())
return false;
}
return true;
}
Rectangle find_tallest_rectangle(int x, int y)
{
assert(myObjects.find(Pt(x,y)) != myObjects.end());
int top = y;
int bottom = y;
while (myObjects.find(Pt(x, top-1) != myObjects.end()) --top;
while (myObjects.find(Pt(x, bottom+1) != myObjects.end()) ++bottom;
// We've now identified the first vertical stripe of pixels.
// The next step is to "paint-roller" that stripe to the left as far as possible...
int left = x;
while (all_pixels_exist(left-1, top, bottom)) --left;
// ...and to the right.
int right = x;
while (all_pixels_exist(right+1, top, bottom)) ++right;
return Rectangle(Pt(top, left), Pt(bottom, right));
}