簡體   English   中英

瓦片的數據結構2d / 3d數組C ++

[英]Data structure 2d/3d array of tiles C++

我正在為新游戲編寫關卡編輯器。 問題是,我不確定用於存儲數據的結構。

它是基於圖塊的地圖引擎,在該位置使用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;
};

(帶有簡短代碼示例的擴展注釋:數據保留在堆上,而向量和映射都保留其副本-也許可以進行改進以方便刪除)

為什么不使用多個向量? 您實際上可以通過具有向量的向量來創建可增長的二維向量,然后重載[]運算符以首先檢查向量的大小是否可以包含該元素(如果不是則返回false),如果可以,則檢查該元素不是一個構造值(無論您的默認“ tile”是什么)。 這將允許像常規向量一樣進行近O(1)查找。 否則,您可以使用公式計算最大的col / row距離,並通過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; 代替!

暫無
暫無

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

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