Showing posts with label Java Notes. Show all posts
Showing posts with label Java Notes. Show all posts

Game of Life simulation Java


/**@author Thanh Lai

/* @version 2*/

import java.util.Scanner;

import javax.swing.JFrame;

public class MainGOL extends JFrame {
    static Scanner scan = new Scanner(System.in);
    static JFrame mainFrame;
    static int Tcol;
    static int Trow;
    static int delay;
    static int generation;

    public static void main(String[] args) {
        /* Prompting user input and check it */
        System.out
                .println("Please enter the width of the universe grid(10-50): ");
        Tcol = scan.nextInt();
        // check for 10 to 50
        if (Tcol < 10 || Tcol > 50) {
            if (Tcol < 10) {
                System.out
                        .println("The width is less than 10. Default width is set to 10.");
                Tcol = 10;
            }
            if (Tcol > 50) {
                System.out
                        .println("The width is greater than 50. Default width is set to 50.");
                Tcol = 50;
            }

        }
        System.out
                .println("Please enter the height of the universe grid(10-50): ");
        Trow = scan.nextInt();
        if (Trow < 10 || Trow > 50) {
            if (Trow < 10) {
                System.out
                        .println("The height is less than 10. Default height is set to 10.");
                Trow = 10;
            }
            if (Trow > 50) {
                System.out
                        .println("The height is greater than 50. Default height is set to 50.");
                Trow = 50;
            }

        }
        System.out.println("Please enter the delay between ticks(0-3000): ");
        delay = scan.nextInt();
        if (delay < 0 || delay > 3000) {
            System.out
                    .println("The delay is out of range. Default delay is set to 500");
            delay = 500;
        }

        System.out
                .println("How many ticks(generations) to run before pausing(0-for continuously): ");
        generation = scan.nextInt();

        /* Create a main frame which contains a main panel */
        mainFrame = new JFrame("Game of Life - Thanh Lai - A00831625");

        /* Create a main panel and add it into the main frame */
        PanelGOL obPanel = new PanelGOL();
        mainFrame.getContentPane().add(obPanel);

        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.pack();
        mainFrame.setVisible(true);
    }

}
 
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Creatures extends JPanel {

 public boolean alive = false;
 public boolean goingToChange = false;
 JLabel x = new JLabel(" ");

 /*
  * Once the Creatures object is created, the random state of the Creatures'
  * cell will be generated
  */
 public Creatures() {
  if ((int) (Math.random() * 2) == 1) {
   alive = true;
   x.setText("X");
  }
  this.add(x);
 }

}

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class PanelGOL extends JPanel {
 static JPanel mainPanel;
 static int ticks = 0;
 /*
  * Create creature cells object which represents for each cells in the main
  * panel
  */
 static Creatures cells[][] = new Creatures[MainGOL.Trow][MainGOL.Tcol];

 /* Timer object 'fires' the action listener after delay period */
 Timer time = new Timer(MainGOL.delay, new MyActionListener());

 public PanelGOL() {
  /*
   * Create a grid layout for the main panel in order to describe the
   * cells
   */
  mainPanel = new JPanel(new GridLayout(MainGOL.Trow, MainGOL.Tcol, 2, 2));
  this.addKeyListener(new TAdapter());
  this.add(mainPanel);
  buildWorld();
  time.start();
  this.setFocusable(true);

 }

 /* Initialize Creatures' object for each cells */
 public static void buildWorld() {
  for (int row = 0; row < MainGOL.Trow; row++) {
   for (int col = 0; col < MainGOL.Tcol; col++) {
    Creatures tempCreature = new Creatures();
    tempCreature.setBackground(Color.orange);
    mainPanel.add(cells[row][col] = tempCreature);
   }
  }

 }

 /*
  * Create a method that return the state  of the Creatures'
  * objects
  */
 public boolean checkState(int row, int col) {
  return cells[row][col].alive;
 }

 /* Logical core of the program */
 /*
  * The method is to check eight neighbor cells - up, down, right, left, and
  * diagonally-except for the cells on the edge of the grid . Finally, return
  * the neighbors number
  */
 public int checkNeighborOf(int row, int col) {
  int neighbors = 0;
  for (int r = row - 1; r <= row + 1; r++)
   for (int c = col - 1; c <= col + 1; c++) {
    if (r < 0 || c < 0 || r >= MainGOL.Trow || c >= MainGOL.Tcol)
     continue;
    if (r == row && c == col)
     continue;
    if (checkState(r, c))
     neighbors++;
   }
  return neighbors;
 }

 /*
  * Create a method to point that which cells are going to be changed after a
  * tick. Due to death and give birth happens at the same time the
  * goingToChange variable is declared to hold the state of each cell before
  * they are actually "be killed or give birth"
  */
 public void killOrCreate() {
  for (int row = 0; row < MainGOL.Trow; row++)
   for (int col = 0; col < MainGOL.Tcol; col++) {
    if (checkNeighborOf(row, col) == 3 && !cells[row][col].alive) {
     cells[row][col].goingToChange = true;
    } else if (cells[row][col].alive
      && checkNeighborOf(row, col) == 2
      || checkNeighborOf(row, col) == 3) {
     cells[row][col].goingToChange = false;
    } else {
     cells[row][col].goingToChange = cells[row][col].alive;
    }
    //to let the cell know it will be changed state (die --> alive or alive--> die)

   }
 }

 /*
  * Support the method above, this method is to change state of the cells
  * through 'alive' variable
  */
 private void changeState() {
  for (int row = 0; row < MainGOL.Trow; row++)
   for (int col = 0; col < MainGOL.Tcol; col++) {
    if (cells[row][col].goingToChange) {
     cells[row][col].alive = !cells[row][col].alive;
    }
   }
 }

 /*
  * After all, rebuild the panels by re-setting its state to appropriate
  * shown-text
  */
 private void reBuildWorld() {
  for (int row = 0; row < MainGOL.Trow; row++)
   for (int col = 0; col < MainGOL.Tcol; col++) {
    if (cells[row][col].alive)
     cells[row][col].x.setText("X");
    else
     cells[row][col].x.setText(" ");
   }
  ticks++;
  System.out.println("Generations: " + ticks);
 }

 /*
  * MyActionListener class implements the whole checking cells, changing
  * states and rebuilding the panels process
  */
 private class MyActionListener implements ActionListener {
  public void actionPerformed(ActionEvent e) {

   killOrCreate();
   changeState();
   reBuildWorld();
   MainGOL.mainFrame.pack();
   MainGOL.mainFrame.repaint();

   if (MainGOL.generation != 0 && ticks == MainGOL.generation) {
    time.stop();
   }
  }

 }

 /* Key functions for the requirement */

 private class TAdapter extends KeyAdapter {
  public void keyPressed(KeyEvent e) {
   /* space key pauses / resumes the game */
   int spaceKey = e.getKeyCode();
   if (spaceKey == 32) { // space key value is 32
    if (time.isRunning()) {
     time.stop();
    } else
     time.start();
   }
   /* escape key stops and exists the game at any point */
   int EscKey = e.getKeyCode();
   if (EscKey == 27) { // escape key value is 27
    System.out.println("Exit program");
    System.exit(0);
   }
   /* s key executes the game for one tick and pauses */
   int sKey = e.getKeyCode(); // 83
   if (sKey == 83) {
    if (time.isRunning()) {
     time.stop();
    }
    killOrCreate();
    changeState();
    reBuildWorld();
    MainGOL.mainFrame.pack();
    MainGOL.mainFrame.repaint();
   }
  }

 }
}
Download the complete source code

Output:

 

How to create a JFrame

import java.awt.*;
import javax.swing.*;
/*Thanh Lai*/
public class MyWindow extends JFrame{
    public MyWindow(){
        super("Demo My Window"); //title bar attribute
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    public static void main(String[] args){
        MyWindow thanh = new MyWindow();    //create a frame
        thanh.setSize(400,400);       
        thanh.setLocationRelativeTo(null);    //display the window on the center of the screen
        thanh.setVisible(true);                //show the window
    }
   
}

Output

Static and Instance Variable

Question: What is the difference between static variable and instance variable?

Answer:

public class Thanh{
int x = 9;
}
....
Thanh a = new Thanh();
Thanh b = new Thanh();

Both a & b have its own copy of x

---------------------------------------------

public class Thanh{
static int x = 9;
}
....
Thanh a = new Thanh();
Thanh b = new Thanh();

Both a & b have the exactly one x to share between them


Note: the static variable is initialized immediately when the JVM loads the class


Java Notes

Question and answer section for Java where I share my own Java notes
 

Copyright © 2013-2014 Lai Duy Thanh All rights reserved.