This site requires JavaScript, please enable it in your browser!
Greenfoot back
camsterb
camsterb wrote ...

2012/12/12

Probably Small Conway's Game of Life Problem...

camsterb camsterb

2012/12/12

#
Basic rules of demo for college: -Make living and dead cells in grid using arrays -If a given cell has 1 or >3 neighbours, it dies -If a dead cell has 3 neighbours, it is reborn -Cells with 2-3 neighbours continue living Here is my uploaded demo. http://www.greenfoot.org/scenarios/6977 I have simplified the input so that you just click with the mouse to add cells before running it. There is a little redundant source code for randomising the initial cells, so that can be ignored. From the world I check through a loop the number of neighbouring cells that are alive and then execute their change of state. If anyone is willing to have a look at my source code, that would be great. The application simply isn't running as seen in real working examples: http://www.greenfoot.org/scenarios/669 Maybe my cells aren't checking their neighbours properly? I'm really not sure. Additionally, here is the source code. I hate to be annoying and post it all, but I'm just not sure what's the problem.
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class life here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Life extends World
{
    Cell[] cell = new Cell[2500];
    int i;
    static final int width = 50;
    static final int height = 50;
    boolean start = false;
    
    public Life()
    {    
        super(50, 50, 10); 
        
    
        for(int y = 0; y < height; y++)
        {
            for(int x = 0; x < width; x++)
            {
                
                int random = Greenfoot.getRandomNumber(1);
                if(random == 0)
                { 
                    cell[(x+(y*width))] = new Cell(0);
                    addObject(cell[(x+(y*width))], (x), (y));
                }
                else if(random ==1)
                {
                    cell[(x+(y*width))] = new Cell(1);
                    addObject(cell[(x+(y*width))], (x), (y));
                }
            }
        }
    }
    public void act()
    {
        checkKeyPress();
        startSimulation();
    }
    private void checkKeyPress()
    {
        if(Greenfoot.isKeyDown("space"))
        {
            start = true;
        }
        if(Greenfoot.isKeyDown("x"))
        {
            start = false;
        }
    }
    private void startSimulation()
    {
        if(start==true)
        {
            for(int y = 0; y < height; y++)
            {
                for(int x = 0; x < width; x++)
                {
                        cell[(x+(y*width))].countAlive();
                }
            }
            for(int y = 0; y < height; y++)
            {
                for(int x = 0; x < width; x++)
                {
                        cell[(x+(y*width))].checkCounter();
                }
            }
        } 
    }
}


import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
import greenfoot.MouseInfo;
import java.util.*;
/**
 * Write a description of class Cell here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Cell extends Actor
{   
    public GreenfootImage img = new GreenfootImage(10,10);
    private boolean alive;
    int counter = 0;
    
    public Cell(int birth)
    {
        if(birth == 0)  
        {
            setImage(img);
            img.drawRect(10,10,1,1);
            alive = false;
        }
        else if(birth == 1)
        {
            setImage(img);
            img.fill();
            alive = true;
        }
        }
    
    public void act() 
    {
        mousePressed();
    }    
    
    private void mousePressed()
    {
        if(Greenfoot.mousePressed(this))
        {
            if(alive == true)
            {   
                makeDie();
            }
            else if(alive == false)
            {   
                makeBorn();
            }
        }
    }
    
    public void makeDie()
    {
        img.clear();
        alive = false;
    }
    
    public void makeBorn()
    {
        img.fill();
        alive = true;
    }
    
    public boolean getStatus(){
        return alive;
        }
        
    public void countAlive()
    {
        if (getX()>0 && getX()< getWorld().getWidth()-1 && getY()>0 && getY()< getWorld().getHeight()-1)
        {
            Cell temp = (Cell) getOneObjectAtOffset(1,0,Cell.class);
            if(temp.getStatus() == true)
            {
            counter++;
            }
        }
        if (getX()>0 && getX()< getWorld().getWidth()-1 && getY()>0 && getY() < getWorld().getHeight()-1)
        {
            Cell temp = (Cell) getOneObjectAtOffset(-1,0,Cell.class);
            if(temp.getStatus() == true)
            {
            counter++;
            }
        }
        if (getX()>0 && getX()< getWorld().getWidth()-1 && getY()>0 && getY() < getWorld().getHeight()-1)
        {
            Cell temp = (Cell) getOneObjectAtOffset(1,-1,Cell.class);
            if(temp.getStatus() == true)
            {
            counter++;
            }
        }
        if (getX()>0 && getX()< getWorld().getWidth()-1 && getY()>0 && getY() < getWorld().getHeight()-1)
        {
            Cell temp = (Cell) getOneObjectAtOffset(0,1,Cell.class);
            if(temp.getStatus() == true)
            {
            counter++;
            }
        }
        if (getX()>0 && getX()< getWorld().getWidth()-1 && getY()>0 && getY() < getWorld().getHeight()-1)
        {
            Cell temp = (Cell) getOneObjectAtOffset(0,-1,Cell.class);
            if(temp.getStatus() == true)
            {
            counter++;
            }
        }
        if (getX()>0 && getX()< getWorld().getWidth()-1 && getY()>0 && getY() < getWorld().getHeight()-1)
        {
            Cell temp = (Cell) getOneObjectAtOffset(-1,-1,Cell.class);
            if(temp.getStatus() == true)
            {
            counter++;
            }
        }
        if (getX()>0 && getX()< getWorld().getWidth()-1 && getY()>0 && getY() < getWorld().getHeight()-1)
        {
            Cell temp = (Cell) getOneObjectAtOffset(1,1,Cell.class);
            if(temp.getStatus() == true)
            {
            counter++;
            }
        }
        if (getX()>0 && getX()< getWorld().getWidth()-1 && getY()>0 && getY() < getWorld().getHeight()-1)
        {
            Cell temp = (Cell) getOneObjectAtOffset(-1,1,Cell.class);
            if(temp.getStatus() == true)
            {
            counter++;
            }
        }
    }
    public void checkCounter()
    {
        if(counter <2)
        {
            makeDie();
            counter = 0;
        }
        if(counter >3)
        {
            makeDie();
            counter = 0;
        }
        if(counter == 3)
        {
            makeBorn();
            counter = 0;
            
        }
    }
}
    
camsterb camsterb

2012/12/12

#
The big crazy paramaters for the if-statements in countAlive() in my Cell are just to make sure we don't bother with cells along the edge of the screen as they can return null values.
nccb nccb

2012/12/12

#
You are not resetting the counter to zero in the case where there are two neighbours alive. So if on frame 13, you have two alive neighbours, then on frame 14 you'll start counting your neighbours at two, and end up with the wrong count. This might have something to do with it? I'd just set counter = 0; at the start of the checkCounter method.
vonmeth vonmeth

2012/12/12

#
You can also reduce those large amount of 'if's down to a double 'for' loop, with two 'if' statements.
public void countAlive()  
    {  
		int x = getX();
		int y = getY();
		int worldWidth = getWorld().getWidth()-1;
		int worldHeight = getWorld().getHeight()-1;
		counter = 0; // remove counter = 0's from checkCounter
		
		for (int offX = -1; offX < 2; offX++)
			for (int offY = -1; offY < 2; offY++) {
				if ( !(offX == 0 && offY == 0) ) {
					if ( !(x+offX < 0 || x+offX > worldWidth || y+offY < 0 || y+offY > worldHeight) )  
					{
                                                if(((Cell) getOneObjectAtOffset(offX,offY,Cell.class)).getStatus() == true)    
						{  
						counter++;  
						}  
					}
				}
			}
    }  
I believe that should work correctly.
camsterb camsterb

2012/12/12

#
Excellent advice. Thank you both for the hard work. Extremely helpful.
kevv kevv

2013/1/8

#
vonmeth wrote...
You can also reduce those large amount of 'if's down to a double 'for' loop, with two 'if' statements.
public void countAlive()  
    {  
		int x = getX();
		int y = getY();
		int worldWidth = getWorld().getWidth()-1;
		int worldHeight = getWorld().getHeight()-1;
		counter = 0; // remove counter = 0's from checkCounter
		
		for (int offX = -1; offX < 2; offX++)
			for (int offY = -1; offY < 2; offY++) {
				if ( !(offX == 0 && offY == 0) ) {
					if ( !(x+offX < 0 || x+offX > worldWidth || y+offY < 0 || y+offY > worldHeight) )  
					{
                                                if(((Cell) getOneObjectAtOffset(offX,offY,Cell.class)).getStatus() == true)    
						{  
						counter++;  
						}  
					}
				}
			}
    }  
I believe that should work correctly.
Hi, could you please explain how the for loops work here. Why int -1 until smalles than 2?
davmac davmac

2013/1/8

#
It's not "until smaller than 2", it's "while smaller than 2". So the values are -1, 0, and 1.
kevv kevv

2013/1/8

#
Ok, but could you please explain how these two for loops work a little more?
danpost danpost

2013/1/8

#
From any cell, there are eight possible neighbours, they occur at offsets of
    (-1, -1)  ( 0, -1)  ( 1, -1)
    (-1,  0)            ( 1,  0)
    (-1,  1)  ( 0,  1)  ( 1,  1)
The x-offsets range from negative one to one; as do the y-offsets. The hole in the center is the current cell which is not a neighbour of itself. The first 'for' loop creates the values of the x-offsets and the second does the same for the y-offsets. The first 'if' eliminates self-neighbouring. The second one eliminates non-existent cells outside the world bounds. The last one checks the status of the cell and increments the counter if it is active (on/live).
You need to login to post a reply.