Reputation: 510
I was trying to create conway's game of live in java. I've no trouble with my code, but with the output of the game. The still lifes pattern work as expected, but all the moving sructures are ending up in something different.
For example: 1 is a living cell; 0 is a dead cell
On the wiki page there is an oscillator, the blinker. in my case it behaves like this:
I'm doing all the stuff in an applet, which i add to a jframe. Here's the applet code (ignore the german comments, unless you're german :P):
import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Canvas extends Applet implements MouseListener{
private static final long serialVersionUID = -9195952699213522986L;
private boolean[][] cells; //True lebt; false ist tod
private int cellWidth;
private int margin = 2;
private int step = 0;
private boolean isRunning = false;
public Canvas(int size, int cv){ //size = 50; cv = 10;
addMouseListener(this);
cells = new boolean[size][size];
cellWidth = cv;
//Zellen Füllen
for(int i = 0; i < cells.length; i++){
for(int j = 0; j < cells[0].length; j++){
cells[i][j] = false;
}
}
}
@Override
public void paint(Graphics g){
//Updaten
if(isRunning)
update();
//Hintergrund
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
//Punkte zeichnen
for(int i = 0; i < cells.length; i++){
for(int j = 0; j < cells[0].length; j++){
if(cells[i][j]){
g.setColor(Color.GREEN);
g.fillRect(i * cellWidth + margin, j * cellWidth + margin, cellWidth - margin, cellWidth - margin);
}
else if(!cells[i][j]){
g.setColor(new Color(0x222222));
g.fillRect(i * cellWidth + margin, j * cellWidth + margin, cellWidth - margin, cellWidth - margin);
}
}
}
repaint();
}
private void update(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Für jede Zelle Spielregeln anwenden ( siehe Wikipedia: http://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens )
//Wichtig:
//Die Matrix muss komplett bearbeitet und neu gespeichert werden, deswegen newCells
boolean[][] newCells = cells.clone();
for(int i = 0; i < cells.length; i++){
for(int j = 0; j < cells[0].length; j++){
//Nachbarn
int neighbors = countNeighbors(i, j);
//Lebende Zelle
if(cells[i][j]){
//Einsamkeit
if(neighbors < 2){
newCells[i][j] = false;
}
//Überbevölkerung
else if(neighbors > 3){
newCells[i][j] = false;
}
//alles ok
else if(neighbors == 2 || neighbors == 3){
newCells[i][j] = true;
}
}
//Tote Zelle
else if(!cells[i][j]){
//Neue Zellen wird geboren
if(neighbors == 3){
newCells[i][j] = true;
}
}
}
}
cells = newCells;
System.out.println("Step #" + (++step));
}
private int countNeighbors(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(x == i && y == j) //Dieselbe Zelle
continue;
try{
if(cells[i][j])
neighbors++;
} catch(java.lang.ArrayIndexOutOfBoundsException e){
}
}
}
return neighbors;
}
//Double Buffering
@Override
public void update(Graphics g){
Graphics offgc;
Image offscreen = null;
Dimension d = getSize();
// create the offscreen buffer and associated Graphics
offscreen = createImage(d.width, d.height);
offgc = offscreen.getGraphics();
// clear the exposed area
offgc.setColor(getBackground());
offgc.fillRect(0, 0, d.width, d.height);
offgc.setColor(getForeground());
// do normal redraw
paint(offgc);
// transfer offscreen to window
g.drawImage(offscreen, 0, 0, this);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@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 mousePressed(MouseEvent e) {
if(e.isMetaDown()){
isRunning = !isRunning;
}
else if(!isRunning){
int x = e.getX() / cellWidth;
int y = e.getY() / cellWidth;
cells[x][y] = !cells[x][y];
}
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
Upvotes: 0
Views: 1634
Reputation: 24895
It is a complex algorithm so I can't ensure you that it will work after this, but the rest of the code looks ok.
boolean[][] newCells = cells.clone();
Ok, clone() performs a shadow copy which works well for primitives. But it does not work for a bidimensional array (which acts as a onedimensional array of onedimensional arrays). So, you have still a shallow copy.
After doing that, you are really overwritting the old array before all the calculations are over. For static situations (no new pixels die/live), it is ok because new and old array are expected to be the same, for the others cases you find the error.
Upvotes: 3