We help IT Professionals succeed at work.

The game of Life - problems with output result

manefist
manefist asked
on
Hello everyone, I am trying to write a simple program which emulate the game of life following four different rules which decide in the next generation the status (dead/alive) of a cell.
These are the rule:

F = filled cell
E = empty cell

1. if F < 2 OR F > 3 the cell in the next generation die
2. if F = 2 OR F = 3 the cell in the next generation live
3. if E = 3 the cell in the next generation live

Now, I want to try with this file:

* * *

The expected output should be:

*
*
*
However my result is:

*
*


*
My output is wrong for some reason that I cannot really understand, I am stuck to this point for days, I will really appreciate if someone has an useful suggestion to share.

import java.util.Scanner;
import java.io.*;

class LifeGrid
{
	private int[][] grid, newGrid;
	private int generation = 0;

	public LifeGrid(int x, int y, String filename) throws FileNotFoundException 
	{ 
		grid = new int[x][y];
		newGrid = new int[x][y];

		int j = 0;
		
		Scanner scanner = new Scanner(new File(filename));

		while(scanner.hasNextLine() && j < x)
		{
			String line = scanner.nextLine();

			for(int i=0; i<line.length() && i<y; i++)
			{
				if(line.charAt(i) == '*')
					grid[j][i] = 1;
				else
					grid[j][i] = 0;
			}
			j++;
		}
		scanner.close();
	}

	public void show()
	{

		for(int i=0; i<grid.length; i++)
		{
			for(int j=0; j<grid[i].length; j++)
			{
				if(grid[i][j] == 1)
					System.out.print("*");
				else
					System.out.print(" "); 
			}
			System.out.println();			
		}
		System.out.println("Generation:" + generation);
	}

	//Getter methods

	public int getWidth()	    	  { return grid[0].length;  }
	public int getHeight()      	  { return grid.length;     }
	public int getGeneration()  	  { return this.generation; }
	public int getCell(int x, int y)  { return grid[x][y]; 	    }


	public static void main(String[] args)throws FileNotFoundException 
	{
		LifeGrid life = new LifeGrid(6, 10, args[0]);
		life.run(); 
    	}

	//Check neighbours
	
	public int neighbours(int x, int y)
	{
		int neighbours = 0;

		int top = (y > 0 ? y-1: getWidth()-1);
		int btm = (y < getWidth()-1 ? y+1: 0);
		int left = (x > 0 ? x-1: getHeight()-1);
		int right = (x < getHeight()-1 ? x+1: 0);

		if(grid[x][top] == 1)		{neighbours++;}
		if(grid[x][btm] == 1)		{neighbours++;}	
		if(grid[left][top]== 1)		{neighbours++;}
		if(grid[left][btm] == 1)	{neighbours++;}	
		if(grid[left][y] == 1)		{neighbours++;}
		if(grid[right][y] == 1)		{neighbours++;}
		if(grid[right][top] == 1)	{neighbours++;}
		if(grid[right][btm] == 1)	{neighbours++;}

		return neighbours;
	}
	public void run()
	{
		int n;

		for(int i=0; i<grid.length; i++)
		{
			for(int j=0; j<grid[i].length; j++)
			{
				n = neighbours(i,j);

				if(grid[i][j] == 1)
				{
					if(n < 2 || n > 3)				{generation = 0;}
					if(n == 2 || n == 3)				{generation = 1;}
				}
				else 
				{
					if(n == 3)					{generation = 1;}
					else						{generation = 0;}
				}

				newGrid[i][j] = generation;
			}
		}
		grid = newGrid.clone();
		show();

	}
}

Open in new window

Comment
Watch Question

I think your program works and your expectations are incorrect.

You are expecting life on the 3rd row when there was no life on the 2nd row to make that life.

I also think your output would be easier to read if you replaced   System.out.print(" ");  with   System.out.print("-");

You also have this code.

if(grid[i][j] == 1)
				{
					if(n < 2 || n > 3)				{generation = 0;}
					if(n == 2 || n == 3)				{generation = 1;}
				}

Open in new window


I don't like the formatting but that's your call.  However the 2nd if statement is really an else and, IMHO, should be called else.  If someone comes along and changes the first if to    if(n < 2 || n > 4 ) but doesn't change the second if, then generation won't have been set by the method.  Instead it will retain the previous value which might not be what you want.
Thinking further, I think I see what is confusing.  Remember how I want to use - instead of space?  Perhaps you meant for a file like this

--------
***-----
--------
--------
--------
--------
--------
--------

Open in new window


Instead of

***-----
--------
--------
--------
--------
--------
--------
--------

Open in new window


The first file produces the output you expected.  The second file produces the output you got.

Author

Commented:
Thank you very much, so from your point of view it was just the file format to be wrong??
However if I try with a different file like this:
 
 ******
   *****
 
 *****
I will get as output:

****    
 **      
 *    *  
         
  ***    
  ***  
I do not think it is correct, do you?
I can't tell because the spaces are invisible.  Could you give a file with dashes so I can see what's actually in the file?

I already ran a test on your program, using dashes instead of spaces in the input file and it worked.

Author

Commented:
Ok this is the output with dashes:
----------
******----
---*****--
----------
-*****----
----------
Generation:0
-****-----
-**-------
-*----*---
----------
--***-----
--***-----
Generation:0
It would help to  know what you don't think is correct.  I could have missed something but I think it is correct except for the first  and last rows.  I think this is correct but I may have missed something.
******----
-**-------
-*----*---
----------
--***-----
-*****----

Open in new window


Do we agree on what the grid should look like?

The method that calculates neighbors appears to be correct.  That's what I've figured out so far.
I think I might have done that wrong.  Still, the neighbor calculation appears correct.
I'm back to the program being correct.  I forgot that neighbors had to be 3 if the cell was empty.  Here's my debugging run.  
The fields are row,column,neighbors, F/E for Full/Empty and 1/0 for if a * should print or not.

If you believe any cell is incorrect, please identify that cell by row/column and I'll look into it.

----------
******----
---*****--
----------
-*****----
----------
Generation:0
0, 0 = 2 E -> 0
0, 1 = 3 E -> 1
0, 2 = 3 E -> 1
0, 3 = 3 E -> 1
0, 4 = 3 E -> 1
0, 5 = 2 E -> 0
0, 6 = 1 E -> 0
0, 7 = 0 E -> 0
0, 8 = 0 E -> 0
0, 9 = 1 E -> 0
1, 0 = 1 F -> 0
1, 1 = 2 F -> 1
1, 2 = 3 F -> 1
1, 3 = 4 F -> 0
1, 4 = 5 F -> 0
1, 5 = 4 F -> 0
1, 6 = 4 E -> 0
1, 7 = 2 E -> 0
1, 8 = 1 E -> 0
1, 9 = 1 E -> 0
2, 0 = 2 E -> 0
2, 1 = 3 E -> 1
2, 2 = 4 E -> 0
2, 3 = 4 F -> 0
2, 4 = 5 F -> 0
2, 5 = 4 F -> 0
2, 6 = 3 F -> 1
2, 7 = 1 F -> 0
2, 8 = 1 E -> 0
2, 9 = 1 E -> 0
3, 0 = 1 E -> 0
3, 1 = 2 E -> 0
3, 2 = 4 E -> 0
3, 3 = 5 E -> 0
3, 4 = 6 E -> 0
3, 5 = 5 E -> 0
3, 6 = 4 E -> 0
3, 7 = 2 E -> 0
3, 8 = 1 E -> 0
3, 9 = 0 E -> 0
4, 0 = 1 E -> 0
4, 1 = 1 F -> 0
4, 2 = 2 F -> 1
4, 3 = 2 F -> 1
4, 4 = 2 F -> 1
4, 5 = 1 F -> 0
4, 6 = 1 E -> 0
4, 7 = 0 E -> 0
4, 8 = 0 E -> 0
4, 9 = 0 E -> 0
5, 0 = 1 E -> 0
5, 1 = 2 E -> 0
5, 2 = 3 E -> 1
5, 3 = 3 E -> 1
5, 4 = 3 E -> 1
5, 5 = 2 E -> 0
5, 6 = 1 E -> 0
5, 7 = 0 E -> 0
5, 8 = 0 E -> 0
5, 9 = 0 E -> 0
-****-----
-**-------
-*----*---
----------
--***-----
--***-----
Generation:0

Open in new window


Author

Commented:
You are definitely right.

Thank you for your solution, you opened my blind eyes ;)
Glad I could help.  Would it help to see your program with my changes - mostly adding debugging statements?  I cleaned up an if/if that I think should have been an if/else too.
Actually, here's the key change I made that allowed me to figure out that it worked.  I used the System.out.println() method to track the state of n & generation through the loops.

                                          generation = 0;
                                        }
                                }

                                System.out.println ( i + ", " + j + " = " + n + " " + full + " -> " + generation );
                                newGrid[i][j] = generation;

Open in new window