Reputation: 139
I've been trying to make a Game of Life program in a fairly simple (yet maybe wrong) way. Technically it seems to work but when I tried to run some test-cases the results did not fit the examples online.
Here's the main class:
package gameOfLife;import java.applet.*;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import gameOfLife.Cell.State;
public class CreateGame extends Applet implements Runnable, MouseListener, KeyListener {
private enum GameState {
SETTING, START
}
private GameState state = GameState.SETTING;
private Image image;
private Graphics second;
private Cell[][] cells = new Cell[200][120];
private int indexI = 1;
private int indexJ = 1;
@Override
public void init() {
setSize(1000, 600);
setFocusable(true);
Frame frame = (Frame) this.getParent().getParent();
frame.setResizable(false);
frame.setTitle("Game of Life - Settings");
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[0].length; j++) {
cells[i][j] = new Cell(i * 5, j * 5);
}
}
addMouseListener(this);
addKeyListener(this);
super.init();
}
@Override
public void start() {
Thread thread = new Thread(this);
thread.start();
super.start();
}
@Override
public void run() {
while (true) {
if (state == GameState.START) {
for(int i=1; i<cells.length-1; i++){
for(int j=1; j<cells[0].length-1; j++){
update(i, j);
}
}
}
repaint();
try {
Thread.sleep(125);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void update(int i, int j) { //updating the cells into ALIVE/DEAD state
int[] neighbors = new int[8];
int sum = 0;
for (int index = 0; index < 8; index++)
neighbors[index] = 0;
if (cells[i - 1][j - 1].state == State.ALIVE)
neighbors[0] = 1;
if (cells[i][j - 1].state == State.ALIVE)
neighbors[1] = 1;
if (cells[i + 1][j - 1].state == State.ALIVE)
neighbors[2] = 1;
if (cells[i - 1][j].state == State.ALIVE)
neighbors[3] = 1;
if (cells[i + 1][j].state == State.ALIVE)
neighbors[4] = 1;
if (cells[i - 1][j + 1].state == State.ALIVE)
neighbors[5] = 1;
if (cells[i][j + 1].state == State.ALIVE)
neighbors[6] = 1;
if (cells[i + 1][j + 1].state == State.ALIVE)
neighbors[7] = 1;
for (int index = 0; index < 8; index++)
sum += neighbors[index];
if ((sum < 2 || sum > 3) && cells[i][j].state == State.ALIVE)
cells[i][j].state = State.DEAD;
else {
if (sum == 3 && cells[i][j].state == State.DEAD)
cells[i][j].state = State.ALIVE;
}
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Rectangle r;
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[0].length; j++) {
if (cells[i][j].state == State.ALIVE) {
r = cells[i][j].getCell();
g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(), (int) r.getHeight());
}
}
}
super.paint(g);
}
@Override
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
second = image.getGraphics();
}
second.setColor(getBackground());
second.fillRect(0, 0, getWidth(), getHeight());
second.setColor(getForeground());
paint(second);
g.drawImage(image, 0, 0, this);
}
@Override
public void mousePressed(MouseEvent e) {
if (state == GameState.SETTING) {
int x = e.getX() - e.getX() % 5;
int y = e.getY() - e.getY() % 5;
cells[x / 5][y / 5].born();
}
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
if(state == GameState.START)
state = GameState.SETTING;
else
state = GameState.START;
}
}
@Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
I made the program in a way that by pressing the Space key you change the game state from SETTING (clicking on the screen to create cells which pauses the game) and START which makes the game run on its own. Cell is a class I created which contains the Rectangle and state:
package gameOfLife;
import java.awt.Rectangle;
public class Cell {
final int Measure = 5;
public static enum State{
DEAD, ALIVE
}
private Rectangle cell;
private int x, y;
public State state;
public void born(){
state = State.ALIVE;
}
public Cell(int x, int y){
state = State.DEAD;
cell = new Rectangle(x, y, Measure, Measure);
this.x = x;
this.y = y;
}
public Rectangle getCell(){
return this.cell;
}
}
If anyone can test it and tell me what's wrong with the program logic it will be great, because overall its working, but there's probably some minor issue I can't put my finger on which screws it up.
Upvotes: 0
Views: 2020
Reputation: 134
I've figured out the error - you were refreshing the state of each cell as you iterated through the grid, but the correct way is to create a grid of new cell states during the iteration, then set the existing cell states to the new cell states in one go, if that makes sense.
Amended code which seems to work:
public class CreateGame
extends Applet
implements Runnable, MouseListener, KeyListener
{
private enum GameState
{
SETTING, START
}
private GameState state = GameState.SETTING;
private Image image;
private Graphics second;
private Cell[][] cells = new Cell[200][120];
private int indexI = 1;
private int indexJ = 1;
@Override
public void init()
{
setSize(1000, 600);
setFocusable(true);
Frame frame = (Frame) this.getParent().getParent();
frame.setResizable(false);
frame.setTitle("Game of Life - Settings");
for (int i = 0; i < cells.length; i++)
{
for (int j = 0; j < cells[0].length; j++)
{
cells[i][j] = new Cell(i * 5, j * 5);
}
}
addMouseListener(this);
addKeyListener(this);
super.init();
}
@Override
public void start()
{
Thread thread = new Thread(this);
thread.start();
super.start();
}
@Override
public void run()
{
while (true)
{
if (state == GameState.START)
{
Cell[][] newCells = new Cell[200][120];
for (int i = 0; i < newCells.length; i++)
{
for (int j = 0; j < newCells[0].length; j++)
{
newCells[i][j] = new Cell(i * 5, j * 5);
}
}
for (int i = 1; i < cells.length - 1; i++)
{
for (int j = 1; j < cells[0].length - 1; j++)
{
update(newCells, i, j);
}
}
cells = newCells; // update all cell states in one go
}
repaint();
try
{
Thread.sleep(125);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public void update(Cell[][] newCells, int i, int j)
{ // updating the cells into ALIVE/DEAD state
int[] neighbors = new int[8];
int sum = 0;
for (int index = 0; index < 8; index++)
neighbors[index] = 0;
if (cells[i - 1][j - 1].state == State.ALIVE)
neighbors[0] = 1;
if (cells[i][j - 1].state == State.ALIVE)
neighbors[1] = 1;
if (cells[i + 1][j - 1].state == State.ALIVE)
neighbors[2] = 1;
if (cells[i - 1][j].state == State.ALIVE)
neighbors[3] = 1;
if (cells[i + 1][j].state == State.ALIVE)
neighbors[4] = 1;
if (cells[i - 1][j + 1].state == State.ALIVE)
neighbors[5] = 1;
if (cells[i][j + 1].state == State.ALIVE)
neighbors[6] = 1;
if (cells[i + 1][j + 1].state == State.ALIVE)
neighbors[7] = 1;
for (int index = 0; index < 8; index++)
sum += neighbors[index];
if (cells[i][j].state == State.ALIVE)
{
if ((sum < 2 || sum > 3))
{
newCells[i][j].state = State.DEAD;
}
else // sum == 2 or 3
{
newCells[i][j].state = State.ALIVE;
}
}
else if (cells[i][j].state == State.DEAD)
{
if (sum == 3)
{
newCells[i][j].state = State.ALIVE;
}
}
}
@Override
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
Rectangle r;
for (int i = 0; i < cells.length; i++)
{
for (int j = 0; j < cells[0].length; j++)
{
if (cells[i][j].state == State.ALIVE)
{
r = cells[i][j].getCell();
g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(), (int) r.getHeight());
}
}
}
super.paint(g);
}
@Override
public void update(Graphics g)
{
if (image == null)
{
image = createImage(this.getWidth(), this.getHeight());
second = image.getGraphics();
}
second.setColor(getBackground());
second.fillRect(0, 0, getWidth(), getHeight());
second.setColor(getForeground());
paint(second);
g.drawImage(image, 0, 0, this);
}
@Override
public void mousePressed(MouseEvent e)
{
if (state == GameState.SETTING)
{
int x = e.getX() - e.getX() % 5;
int y = e.getY() - e.getY() % 5;
cells[x / 5][y / 5].born();
}
}
@Override
public void mouseEntered(MouseEvent e)
{
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e)
{
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e)
{
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e)
{
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SPACE)
{
if (state == GameState.START)
state = GameState.SETTING;
else
state = GameState.START;
}
}
@Override
public void keyReleased(KeyEvent arg0)
{
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent arg0)
{
// TODO Auto-generated method stub
}
}
Upvotes: 2