C++ 控制台保存和加载保存的“游戏”

Posted

技术标签:

【中文标题】C++ 控制台保存和加载保存的“游戏”【英文标题】:C++ console Save and load saved "games" 【发布时间】: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 流来完成)。但是,第二个参数。甚至会应用于您当前的数据模型。 【参考方案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 个保存/文件。

以上是关于C++ 控制台保存和加载保存的“游戏”的主要内容,如果未能解决你的问题,请参考以下文章

如何将变量保存到新的文本文件中,以便下次程序运行时加载这些变量?

分段控制的保存和加载状态

unity play 游戏服务云保存内部错误

无法加载视图状态。正在加载视图状态的控制树必须与用于保存视图状态的控制树匹配

将文件保存到 C++ 中用户输入定义的位置和名称

C++ sln 保存