如何创建一个一维数组来容纳几个二维数组

How can i create a one-dimensional array to hold several two-dimensional arrays?

本文关键字:几个 二维数组 一维数组 何创建 创建 一个      更新时间:2023-10-16

我一直在开发一款游戏。这是一款基于文本的RPG冒险游戏。我希望让玩家使用简单的文本命令在世界上导航。我设置它是为了将世界划分为"区域"或阵列。每个区域都是自定义数据类型Location,由一个二维数组组成。我将使用两个变量来跟踪玩家的位置,这实际上是"区域"网格上点位置的两个索引值。当玩家输入方向命令,如"北"、"南"、"东"或"西"时,它会增加或减少这些值来"移动"玩家。当他们到达过渡区时,它将把他们转移到另一个"区域"。我在想我可以有一个数组来容纳所有的区域。过渡区将仅仅提高或降低主阵列的索引以"过渡"到下一个区。我当然会让过渡空间有一个值来存储玩家在下一个区域网格上的位置。我只是想知道如何制作这个"主数组"来容纳区域数组。只要问问我有没有什么没有;我解释得不够好。提前谢谢。

struct Location
{
    int type, destX, destY;
    // 1 = battlefield
    //  areas where random encounters will at some future date occur
    // 2 = town
    //  areas where hopefully the foolhardy adventurer will be able to speak
    // to merchants and towns folk
    // 3 = dungeon
    //  areas with long travel times and the promise of an end boss
    //  but more importantly really awesome loot
    // 4 = transition points
    //
    string name, desc;
};

这就是我的设想。

EgForest

[][][]
[][][]
[][][]
^
过渡区将使用存储值destX和destY将玩家移动到以下"区域"中的目的地

SRavine

这个地方就是目的地
V
[][][][][]]
[][][][][]]
[][][][][]]
[][][][][]

三维数组就是答案。

int world[4][5][6];

4是区域的数量,5和6是2D阵列。如果您需要可变大小的区域,请使用指针并分配所需的数量。

关于您问题的标题,这是您在C++中创建二维数组的一维数组:

std::vector<std::vector<std::vector<Entity>>> v;

这是一个多维数组,其中每个子数组的大小可以相互独立。

注意,C++也有固定大小的数组(也是一维的):

std::array<std::array<std::array<int,16>,16,16>> 
         array_16_of_array_16_of_array_16_of_int;

通常,比起直接数组,更喜欢标准容器。这为您打开了一个算法(例如algorithm标头)和辅助方法(.size())的世界。

不幸的是,C++没有内置的多维容器,但有些库提供了它们,或者您可以自己制作。一个基本的实现可能看起来像这样:

template <typename T>
class surface {
public:
    typedef size_t size_type;
    surface(size_type w, size_type h) : width_(w), height_(h), data_(w*h) {}
    size_type width()  const { return width_;  }
    size_type height() const { return height_; }
    size_type size()   const { return width_*height_; }
    // These are for when you need to loop over all elements
    // without interest in coordinates.
    T  operator[] (size_type i) const { return data_[i]; }
    T& operator[] (size_type i)       { return data_[i]; }
    T  operator() (size_type x, size_type y) const { return data_[y*width_+x]; }
    T& operator() (size_type x, size_type y)       { return data_[y*width_+x]; }
    T at(size_type i) const {
        if (i>=size()) throw std::out_of_range(....);
        return (*this)[i];
    }
    T& at(size_type i) {
        if (i>=size()) throw std::out_of_range(....);
        return (*this)[i];
    }
    T at(size_type x, size_type y) const {
        if (x>=width_ || y>=height_) throw std::out_of_range(....);
        return (*this)(x,y);
    }
    T& at(size_type x, size_type y) {
        if (x>=width_ || y>=height_) throw std::out_of_range(....);
        return (*this)(x,y);
    }
private:
    size_type width_, height_;
    std::vector<T> data_;
};
...
surface<Foo> x(256,256);
x(16,12) = Foo();
x[16+12*256] = Foo();

根据数组的大小和访问顺序,您可以使用其他索引器(例如Morton/Z-Order索引)。

template <typename T, typename Indexer=LinearIndexer>
...
    T  operator() (size_type x, size_type y) const { return data_[Indexer()(x,y)]; }
...
surface<int, Morton> foo(102400, 102400);

您甚至可能将容器模板化,以允许出现像容器这样的特殊情况,这些容器可以及时从磁盘加载/保存到磁盘。

您可以将所有矩阵缩减为一个大的一维数组。对于每个区域,您都知道它在阵列中的偏移量,以及它的宽度和高度。一个区域内的导航很简单,+/-1表示东/西,+/-region_width表示南/北。当遍历区域的边界时,需要特殊的代码来防止它,或者跳到另一个区域。

我建议你把世界从一堆矩阵变成一张图。图中的一个位置将至少有4个(但可能更多)出口槽。插槽将有一个方向标识符(除了n、s、e、w之外,还可以有"向上"、"向下"、"门"、"楼梯"和任何您喜欢的东西),可以是隐式的(已知插槽),也可以是显式的(与插槽一起存储),还可以是该插槽指向的位置的标识符。这个标识符可以是"一个大的1D数组"中的位置索引。这种方法的缺点是记账更多。好处是你在创造自己的世界时有更多的自由。这张图在特殊情况下闪闪发光。你可以有4个以上的出口、单向通道,或者像下水道这样令人难以置信的区域,你以为你可以向北走,但它会把你带向西方,或者诸如此类。CircleMUD和大多数其他MUD都使用图形解决方案。