从文件加载数组

Loading array from file

我正在尝试加载一个整数文件,将它们添加到一个二维数组,遍历该数组,并根据当前索引处的整数(图块 ID)将图块添加到我的关卡。我的问题似乎是数组 loaded/iterated 顺序错误。这是我从中加载的文件:

test.txt

02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01

这是关卡构造函数:

Level::Level(std::string levelpath, int _width, int _height)
{
    std::ifstream levelfile(levelpath);
    width = _width;
    height = _height;
    int ids[15][9];

    while (levelfile.is_open()) {
        std::copy_n(std::istream_iterator<int>(levelfile), width * height, &ids[0][0]);

        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                tiles.push_back(getTile(ids[x][y], sf::Vector2f(x * Tile::SIZE, y * Tile::SIZE)));
                std::cout << ids[x][y] << " ";
            }
            std::cout << std::endl;
        }

        levelfile.close();
    }
}

这就是我创建关卡的方式:

level = std::unique_ptr<Level>(new Level("data/maps/test.txt", 15, 9));

这是控制台中的输出:

2 2 1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 1 1 1 1 1 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1 1 1 1 1 1

如您所见,内容与test.txt中的相同,但顺序错误。

原因是您调换了数组的维度。而不是

int ids[15][9];

...也就是15行9个元素,你要

int ids[9][15];

...这是 9 行,每行 15 个元素。声明中范围的顺序与访问中索引的顺序相同。

编辑:...你也交换了。而不是

ids[x][y]

你需要

ids[y][x]

这确实更好地解释了你得到的输出,想想看。 C++ 中的二维数组按行优先存储,这意味着最里面的数组(连续存储的数组)是具有最右边索引的数组。换句话说,ids[y][x]直接存储在ids[y][x + 1]之前,而ids[y][x]ids[y + 1][x]之间有一些space。

如果您像读取 std::copy_n 一样读入行优先数组并将其解释为列优先数组,您会得到转置(由于尺寸改变而有点扭曲,但可以看出是这样. 如果你交换高度和宽度,你会看到真正的转置)。

如果您看一下,您会发现您在第一个原始文件中打印了前 15 个值(需要在第一行中)(以及第二个中不适合的值)。您可以理解它开始填充行之前的行,并且您的文件首先包含该行。所以加载你的地图 "on the side"。将高度设置为宽度 (15) 和相反的值(宽度是 9 而不是 15)。现在您将正确加载地图。

不只是打印每一行和第二行之前的 "endl"(每行打印为一行)。你会看到这个 ok.

希望已经足够清楚了。

int ids[9][15];

while (levelfile.is_open()) {
    std::copy_n(std::istream_iterator<int>(levelfile), width * height, &ids[0][0]);

    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            tiles.push_back(getTile(ids[y][x], sf::Vector2f(x * Tile::SIZE, y * Tile::SIZE)));
            std::cout << ids[y][x] << " ";
        }
        std::cout << std::endl;
    }