2017-04-20 8 views
0

私は、ランダムに生成されたベクトルのベクトル内に含まれるサイズgameSize x gameSize(ユーザー入力)のグリッドを持っています。ユーザーは2つの座標(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

ベクトルのベクトルを保存/ロードするには、内側のベクトルサイズをファイル形式に「ベーク」する必要があります。さもなければ、ローダーは内部ベクトルを適切に回復することができません。あなたの場合、内側のベクトルは常に同じサイズを持つようです。これは事を単純化します:第一に私は修正サイズ(例えば構造体)を持つ何かを使用します。 2番目のファイルI/Oは、固定サイズの要素のベクトルの方がはるかに簡単です(すでに提案したようにI/Oストリームをそのまま使用することもできます)。しかし、第2引数。あなたの現在のデータモデルにも適用されます。 – 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クラスが既に存在していない場合、それをメソッドとしてGameクラスに追加することができます。がんばろう!

0

まず、CSV形式についてお読みください。ユーザーにゲームの名前を設定して、配列を次のようなファイルに保存するよう依頼してください:
- 1行に1回の保存
- 行は保存名で始まります
- 次の2つの値はサイズXとサイズYを表します。
- 次の行末までの値は配列データを表します。ファイル内検索含む行を: - ユーザーが利用できるの一覧が表示され
を節約できます - -
をロードすることを意図セーブユーザー入力アプリケーションは、このようにデータをロード
:セーブゲームをロード
は次のように行い、読み込む予定の名前、サイズxおよびサイズyを読み込んでそのサイズの配列を初期化し、内容を配列にロードします。行によって

+0

このような単純なタスクにCSVを使用する理由彼はゲームを記述してサーバーからロードするためにjsonを使うこともできますが、今はプロジェクトの範囲を超えていると思います。 :) –

+0

彼はコンソールアプリケーションのために述べたので...そしてCSVはComma Separated Valuesの略です。それが私のアプリケーションであれば私はXMLを使っていたでしょう、XMLを解釈してあなたの人生を楽にするライブラリがありますが、CSV形式ではこのアプリケーションから何かを学ぶことができます。また、1つのファイルに複数のセーブを保存することもできます。 –

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&のパラメータを使用すると、ファイルの使用に限定されず、stringstreamcincoutなどの任意のストリームを使用できます。
後者はデバッグに便利です。

関連する問題