Search code examples
javaserializationloaddeserializationobjectinputstream

How to load a game using file/object input stream


I have written save / Load methods (not sure entirely if the save works but the file 'minesweepersavestate.ser' appears in my project folder after calling saveGame()). I want to try to get the load to work because at current it doesn't seem to do anything.

Here are my functions:

   public void saveGame(){

        GameBoard b = new GameBoard();
        try {
            System.out.println("Creating File/Object output stream...");
            FileOutputStream fileOut = new FileOutputStream("minesweepersavestate.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);

            System.out.println("Writing GameBoard Object...");
            out.writeObject(b);

            System.out.println("Save Successful...\n");
            out.close();
            fileOut.close();

        } catch(FileNotFoundException e) {
            System.out.println("no");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("no");
            e.printStackTrace();
        } 

    }


    public void loadBoard()
    {
        GameBoard b = null;
        try {

            System.out.println("Creating File/Object input stream...");

            FileInputStream fileIn = new FileInputStream("minesweepersavestate.ser");
            ObjectInputStream in = new ObjectInputStream(fileIn);

            System.out.println("Loading GameBoard Object...");
            b = (GameBoard)in.readObject();

            System.out.println("Load Successful...\n");
            in.close();
            fileIn.close();

        } catch (ClassNotFoundException e) {
            System.out.println("Class not found\n");
            e.printStackTrace();
        } catch(FileNotFoundException e) {
            System.out.println("File not found\n");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

How can I alter this method so that when i call the loadBoard() method, it brings back the game in the state it was saved?

Edit:

GameBoard Class:

public class GameBoard extends JFrame implements Serializable
{
//MENU ITEMS
private JFrame frame;
private JMenuBar menubar = new JMenuBar();
private JTable table;

//FIELDS USED FOR GAMEPLAY
private int x;
private int y;
private boolean mineTrue;
private boolean triedTrue;
private static int boardsize = 8; 
private  int numberOfMines = 10;
public static final int Empty = 0;
public static final int Mine = -1;
public static final int Flag = -2;
public static final int FMine = -3;
public static final int RevealedMine = -4;
public static final int RevealedEmpty = -5;
// SIZE OF BUTTONS
private int gridsize = 45;
// ARRAY FOR THE BUTTONS
private JButton[][] buttons;
private int[][] board;
//VARIABLE USED FOR LABELS
private static int noGamesPlayed = 0;
private static int noGamesWon = 0;
private int mine = 10;
private int minesLeft = 10;
private static int score = 1;
private static String playername;
// GAME STATUS
private boolean gamegoing = true;
// GAME LABELS

private JLabel space = new JLabel("");
private JTextField nameEnter = new JTextField("Enter name here: ");
private JButton saveName = new JButton("Play");
private JLabel namelabel = new JLabel("Player 1: ");
private JLabel scorelabel = new JLabel("0 points ");
private JLabel status = new JLabel("Game in Progress: ");
private JLabel gamesPlayed = new JLabel("Games Played: " + noGamesPlayed);
private JLabel gamesWon = new JLabel("Games Won : " + noGamesWon);
private JLabel noMines = new JLabel("Number of Mines: " + minesLeft);


/**
 * Constructor 
 */
public GameBoard() { }

/**
 *Making the game Frame
 */
private void makeFrame() { }

// MAKING THE GAME MENU BAR
public void makeMenuBar(){  
}   

public void setx(int pmeter) { }

public void sety(int pmeter) { }

public int getx() { }

public int gety() { }

public void settried(boolean paramBoolean) { }

public boolean gettried() { }

public void setmine(boolean paramBoolean) { }

public boolean getmine() { }

//ASSIGN MINES TO RANDOM LOCATION
public void assignmines() { }

// *********************************GAME CONTROLS************
private void quit() { }

//RESETS THE BOARD
public void reset() { }    

public void newGame() { }

public void biggerBoard() { }

public void changeDifficulty() { }

public void saveGame() { }


public void loadBoard() { }

// LOSING THE GAME ALERT
public void lose() { }

// WINNING THE GAME ALERT
public void win() { }

// UPDATING THE SCORE
public void updatescore() { }

public void gamesPlayed() { }

public void UpdateName() { }

public void updateGamesPlayed() { }

public void updateGamesWon() { }

//WHAT VALUES THE CHARACTER HAVE
static char whichCharacter(int value) { }

//This method shows how many mines are around the spot that was clicked
static int minesAround(int[][] board, int row, int col) { }

// This method takes in an x and y value and defines what should happen when the user clicks there. 
public void click(int rows, int cols) { }

//ACTION WHEN USER CLICKS ON A BUTTON INNER CLASS
private class MouseListener extends MouseAdapter {
    private int x = 0;
    private int y = 0;

    public MouseListener(int row, int col) { }

    public void mouseClicked(MouseEvent e) { }

}

}


Solution

  • You need to make sure that all your fields in your class are Serializable as this tutorial suggests. Of particular note are the requirements for a class to be Serializable:

    Notice that for a class to be serialized successfully, two conditions must be met:

    The class must implement the java.io.Serializable interface.

    All of the fields in the class must be serializable. If a field is not serializable, it must be marked transient.

    This means you'll have to do some digging in the Javadocs for all the fields in your GameBoard class. For instance, I did a quick search on JFrame, and there seems to be a bit of a nuance when it comes to saving a JFrame. When you retrieve the state of your saved game, it might be better just to recreate the GUI from scratch rather than to rely upon Serialization to do it for you. This thread also seems to concur that it's not a good idea to rely on Java to restore a GUI for you, but gives a suggestion as to how to possibly make it work:

    once deserialised, you will need to show the frame with frame.setVisible(true);