I've implemented the Conway's Game of Life in Java, including a GUI. Here's the code of the two classes I wrote:
GameOfLife.java
public class GameOfLife {
public static void main(String[] args) throws InterruptedException {
Gui gui = new Gui();
int [][] array = new int [71][71];
//Field edge is getting filled up with '2'
for(int i = 0; i < array.length; i++){
for(int j = 0; j < array.length; j++){
array[i][j] = 2;
}
}
//Field gets filled up with '0' = dead cells
for(int i = 1; i < array.length - 1; i++){
for(int j = 1; j < array.length - 1; j++){
array[i][j] = 0;
}
}
//A glider
array[9][5]=1;
array[9][6]=1;
array[9][7]=1;
array[8][7]=1;
array[7][6]=1;
Gui.printingOut(array);
}
public static void applyRules(int[][] array) {
int[][] newArray = new int[array.length][array.length];
for(int y = 1; y < array.length - 1; y++) {
for(int x = 1; x < array.length - 1; x++) {
int neighbors = neighborsCounter(array, x, y);
if(array[x][y] == 1) {
if((neighbors < 2) || (neighbors > 3)) {
newArray[x][y] = 0;
}
if((neighbors == 2) || (neighbors == 3)) {
newArray[x][y] = 1;
}
}
else if(array[x][y] == 0){
if(neighbors == 3) {
newArray[x][y] = 1;
}
else {
newArray[x][y] = 0;
}
}
}
}
for(int i = 1; i < array.length - 1; i++){
for(int j = 1; j < array.length - 1; j++) {
array[i][j] = newArray[i][j];
}
}
}
public static int neighborsCounter(int[][] array, int x, int y) {
int neighbors = 0;
for(int i = x - 1; i <= x + 1; i++) {
for(int j = y - 1; j <= y + 1; j++) {
if(array[i][j] == 1) {
neighbors = neighbors + 1;
}
}
}
if(array[x][y] == 1) {
neighbors = neighbors - 1;
}
return neighbors;
}
}
And here's the class for the GUI:
Gui.java
import javax.swing.*;
import java.awt.*;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
public class Gui {
static JPanel panel;
static JFrame frame;
static int count = 0;
static boolean[] test = new boolean[1];
public static void helper() {
count++;
if(count % 2 != 0) {
test[0] = false;
}
else {
test[0] = true;
}
}
public static void GraphicalInterface(int[][] array, Graphics graphic) {
int BOX_DIM = 10;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[0].length; j++) {
if(array[i][j] == 0) {
graphic.setColor(Color.WHITE);
}
if(array[i][j] == 1) {
graphic.setColor(Color.BLACK);
}
if(array[i][j] == 2) {
graphic.setColor(Color.RED);
}
graphic.fillRect(i * BOX_DIM, j * BOX_DIM, BOX_DIM, BOX_DIM);
}
}
}
public static void printingOut(int[][] array) throws InterruptedException {
test[0] = true;
JFrame frame = new JFrame("Conway's Game of Life");
frame.setSize(830,800);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(710, 710));
JButton button = new JButton("Start / Stop");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) {
helper();
}
});
frame.add(button, BorderLayout.EAST);
frame.add(panel, BorderLayout.WEST);
frame.setVisible(true);
while(true) {
//Printing out
while(Gui.test[0]) {
Graphics graphic = panel.getGraphics();
GraphicalInterface(array, graphic);
//Applying rules
GameOfLife.applyRules(array);
Thread.sleep(249);
}
Thread.sleep(1);
}
}
}
I would appreciate any suggestions to improve my code.
2 Answers 2
Gui.java
1) The panel
and frame
variables are unused.
static JPanel panel;
static JFrame frame;
2) The test
variable can be converted to a boolean.
static boolean test;
3) The helper
method can be simplified
public static void helper() {
test = count++ % 2 == 0;
}
4) Method GraphicalInterface
You should rename it to
graphicalInterface
, since the methods start with a lowercase.The variable
BOX_DIM
should be a class constant.
public static final int BOX_DIM = 10;
- In the loop, you can use an else-if or a switch case, since you can have only one choice.
if (array[i][j] == 0) {
graphic.setColor(Color.WHITE);
} else if (array[i][j] == 1) {
graphic.setColor(Color.BLACK);
} else if (array[i][j] == 2) {
graphic.setColor(Color.RED);
}
or
if (array[i][j] == 0) {
graphic.setColor(Color.WHITE);
} else if (array[i][j] == 1) {
graphic.setColor(Color.BLACK);
} else if (array[i][j] == 2) {
graphic.setColor(Color.RED);
}
GameOfLife.java
MethodapplyRules
1) Since the array is not updated during the execution of the method, I suggest that you extract the array.length
in a variable (used 6 times).
2) You can extract array[x][y]
in a variable.
public static void applyRules(int[][] array) {
final int lengthOfTheArray = array.length;
int[][] newArray = new int[lengthOfTheArray][lengthOfTheArray];
for (int y = 1; y < lengthOfTheArray - 1; y++) {
for (int x = 1; x < lengthOfTheArray - 1; x++) {
int neighbors = neighborsCounter(array, x, y);
final int currentArrayValue = array[x][y];
if (currentArrayValue == 1) {
if ((neighbors < 2) || (neighbors > 3)) {
newArray[x][y] = 0;
}
if ((neighbors == 2) || (neighbors == 3)) {
newArray[x][y] = 1;
}
} else if (currentArrayValue == 0) {
if (neighbors == 3) {
newArray[x][y] = 1;
} else {
newArray[x][y] = 0;
}
}
}
}
for (int i = 1; i < lengthOfTheArray - 1; i++) {
for (int j = 1; j < lengthOfTheArray - 1; j++) {
array[i][j] = newArray[i][j];
}
}
}
Method neighborsCounter
1) Instead of increasing the variable neighbors
using neighbors = neighbors + 1;
, you can use neighbors++;
.
2) Same for the decrease, you can use:
if (array[x][y] == 1) {
neighbors--;
}
``
You should remove all static qualifiers, so that you have real object. Maby create a Main.java with the main function so that it is your only class with static. Your distinction between Gui and GameOfLife is good and i would keep it that way.
You can move the int [][] array = new int [71][71];
out of the method to a field from the class GameOfLife and you should rename it to something like "gamefield" or "gamestate".
These are the important things.
A little thing you can replace:
static int count = 0;
static boolean[] test = new boolean[1];
with something like:
boolean running = true;
the hole helper() can be replaced with:
running = !running;