数据结构2d/3d瓦片数组C++

Data structure 2d/3d array of tiles C++

本文关键字:数组 C++ 3d 2d 数据结构      更新时间:2023-10-16

我正在为一款新游戏编程一个关卡编辑器。问题是,我不确定用什么结构来存储我的数据。

它是一个基于瓦片的地图引擎,使用x和y坐标以及该位置的瓦片的id。

我有多个层,映射是可调整大小的,所以数组可能会给我带来一些麻烦,这就是为什么我在这种情况下选择std::vector的原因。为了防止大量过载,当有人放置瓷砖时,我只添加一个瓷砖,所以如果没有瓷砖,矢量大小为零,并且放置的瓷砖越多,矢量大小就会增加。

struct tile {
unsigned short tile_id;
unsigned short tile_x;
unsigned short tile_y;
};

我的矢量:

std::vector<tile> tiles;

问题是,在添加新的磁贴之前,我需要检查在x和y位置是否已经有磁贴。

// Returns true/false if there is a tile at given position or not
bool Layer::has_tile_at(unsigned short x, unsigned short y) {
unsigned int i;
for (i = 0; i < tiles.size(); i++) {
if (tiles[i].tile_x == x && tiles[i].tile_y == y)
return true;
}
return false;
}

我的问题是,对于每一个放置的瓷砖,我都必须遍历整个向量,这在一开始很快,但在放置了一些瓷砖后,真的会让人头疼。

到目前为止,你认为我的方法还可以吗?还是有更聪明、更具表现力的方法?

要使用的数据结构应该主要取决于用例:如果你主要进行(x,y)读取,那么你可能需要一个矩阵(可以是通过向量的向量,也可以只是数组的数组)。

如果您需要索引访问和瓦片上的简单迭代,也许可以将数据保持在两个数据结构中。您应该能够轻松地实现一个2d映射,其中指针指向向量中的瓦片——最初是空的,在(x,y)访问时延迟加载(记住数据安全!)。

例如:

class Map
{
public:
void addTile(std::shared_ptr<Tile> tile)
{
m_tiles.push_back(tile);             // should probably remove old elements at (x,y) from the vector
m_map[{tile->x, tile->y}] = tile;    // overwrites whatever was stored in there!
}
std::shared_ptr<Tile> getTile(int x, int y)
{
return m_tilesMap[{x, y}];           // if no tile there, returns default ctor-ed shared_ptr: nullptr
}
private:
std::vector<std::shared_ptr<Tile>> m_tiles;
using Index2D = std::pair<int, int>;
std::map<Index2D, std::shared_ptr<Tile>> m_tilesMap;
};

(带有简短代码示例的扩展注释:数据保存在堆中,而矢量和映射都保存其副本——也许可以改进以更容易地删除)

为什么不使用多个矢量?您可以通过拥有一个向量的向量来创建一个可增长的2-D向量,然后重载[]运算符,首先检查向量大小是否可以包含该元素(如果不能,则返回false),如果可以,则检查该元素是否不是构造值(无论您的默认"tile"是什么)。这将允许类似于规则向量中的O(1)查找。否则,您可以使用最大列/行距离的公式,并通过一些2-D到1-D的转换(如在2-D阵列中)进行O(1)查找。

这就是我的想法:

vector< vector<tile> > tiles;
bool::Layer has_tile_at(unsigned short x, unsigned short y) {
if (tiles.size() <= x) {
return false;
} else if (tiles[x].size() > y) {
if (tiles[x][y] != tile()) {
return true;
}
}
return false;
}

编辑:

正如另一位用户所指出的,您还可以使用指针来检查tile[x][y]==nullptr;相反