JAVA!!! I really need help with this problem. I don\'t have any ideas how to sav
ID: 3739466 • Letter: J
Question
JAVA!!! I really need help with this problem. I don't have any ideas how to save and recall the state of the Game of Life.
Here's the instruction:
Now, the state information is what's stored in the "two-dimensional" matrix you created in for Part I. What you need to do is serialize the data for storage into a file. You may find the notes (documentation) for java.io.Seralizable to be helpful.
Now, this serialized data (yes, it just means that it's been arranged into a single string of bytes) needs to be stored. Recall that java.io is structured around input and output streams. So, you will need to create an output stream (with an associated file open for writing) to save the state of the game. The serialized data can be stored using that output stream. Similarly, to restore the stored state of the game, you will need to create an input stream (with an associated file open for reading). Some research on your part will make this operation relatively trivial.
The question may arise about user interface for saving and restoring the state information. For example, you could have a textbox in your user interface, with Save and Restore buttons (or other similar captions). This is a minimal user interface, which is rather straight-forward to code. The issue becomes one of making sure that the user is providing reasonable file and folder information. To help the user give folder information, one could use javax.swing.JFileChooser. This class supports File Open and File Save As options. This circumvents a number of the potential problems with opening files for reading or writing, since the user will be 'guided' to give reasonable directory information. (There is an extra-credit option for filtering the files displayed by the File Open, and possibly amending the file name for File Save.)
Note: no matter how you support the user providing filename information, it is reasonable for the application to 'ask' before it overwrites a file. With this sort of game is not typical that a user will want to open a saved game, let it run for a while, then save the updated state (overwriting the formerly saved state). The initial state is of greater interest than the resultant state, since the resultant state is derivable in a mechanical way from the starting point. So, one of the requirements for full credit is to check for the existence of the output file and confirm overwrite before saving, even if it is the file that was read to give this starting state. (A simple confirm dialog box is supported by JOptionPane.)
Here is what I've done so far:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
public class runMain extends JFrame implements ActionListener, Runnable{
// Label the number of generation
private JLabel generationLabel;
// Label the start/stop/reset buttons
private JButton start;
private JButton stop;
private JButton restart;
// The inital number of generation
private int generation = 0;
// Thread clas object
private Thread t;
private boolean flag = true;
// Label the cells
private MarkLabel[][] mark;
// Declare state of the game
private boolean gameLife = false;
/**
* Construct game of life with user interface
*/
public runMain(int ROW, int COL){
// Set up window
super("Life - Controller");
setLocation(25,25);
setSize(450,450);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Creating the labels for cells on board game
mark = new MarkLabel[ROW + 2][COL + 2];
for (int row = 0; row < ROW + 2; row++) {
for (int col = 0; col < COL + 2; col++) {
mark[row][col] = new MarkLabel();
}
}
// Set size of horizontal and vertical lines and set color for lines
JPanel boardPanel = new JPanel(new GridLayout(ROW, COL, 1, 1));
// Set background color
boardPanel.setBackground(Color.LIGHT_GRAY);
// Adding each label to the board panel and add to each of them to its neigbors
for(int row = 1; row <ROW+1; row++) {
for(int col = 1; col < COL+1; col++) {
boardPanel.add(mark[row][col]);
mark[row][col].nextAdd(mark[row-1][col]);
mark[row][col].nextAdd(mark[row+1][col]);
mark[row][col].nextAdd(mark[row][col-1]);
mark[row][col].nextAdd(mark[row][col+1]);
mark[row][col].nextAdd(mark[row-1][col-1]);
mark[row][col].nextAdd(mark[row-1][col+1]);
mark[row][col].nextAdd(mark[row+1][col-1]);
mark[row][col].nextAdd(mark[row+1][col+1]);
}
}
// Adding to Panel
add(boardPanel, BorderLayout.CENTER);
// Arrange the stop/stop/reset buttons and generation on the board
boardPanel = new JPanel( new GridLayout (2,0));
boardPanel.setBackground(Color.green);
JPanel buttonPanel = new JPanel( new GridLayout(1,0));
// Label the start button, set color to green and take action from user
start = new JButton("Start");
start.addActionListener(this);
start.setBackground(Color.green);
start.setFont(new Font("Calibri", Font.BOLD, 18));
buttonPanel.add(start);
// Label the stop button, set color to green and take action from user
stop = new JButton("Stop");
stop.addActionListener(this);
stop.setBackground(Color.green);
stop.setFont(new Font("Calibri", Font.BOLD, 18));
buttonPanel.add(stop);
// Label the reset button, set color to green and take action from user
restart = new JButton("Reset");
restart.addActionListener(this);
restart.setBackground(Color.green);
restart.setFont(new Font("Calibri", Font.BOLD, 18));
buttonPanel.add(restart);
// Add button to the board
boardPanel.add(buttonPanel);
// Label the generation, set up Font, set up its location and add to the gameboard
generationLabel = new JLabel("Generation: 0", JLabel.CENTER);
generationLabel.setFont(new Font("Calibri", Font.BOLD, 20));
boardPanel.add(generationLabel);
add(boardPanel, BorderLayout.SOUTH);
// Set window to be visible
validate();
setVisible(true);
// Instructions for player
UIManager jPane1 = new UIManager();
jPane1.put("OptionPane.background", Color.green);
jPane1.put("Panel.background", Color.yellow);
JOptionPane.showMessageDialog(null,
"Create some pattern by clicking on the board, then click start ",
"How to play the game ?",JOptionPane.INFORMATION_MESSAGE);
}
/**
* This method takes action from user to start/stop/reset
* @return Return the values everytime for start/stop/reset
*/
public void actionPerformed(ActionEvent e) {
Object act = e.getSource();
// If start button is clicked, the game runs with the delay of 1000 milliseconds(1 second)
if(act == start){
if (flag){
gameLife = true;
t = new Thread (this);
// Start thread(timer)
t.start();
flag = false;
}
// Return the value
return;
}
// If stop button is clicked, the game stop(set it to false)
else if(act == stop){
try{
// Stop the thread
t.stop();
}
catch(NullPointerException ae){
// Do nothing
}
gameLife = false;
flag = true;
// Return the value
return;
}
// If reset button is clicked, reset everything
else if(act == restart){
try{
// Stop the thread
t.stop();
}
catch(NullPointerException ae){
// Do nothing
}
gameLife = false;
flag = true;
// Reset every cell
for( int row = 1; row < mark.length -1; row ++){
for(int col = 1; col < mark[row].length - 1; col ++){
mark[row][col].restart();
}
}
// Reset number of generation
generation = 0;
generationLabel.setText("Generation: " + generation);
// Return the value
return;
}
//if the game is not running wait for next time
if(!gameLife)
return;
}
/**
* Method of thread class
*/
public void run() {
try{
while(true){
// Increment the number of generation by 1 and add it to gameboard
generation ++;
generationLabel.setText("Generation: " + generation);
// Checking and updating state of cells
for(int row = 0; row < mark.length; row++) {
for(int col = 0; col < mark[row].length; col++) {
mark[row][col].checkState();
}
}
for(int row = 0; row < mark.length; row++) {
for(int col = 0; col < mark[row].length; col++) {
mark[row][col].updateState();
}
}
// Sleeping thread for 1 second
Thread.sleep(1000);
}
}
catch(InterruptedException e) {
// Do nothing
}
}
/**
* This is the main method which runs the program
* @param args The command-line arguments
*/
public static void main(String[] args) {
// 19*19 size gameboard
new runMain(19,19);
}
}
class MarkLabel extends JLabel implements MouseListener {
// Declare the color for gameboard and clicked cells
static final Color[] color = {Color.GRAY, Color.RED};
// Declare state of the game and number of neighbor cells
private int state, newState, nCell;
// Set up the array
private MarkLabel[] neighborCell = new MarkLabel[8];
MarkLabel() {
// State of the game DEAD
state = newState = 0;
// Show up color
setOpaque(true);
setBackground(color[0]);
// To select new ALIVE cells
addMouseListener(this);
}
// Adding neighbor cell
void nextAdd(MarkLabel n) {
neighborCell[nCell++] = n;
}
// Check cells whether it should stay ALIVE or DEAD
void checkState() {
int Alive = 0;
for(int i = 0; i < nCell; i++)
Alive += neighborCell[i].state;
// If state is alive:
if(state == 1) {
// Cell with fewer 2 LIVE neighbor dies
if(Alive < 2)
newState = 0;
// Cell with more than 3 neigbor dies
if(Alive > 3)
newState = 0;
}
// If DEAD cells with 3 LIVE neighbors will become ALIVE
else {
if(Alive == 3)
newState = 1;
}
}
// Update the state
void updateState() {
if(state != newState) {
state = newState;
setBackground(color[state]);
}
}
// Call when the game is reseted
void restart() {
if(state == 1 || newState == 1) {
state = newState = 0;
setBackground(color[state]);
}
}
/**
* This method takes action from clicking mouse from the user
*/
// If mouse is click on a cell, it become ALIVE
@Override
public void mouseClicked(MouseEvent e) {
state = newState = 1;
setBackground(color[1]);
}
// If click on a ALIVE cell, hold and drag that cell, it will become DEAD
@Override
public void mouseReleased(MouseEvent e) {
state = newState = 0;
setBackground(color[0]);
}
// Do nothing for all of these below
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
Explanation / Answer
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.io.*;
//import java.io.Serializable;
public class runMain extends JFrame implements ActionListener, Runnable {
// Label the number of generation
private JLabel generationLabel;
// Label the start/stop/reset buttons
private JButton start;
private JButton stop;
private JButton restart;
private JButton save;
private JButton restore;
private JFileChooser fileChooser;
// The inital number of generation
private int generation = 0;
// Thread clas object
private Thread t;
private boolean flag = true;
// Label the cells
private MarkLabel[][] mark;
// Declare state of the game
private boolean gameLife = false;
/**
* Construct game of life with user interface
*/
public runMain(int ROW, int COL) {
// Set up window
super("Life - Controller");
setLocation(25, 25);
setSize(450, 450);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Creating the labels for cells on board game
mark = new MarkLabel[ROW + 2][COL + 2];
for (int row = 0; row < ROW + 2; row++) {
for (int col = 0; col < COL + 2; col++) {
mark[row][col] = new MarkLabel();
}
}
// Set size of horizontal and vertical lines and set color for lines
JPanel boardPanel = new JPanel(new GridLayout(ROW, COL, 1, 1));
// Set background color
boardPanel.setBackground(Color.LIGHT_GRAY);
// Adding each label to the board panel and add to each of them to its neigbors
for (int row = 1; row < ROW + 1; row++) {
for (int col = 1; col < COL + 1; col++) {
boardPanel.add(mark[row][col]);
mark[row][col].nextAdd(mark[row - 1][col]);
mark[row][col].nextAdd(mark[row + 1][col]);
mark[row][col].nextAdd(mark[row][col - 1]);
mark[row][col].nextAdd(mark[row][col + 1]);
mark[row][col].nextAdd(mark[row - 1][col - 1]);
mark[row][col].nextAdd(mark[row - 1][col + 1]);
mark[row][col].nextAdd(mark[row + 1][col - 1]);
mark[row][col].nextAdd(mark[row + 1][col + 1]);
}
}
// Adding to Panel
add(boardPanel, BorderLayout.CENTER);
// Arrange the stop/stop/reset buttons and generation on the board
boardPanel = new JPanel(new GridLayout(3, 0));
boardPanel.setBackground(Color.green);
JPanel buttonPanel = new JPanel(new GridLayout(1, 0));
// Label the start button, set color to green and take action from user
start = new JButton("Start");
start.addActionListener(this);
start.setBackground(Color.green);
start.setFont(new Font("Calibri", Font.BOLD, 18));
buttonPanel.add(start);
// Label the stop button, set color to green and take action from user
stop = new JButton("Stop");
stop.addActionListener(this);
stop.setBackground(Color.green);
stop.setFont(new Font("Calibri", Font.BOLD, 18));
buttonPanel.add(stop);
// Label the reset button, set color to green and take action from user
restart = new JButton("Reset");
restart.addActionListener(this);
restart.setBackground(Color.green);
restart.setFont(new Font("Calibri", Font.BOLD, 18));
buttonPanel.add(restart);
// Add button to the board
boardPanel.add(buttonPanel);
// Label the generation, set up Font, set up its location and add to the gameboard
generationLabel = new JLabel("Generation: 0", JLabel.CENTER);
generationLabel.setFont(new Font("Calibri", Font.BOLD, 20));
boardPanel.add(generationLabel);
add(boardPanel, BorderLayout.SOUTH);
boardPanel = new JPanel(new GridLayout(0, 2));
save = new JButton("Save State");
save.addActionListener(this);
boardPanel.add(save);
restore = new JButton("Restore State");
restore.addActionListener(this);
boardPanel.add(restore);
add(boardPanel, BorderLayout.NORTH);
// Set window to be visible
validate();
setVisible(true);
// Instructions for player
UIManager jPane1 = new UIManager();
jPane1.put("OptionPane.background", Color.green);
jPane1.put("Panel.background", Color.yellow);
JOptionPane.showMessageDialog(null,
"Create some pattern by clicking on the board, then click start ",
"How to play the game ?", JOptionPane.INFORMATION_MESSAGE);
}
/**
* This method takes action from user to start/stop/reset
*
* @return Return the values everytime for start/stop/reset
*/
public void actionPerformed(ActionEvent e) {
Object act = e.getSource();
// If start button is clicked, the game runs with the delay of 1000 milliseconds(1 second)
if (act == start) {
if (flag) {
gameLife = true;
t = new Thread(this);
// Start thread(timer)
t.start();
flag = false;
}
// Return the value
return;
} // If stop button is clicked, the game stop(set it to false)
else if (act == stop) {
try {
// Stop the thread
t.stop();
} catch (NullPointerException ae) {
// Do nothing
}
gameLife = false;
flag = true;
// Return the value
return;
} // If reset button is clicked, reset everything
else if (act == restart) {
try {
// Stop the thread
t.stop();
} catch (NullPointerException ae) {
// Do nothing
}
gameLife = false;
flag = true;
// Reset every cell
for (int row = 1; row < mark.length - 1; row++) {
for (int col = 1; col < mark[row].length - 1; col++) {
mark[row][col].restart();
}
}
// Reset number of generation
generation = 0;
generationLabel.setText("Generation: " + generation);
// Return the value
return;
} else if (act == save) {
fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(this);
if (result == JFileChooser.APPROVE_OPTION) {
File f = fileChooser.getSelectedFile();
try {
FileOutputStream fout = new FileOutputStream(f);
ObjectOutputStream out = new ObjectOutputStream(fout);
out.writeObject(mark);
out.flush();
} catch (Exception ex) {
}
}
} else if (act == restore) {
fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(this);
if (result == JFileChooser.APPROVE_OPTION) {
File f = fileChooser.getSelectedFile();
try {
FileInputStream fin = new FileInputStream(f);
ObjectInputStream in = new ObjectInputStream(fin);
mark = (MarkLabel[][]) in.readObject();
} catch (Exception ex) {
}
}
//if the game is not running wait for next time
if (!gameLife) {
return;
}
}
}
/**
* Method of thread class
*/
public void run() {
try {
while (true) {
// Increment the number of generation by 1 and add it to gameboard
generation++;
generationLabel.setText("Generation: " + generation);
// Checking and updating state of cells
for (int row = 0; row < mark.length; row++) {
for (int col = 0; col < mark[row].length; col++) {
mark[row][col].checkState();
}
}
for (int row = 0; row < mark.length; row++) {
for (int col = 0; col < mark[row].length; col++) {
mark[row][col].updateState();
}
}
// Sleeping thread for 1 second
Thread.sleep(1000);
}
} catch (InterruptedException e) {
// Do nothing
}
}
/**
* This is the main method which runs the program
*
* @param args The command-line arguments
*/
public static void main(String[] args) {
// 19*19 size gameboard
new runMain(19, 19);
}
}
class MarkLabel extends JLabel implements MouseListener {
// Declare the color for gameboard and clicked cells
static final Color[] color = {Color.GRAY, Color.RED};
// Declare state of the game and number of neighbor cells
private int state, newState, nCell;
// Set up the array
private MarkLabel[] neighborCell = new MarkLabel[8];
MarkLabel() {
// State of the game DEAD
state = newState = 0;
// Show up color
setOpaque(true);
setBackground(color[0]);
// To select new ALIVE cells
addMouseListener(this);
}
// Adding neighbor cell
void nextAdd(MarkLabel n) {
neighborCell[nCell++] = n;
}
// Check cells whether it should stay ALIVE or DEAD
void checkState() {
int Alive = 0;
for (int i = 0; i < nCell; i++) {
Alive += neighborCell[i].state;
}
// If state is alive:
if (state == 1) {
// Cell with fewer 2 LIVE neighbor dies
if (Alive < 2) {
newState = 0;
}
// Cell with more than 3 neigbor dies
if (Alive > 3) {
newState = 0;
}
} // If DEAD cells with 3 LIVE neighbors will become ALIVE
else if (Alive == 3) {
newState = 1;
}
}
// Update the state
void updateState() {
if (state != newState) {
state = newState;
setBackground(color[state]);
}
}
// Call when the game is reseted
void restart() {
if (state == 1 || newState == 1) {
state = newState = 0;
setBackground(color[state]);
}
}
/**
* This method takes action from clicking mouse from the user
*/
// If mouse is click on a cell, it become ALIVE
@Override
public void mouseClicked(MouseEvent e) {
state = newState = 1;
setBackground(color[1]);
}
// If click on a ALIVE cell, hold and drag that cell, it will become DEAD
@Override
public void mouseReleased(MouseEvent e) {
state = newState = 0;
setBackground(color[0]);
}
// Do nothing for all of these below
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.