Difference between revisions of "2021-Save Game"
(Created page with "=Game Save File= Player One,0,5,5,2 Player Two,0,5,5,2 6 #,#,~,~, , , ,~, , , , , ,#,#,#,~,~ 1,Baron,0 2,Baron,1 1,LESS,3 1,LESS,15 2,LESS,2 1,Serf,17 2,LESS,13") |
(→Grid Tiles) |
||
(14 intermediate revisions by the same user not shown) | |||
Line 11: | Line 11: | ||
1,Serf,17 | 1,Serf,17 | ||
2,LESS,13 | 2,LESS,13 | ||
+ | |||
+ | The first 2 lines are the player 1 and player 2 data | ||
+ | |||
+ | The third line is the grid size | ||
+ | |||
+ | The fourth line is each tile (notice the space between the comma, space is for a field) | ||
+ | |||
+ | From this point, each line is a piece. This should be the player, followed by the type of piece and finally the hex number. | ||
+ | |||
+ | =Issue= | ||
+ | The program is able to load a save game file, however it is not possible to save a game. | ||
+ | |||
+ | =Solution= | ||
+ | We need to create a new method in the program class for save game. The basic structure of the method is: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | public static void SaveGame(Player p1, Player p2, HexGrid g) | ||
+ | { | ||
+ | Console.Write("Enter the name of the file to save: "); | ||
+ | string fileName = Console.ReadLine(); | ||
+ | try | ||
+ | { | ||
+ | Console.WriteLine("File saved"); | ||
+ | } | ||
+ | catch | ||
+ | { | ||
+ | Console.WriteLine("File not saved"); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | The SaveGame method above accepts parameters for Player1, Player2, and the grid. The code above will ask the user to enter a filename to use for the game save. I have included a try & catch because writing to files will often cause issues, so it is good error handling. | ||
+ | |||
+ | ==StreamWriter== | ||
+ | |||
+ | Now, inside the try block but before the 'Console.WriteLine()' add the following to create and open the file: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | using (StreamWriter myStream = new StreamWriter(fileName)) | ||
+ | { | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==Player Data== | ||
+ | Now inside the { } of the using statement add this: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | string playerData = p1.GetName() + "," + p1.GetVPs() + "," + p1.GetFuel() + "," + p1.GetLumber() + "," + p1.GetPiecesInSupply(); | ||
+ | myStream.WriteLine(playerData); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | This will create a string of the data from Player1, the stream will have a 'WriteLine' which is used to write to the file. | ||
+ | |||
+ | Repeat the code above for Player2 (obviously change p1 to p2). | ||
+ | |||
+ | ==GridSize== | ||
+ | The grid size is currently stored within the HexGrid object, however it is currently private and can't be accessed. Find the HexGrid class in the skeleton program: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | class HexGrid | ||
+ | { | ||
+ | protected List<Tile> tiles = new List<Tile>(); | ||
+ | protected List<Piece> pieces = new List<Piece>(); | ||
+ | int size; | ||
+ | bool player1Turn; | ||
+ | |||
+ | public HexGrid(int n) | ||
+ | { | ||
+ | size = n; | ||
+ | SetUpTiles(); | ||
+ | SetUpNeighbours(); | ||
+ | player1Turn = true; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | This is just a fraction of the HexGrid class, but you can see size is declared as an int. Because the default for variables is 'private' this isn't available to save the game. We could change this by adding public before the int size;. Alternatively we can create a property to access it: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | public int GetSize() | ||
+ | { | ||
+ | return size; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Now, back in our SaveGame method and below the code to write the data for Player1 and Player2. We can get the grid size and write it to the file using this code: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | int gridsize = g.GetSize(); | ||
+ | myStream.WriteLine(gridsize); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==Grid Tiles== | ||
+ | |||
+ | The tiles within HexGrid are protected, so they can't be accessed. We therefore need to create a new method in HexGrid to return the tiles, this will be just as a string: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | public string GetTiles() | ||
+ | { | ||
+ | string temp = ""; | ||
+ | foreach (Tile t in tiles) | ||
+ | { | ||
+ | temp = temp + t.GetTerrain() + ","; | ||
+ | } | ||
+ | temp = temp.Substring(0, temp.Length - 1); | ||
+ | return temp; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | The foreach loop will cycle through each tile, and add the terrain type to the temp string. | ||
+ | |||
+ | Adding "," will mean the final string will have a , at the end. The Substring will remove this final ,. | ||
+ | |||
+ | Now back in the SaveGame we can add the following after the code to write the tiles: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | string tiles = g.GetTiles(); | ||
+ | myStream.WriteLine(tiles); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | =Pieces= | ||
+ | Unfortunately, like tiles the pieces in HexGrid are protected and also the pieceType in the Piece class is also protected. Another complication is that the piece doesn't store the location of the piece. | ||
+ | |||
+ | ==Changes to Piece== | ||
+ | |||
+ | We need to add code into the Piece class to return the data we need. Create this method: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | public string GetPieceData() | ||
+ | { | ||
+ | string temp = ""; | ||
+ | |||
+ | if (this.belongsToPlayer1) | ||
+ | temp = "1"; | ||
+ | else | ||
+ | temp = "2"; | ||
+ | |||
+ | string piece = ""; | ||
+ | switch (this.pieceType) | ||
+ | { | ||
+ | case "S": | ||
+ | piece = "Serf"; | ||
+ | break; | ||
+ | case "B": | ||
+ | piece = "Baron"; | ||
+ | break; | ||
+ | case "L": | ||
+ | piece = "LESS"; | ||
+ | break; | ||
+ | case "P": | ||
+ | piece = "PBDS"; | ||
+ | break; | ||
+ | } | ||
+ | temp = temp + "," + piece + ","; | ||
+ | |||
+ | return temp; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | This will get everything required apart from the location, however this will need to come from elsewhere. | ||
+ | |||
+ | ==Changes to HexGrid== | ||
+ | |||
+ | Now we have the new method in Piece, we can use it to complete the data for a single piece: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | public string GetPieceData(Piece p) | ||
+ | { | ||
+ | string temp = ""; | ||
+ | int count = 0; | ||
+ | foreach(Tile t in tiles) | ||
+ | { | ||
+ | if (p == t.GetPieceInTile()) | ||
+ | temp = p.GetPieceData() + count; | ||
+ | count++; | ||
+ | } | ||
+ | return temp; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | The tile number is literally the position in the list, so a simple count is used. When the piece is found this will be added to the output of GetPieceData. | ||
+ | |||
+ | Now we need to get the data of every piece: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | public List<string> GetPieces() | ||
+ | { | ||
+ | List<string> temp = new List<string>(); | ||
+ | foreach (Piece p in pieces) | ||
+ | { | ||
+ | temp.Add(GetPieceData(p)); | ||
+ | } | ||
+ | return temp; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | This creates an empty list, and then adds the data from each piece (remember as a string). | ||
+ | |||
+ | Finally, back in SaveGame we can use the new list and write each piece to the file: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | List<string> pieces = g.GetPieces(); | ||
+ | foreach (string p in pieces) | ||
+ | { | ||
+ | myStream.WriteLine(p); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | =Final SaveGame Method= | ||
+ | So my finished SaveGame method looks like this: | ||
+ | |||
+ | <syntaxhighlight lang=c#> | ||
+ | public static void SaveGame(Player p1, Player p2, HexGrid g) | ||
+ | { | ||
+ | Console.Write("Enter the name of the file to save: "); | ||
+ | string fileName = Console.ReadLine(); | ||
+ | try | ||
+ | { | ||
+ | using (StreamWriter myStream = new StreamWriter(fileName)) | ||
+ | { | ||
+ | string playerData = p1.GetName() + "," + p1.GetVPs() + "," + p1.GetFuel() + "," + p1.GetLumber() + "," + p1.GetPiecesInSupply(); | ||
+ | myStream.WriteLine(playerData); | ||
+ | playerData = p2.GetName() + "," + p2.GetVPs() + "," + p2.GetFuel() + "," + p2.GetLumber() + "," + p2.GetPiecesInSupply(); | ||
+ | myStream.WriteLine(playerData); | ||
+ | int gridsize = g.GetSize(); | ||
+ | myStream.WriteLine(gridsize); | ||
+ | string tiles = g.GetTiles(); | ||
+ | myStream.WriteLine(tiles); | ||
+ | List<string> pieces = g.GetPieces(); | ||
+ | foreach (string p in pieces) | ||
+ | { | ||
+ | myStream.WriteLine(p); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | catch | ||
+ | { | ||
+ | Console.WriteLine("File not saved"); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> |
Latest revision as of 13:16, 12 September 2020
Contents
Game Save File
Player One,0,5,5,2 Player Two,0,5,5,2 6 #,#,~,~, , , ,~, , , , , ,#,#,#,~,~ 1,Baron,0 2,Baron,1 1,LESS,3 1,LESS,15 2,LESS,2 1,Serf,17 2,LESS,13
The first 2 lines are the player 1 and player 2 data
The third line is the grid size
The fourth line is each tile (notice the space between the comma, space is for a field)
From this point, each line is a piece. This should be the player, followed by the type of piece and finally the hex number.
Issue
The program is able to load a save game file, however it is not possible to save a game.
Solution
We need to create a new method in the program class for save game. The basic structure of the method is:
public static void SaveGame(Player p1, Player p2, HexGrid g)
{
Console.Write("Enter the name of the file to save: ");
string fileName = Console.ReadLine();
try
{
Console.WriteLine("File saved");
}
catch
{
Console.WriteLine("File not saved");
}
}
The SaveGame method above accepts parameters for Player1, Player2, and the grid. The code above will ask the user to enter a filename to use for the game save. I have included a try & catch because writing to files will often cause issues, so it is good error handling.
StreamWriter
Now, inside the try block but before the 'Console.WriteLine()' add the following to create and open the file:
using (StreamWriter myStream = new StreamWriter(fileName))
{
}
Player Data
Now inside the { } of the using statement add this:
string playerData = p1.GetName() + "," + p1.GetVPs() + "," + p1.GetFuel() + "," + p1.GetLumber() + "," + p1.GetPiecesInSupply();
myStream.WriteLine(playerData);
This will create a string of the data from Player1, the stream will have a 'WriteLine' which is used to write to the file.
Repeat the code above for Player2 (obviously change p1 to p2).
GridSize
The grid size is currently stored within the HexGrid object, however it is currently private and can't be accessed. Find the HexGrid class in the skeleton program:
class HexGrid
{
protected List<Tile> tiles = new List<Tile>();
protected List<Piece> pieces = new List<Piece>();
int size;
bool player1Turn;
public HexGrid(int n)
{
size = n;
SetUpTiles();
SetUpNeighbours();
player1Turn = true;
}
This is just a fraction of the HexGrid class, but you can see size is declared as an int. Because the default for variables is 'private' this isn't available to save the game. We could change this by adding public before the int size;. Alternatively we can create a property to access it:
public int GetSize()
{
return size;
}
Now, back in our SaveGame method and below the code to write the data for Player1 and Player2. We can get the grid size and write it to the file using this code:
int gridsize = g.GetSize();
myStream.WriteLine(gridsize);
Grid Tiles
The tiles within HexGrid are protected, so they can't be accessed. We therefore need to create a new method in HexGrid to return the tiles, this will be just as a string:
public string GetTiles()
{
string temp = "";
foreach (Tile t in tiles)
{
temp = temp + t.GetTerrain() + ",";
}
temp = temp.Substring(0, temp.Length - 1);
return temp;
}
The foreach loop will cycle through each tile, and add the terrain type to the temp string.
Adding "," will mean the final string will have a , at the end. The Substring will remove this final ,.
Now back in the SaveGame we can add the following after the code to write the tiles:
string tiles = g.GetTiles();
myStream.WriteLine(tiles);
Pieces
Unfortunately, like tiles the pieces in HexGrid are protected and also the pieceType in the Piece class is also protected. Another complication is that the piece doesn't store the location of the piece.
Changes to Piece
We need to add code into the Piece class to return the data we need. Create this method:
public string GetPieceData()
{
string temp = "";
if (this.belongsToPlayer1)
temp = "1";
else
temp = "2";
string piece = "";
switch (this.pieceType)
{
case "S":
piece = "Serf";
break;
case "B":
piece = "Baron";
break;
case "L":
piece = "LESS";
break;
case "P":
piece = "PBDS";
break;
}
temp = temp + "," + piece + ",";
return temp;
}
This will get everything required apart from the location, however this will need to come from elsewhere.
Changes to HexGrid
Now we have the new method in Piece, we can use it to complete the data for a single piece:
public string GetPieceData(Piece p)
{
string temp = "";
int count = 0;
foreach(Tile t in tiles)
{
if (p == t.GetPieceInTile())
temp = p.GetPieceData() + count;
count++;
}
return temp;
}
The tile number is literally the position in the list, so a simple count is used. When the piece is found this will be added to the output of GetPieceData.
Now we need to get the data of every piece:
public List<string> GetPieces()
{
List<string> temp = new List<string>();
foreach (Piece p in pieces)
{
temp.Add(GetPieceData(p));
}
return temp;
}
This creates an empty list, and then adds the data from each piece (remember as a string).
Finally, back in SaveGame we can use the new list and write each piece to the file:
List<string> pieces = g.GetPieces();
foreach (string p in pieces)
{
myStream.WriteLine(p);
}
Final SaveGame Method
So my finished SaveGame method looks like this:
public static void SaveGame(Player p1, Player p2, HexGrid g)
{
Console.Write("Enter the name of the file to save: ");
string fileName = Console.ReadLine();
try
{
using (StreamWriter myStream = new StreamWriter(fileName))
{
string playerData = p1.GetName() + "," + p1.GetVPs() + "," + p1.GetFuel() + "," + p1.GetLumber() + "," + p1.GetPiecesInSupply();
myStream.WriteLine(playerData);
playerData = p2.GetName() + "," + p2.GetVPs() + "," + p2.GetFuel() + "," + p2.GetLumber() + "," + p2.GetPiecesInSupply();
myStream.WriteLine(playerData);
int gridsize = g.GetSize();
myStream.WriteLine(gridsize);
string tiles = g.GetTiles();
myStream.WriteLine(tiles);
List<string> pieces = g.GetPieces();
foreach (string p in pieces)
{
myStream.WriteLine(p);
}
}
}
catch
{
Console.WriteLine("File not saved");
}
}