【问题标题】:C++ console Save and load saved "games"C++ 控制台保存和加载保存的“游戏”
【发布时间】:2017-04-20 06:12:14
【问题描述】:

我有一个随机生成的数字网格,大小为gameSizexgameSize(用户输入),包含在向量向量中。用户可以输入两个坐标 (x, y),以便将网格内的数字更改为预定义的值。

例如,用户输入 X:0 Y:0 和:

{9, 7, 9}

{9, 6, 8}

{5, 1, 4}

变成:

{0, 7, 9} <-- Changes position 0,0 to 0 (the predefined value)

{9, 6, 8} 

{5, 1, 4}

我正试图弄清楚如何制作它,以便用户可以保存当前的板状态并在以后访问它。我知道我需要以某种方式将游戏 (myGame) 保存到一个文件中,这样我才能访问它并将其再次加载到控制台应用程序中,本质上是保存并重新启动保存的游戏,但我不知道从哪里开始。

【问题讨论】:

  • 我将从输入和输出文件流开始。如果你有一本教科书,应该有一个关于文件输入和输出的部分。然后将您的一系列数字打印到文件中,然后在加载期间将它们读回
  • 如果你想保存/加载一个向量向量,你必须将内部向量大小“烘焙”成文件格式。否则,加载器无法适当地恢复内部向量。在您的情况下,内部向量似乎始终具有相同的大小。这简化了事情:第一,我会使用固定大小的其他东西(例如结构)。具有固定大小的元素向量的第二个文件 I/O 要容易得多(并且可以像已经建议的那样直接使用 I/O 流来完成)。但是,第二个参数。甚至会应用于您当前的数据模型。

标签: c++ console save restart


【解决方案1】:

您可以使用标准库中的 fstream 并将特殊方法添加到您的游戏类,这里是工作示例:

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Game
{
public:
    Game(int gameSize) : size(gameSize), field(size, vector<int>(size))
    {
        //Randomize(); //generate random numbers
//just filling example for test
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                field[i][j] = i * size + j;
            }
        }
    }

    Game(string filename) {
        Load(filename);
    }

    void Load(string filename) {
        fstream in;
        in.open(filename, fstream::in);
        in >> size;
        field.resize(size, vector<int>(size));
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                in >> field[i][j];
            }
        }
        in.close();
    }

    void Save(string filename) {
        fstream out;
        out.open(filename, fstream::out);
        out << size << endl;
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                out << field[i][j] << " ";
            }
            out << endl; //for user friendly look of file
        }
        out.close();
    }

private:
    int size;
    vector<vector<int>> field;
};

int main() {
    Game game(3);
    game.Save("game.txt");
    game.Load("game.txt");
    game.Save("game2.txt");

    return 0;
}

不要忘记将游戏大小存储在文件中以方便阅读。如果您想加载已存储的游戏,最好将 size 属性添加到您的类并使用另一个构造函数。此外,如果您添加一些检查文件格式是否正确会更好。 如果它们还没有,您可以将所有使轮换的逻辑作为方法添加到 Game 类中。祝你好运!

【讨论】:

    【解决方案2】:

    逐行保存,每行一行:

    void Game::save(std::istream& s)
    {
        for (const auto& row: myGame)
        {
            for (auto cell: row)
            {
                s << cell << ' ';
            }
            s << '\n';
        }
    }
    

    然后逐行回读并创建行:

    void Game::load(std::istream& s)
    {
        myGame.clear();
        std::string line;
        while (std::getline(s, line))
        {
            std::istringstream cells(line);
            std::vector<int> row;
            int cell = 0;
            while (cells >> cell)
            {
                row.push_back(cell);
            }
            myGame.push_back(row);
        }
    }
    

    将行分隔成行意味着您不需要跟踪长度。
    使用istream&amp;ostream&amp; 参数意味着您不仅可以使用文件,还可以使用任何流,例如stringstream,或cincout
    后者可以在调试时派上用场。

    【讨论】:

      【解决方案3】:

      首先,您应该阅读 CSV 格式。要求用户为您的游戏设置名称,然后将数组保存到如下文件中:
      - 每行 1 次保存。
      - 行以保存名称开头
      - 接下来的两个值代表大小 X 和大小 Y。
      - 直到行尾的下一个值表示数组数据。
      加载保存游戏的过程如下:
      - 用户会看到可用保存的列表
      - 打算加载哪个存档的用户输入
      - 应用程序像这样加载数据:在文件中搜索包含要加载的名称的行,读取大小 x 和大小 y 以初始化该大小的数组,将内容加载到数组中。

      【讨论】:

      • 为什么要使用 CSV 来完成如此简单的任务?他还可以使用 json 来描述游戏并从服务器加载它,但我认为它现在超出了项目的范围。 :)
      • 因为他说的是控制台应用程序......而 CSV 代表逗号分隔值。如果是我的应用程序,我会使用 XML,有一些库可以解释 XML,让你的生活更轻松,而使用 CSV 格式意味着你可以从这个应用程序中学到一些东西。同样在一个文件中,您可以存储多个保存...使用您的方法,它可以存储 1 个保存/文件。
      猜你喜欢
      • 1970-01-01
      • 2011-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-07
      • 2011-05-17
      • 2010-09-30
      • 1970-01-01
      相关资源
      最近更新 更多