使用序列化 C++ 保存游戏状态 [英] Saving a game state using serialization C++

查看:81
本文介绍了使用序列化 C++ 保存游戏状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 Game 的类,它包含以下内容:

I have a class called Game which contains the following:

vector<shared_ptr<A>> attr; // attributes
D diff; // differences
vector<shared_ptr<C>> change; // change

我的问题是,如何将这些(保存)写入文件并稍后读取/加载?我想过在其中使用 struct 并简单地保存 struct 但我不知道从哪里开始.

My question is, how can I write these (save) to a file and read/load it up later? I thought about using a struct with these in it, and simply saving the struct but I have no idea where to start.

到目前为止,这是我的尝试,只是尝试保存change.我已经阅读了很多关于这个问题的文章,我的问题(无论如何是其中之一)似乎是我正在存储关闭程序后将无效的指针(由于我在退出之前也释放了它们这一事实而复杂化)).

This is my attempt so far, with just trying to save change. I've read up a lot on the issue and my issue (well one of them, anyway) here seems to be that I am storing pointers which after closing the program would be invalid (compounded by the fact that I also free them before exiting).

/* Saves state to file */
void Game::saveGame(string toFile) {
    ofstream ofs(toFile, ios::binary);
    ofs.write((char *)&this->change, sizeof(C));

    /* Free memory code here */
    ....

    exit(0);
}; 

/* Loads game state from file */
void Game::loadGame(string fromFile) {
    ifstream ifs(fromFile, ios::binary);
    ifs.read((char *)&this->change, sizeof(C));

    this->change.toString(); // display load results
};

任何人都可以指导我朝着正确的方向序列化这些数据吗?我只想使用标准包,所以没有 boost.

Can anyone guide me in the right direction for serializing this data? I'd like to use only standard packages, so no boost.

谢谢.

推荐答案

编写自己的序列化是一个相当大的挑战.即使您不使用 boost serializatoin,我也建议您学习如何使用它并理解它的工作原理,而不是自己去发现它.

Writing your own serialization is quite a challenge. Even if you do not use boost serializatoin I would recommend you learn how to use it and comprehend how it works rather than discovering it yourself.

在序列化时,您最终会得到一个数据缓冲区,您对哪些内容的想法非常模糊.您必须保存所需的一切才能恢复它.你一块一块地读.示例(未编译、未测试且不时尚):

When serializing you finally end up with a buffer of data of which content you have very vague idea. You have to save everything you need to be able to restore it. You read it chunk by chunk. Example (not compiled, not tested and not stylish ):

void save(ostream& out, const string& s)
{
   out << s.size();
   out.write(s.c_str(), s.size());
}
void load(istream& in, string& s)
{
   unsigned len;
   in >> len;
   s.resize(len);
   in.read((char*)s, len); 
}

struct Game
{
   void save(ostream& out)
   {
      player.save(out);
   };
   void load(istream& in)
   {
      player.load(in);
   }
};
struct Player
{
   void save(ostream& out)
   {
       // save in the same order as loading, serializing everything you need to read it back
       save(out, name);
       save(out, experience);
   }
   void load(istream& in)
   {
       load(in, name);
       load(in, experience); // 
   }
};

我不知道你为什么要对自己这样做而不是使用 boost 但这些是你应该考虑的一些情况:- 类型 - 你必须想办法知道你实际上有什么变化类型".- 一个字符串(向量,随便什么) - 大小 + 数据(然后你从字符串读回的第一件事是长度,你调整它的大小并复制长度"字符数)- 一个指针 - 保存指针指向的数据,然后在反序列化时必须分配它,构造它(通常是默认构造)并读回数据并将成员重置为其各自的值.注意:您必须避免内存泄漏.- 多态指针 - 哎哟你必须知道指针实际指向什么类型,你必须构造派生类型,保存派生类型的值......所以你必须保存类型信息- 空指针...您必须区分空指针,以便您知道不需要进一步从流中读取数据.- 版本控制 - 您必须能够在添加/删除字段后读取数据

I do not know why you would do it to yourself instead of using boost but those are some of the cases you should consider: - type - you must figure out a way to know what "type of change" you actually have there. - a string (vector, whatever) - size + data (then the first thing you read back from the string is the length, you resize it and copy the "length" number of characters) - a pointer - save the data pointed by pointer, then upon deserialization you have to allocate it, construct it (usually default construct) and read back the data and reset the members to their respective values. Note: you have to avoid memory leakage. - polymorphic pointer - ouch you have to know what type the pointer actually points to, you have to construct the derived type, save the values of the derived type... so you have to save type information - null pointer... you have to distinguish null pointer so you know that you do not need to further read data from the stream. - versioning - you have to be able to read a data after you added/removed a field

内容太多,你无法得到完整的答案.

There is too much of it for you to get a complete answer.

这篇关于使用序列化 C++ 保存游戏状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆