2017-04-20 126 views
0

我有一个随机生成的大小为gameSize x gameSize(用户输入)的数字网格,它包含在矢量向量中。用户可以输入两个坐标(x,y),以便将网格内的数字更改为预定义的值。C++控制台保存并加载保存的“游戏”

因此,例如,用户输入,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)保存到一个文件中,这样我就可以访问它并将其重新加载到控制台应用程序中,从本质上保存并重新启动保存的游戏,但我不知道从哪里开始。

+0

我会从输入和输出文件流开始。如果你有一本教科书,应该有一个文件输入和输出部分。然后就是将一系列数字打印到一个文件中,然后在加载过程中将它们读回来 – jdow

+0

如果要保存/加载矢量矢量,则必须将内部矢量大小“烘烤”为文件格式。否则,加载程序无法适当地恢复内部向量。在你的情况下,内部矢量似乎总是相同的大小。这简化了一些事情:第一,我会使用其他修正大小的东西(例如一个结构体)。对于具有修订大小的元素向量的第二个文件I/O更容易(并且可以像已经提出的那样直接向前输入/输出流)完成。然而,第二个arg。甚至会适用于您当前的数据模型。 – Scheff

回答

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类中作为方法。祝你好运!

0

首先,你应该阅读关于CSV格式。要求用户为你的游戏设置一个名称,然后将数组保存到这样的文件中:
- 1每行保存一次。
- 行以保存名称
开头 - 接下来的两个值分别代表大小X和大小Y.
- 直到行结束的下一个值代表数组数据。
加载保存游戏进行这样的:
- 用户提供的可用列表保存
- 用户输入其保存打算加载
- 应用程序加载这样的数据:搜索的文件,其中包含行它打算加载的名称,读取大小x和大小y以初始化该大小的数组,将内容加载到数组中。

+0

为什么要将CSV用于这么简单的任务?他也可以使用json来描述一个游戏并从服务器加载它,但我认为这超出了现在的项目范围。 :) –

+0

因为他陈述了控制台应用程序...和CSV代表逗号分隔值。如果这是我的应用程序,我会使用XML,有些库可以解释XML并使您的生活更加轻松,同时使用CSV格式,这意味着您可以从此应用程序中学到一些东西。同样在一个单独的文件中,您可以存储多个保存...使用您的方法,它可以存储1个保存/文件。 –

1

保存一行一行,每行一个行:

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&ostream&参数意味着你不仅限于使用的文件,但可以使用任何流,像stringstream,或cincout
后者可以派上用场进行调试。