Question: GameOfLife Java Code: could someone help me find the bug in my code? the issue is that in the next generation I only kill cells

GameOfLife Java Code:

could someone help me find the bug in my code? the issue is that in the next generation I only kill cells when I should be making some cells alive. Whenever a dead cell has 3 neighbors it becomes alive in the next generation. I end up kelling all of my cells.

I bolded the methods that deal with next generation

//TODO: file header

import java.util.Random; import java.util.Scanner;

//TODO: class header public class GameOfLife {

// global variables private static boolean first = true; static String line;

// TODO: method header public static void main(String[] args) {

Scanner scnr = new Scanner(System.in); boolean[][] World = new boolean[Config.WORLD_ROWS][Config.WORLD_COLUMNS]; System.out.println("Welcome to Conway's Game Of Life"); System.out.println("--------------------------------"); System.out.println("1)Glider 2)Beacon 3)Beehive 4)R-pentomino"); System.out.println("5)Random 6)Custom or 7)Exit"); System.out.print("Choose a pattern: ");

int Generation = 0; String Line = ""; int choice = 0; while (scnr.hasNextLine()) { if (scnr.hasNextInt() || GameOfLife.first) { choice = getIntChoice(scnr, 1, 7); } else if (!GameOfLife.first) { runSimulation(scnr, World); System.out.println("1)Glider 2)Beacon 3)Beehive 4)R-pentomino"); System.out.println("5)Random 6)Custom or 7)Exit"); System.out.print("Choose a pattern: "); choice = getIntChoice(scnr, 1, 7); }

if (choice == 1) { clearWorld(World); System.out.println(""); Generation = 0; System.out.println("Generation: " + Generation); initializeGliderWorld(World); }

else if (choice == 2) { clearWorld(World); System.out.println(""); Generation = 0; System.out.println("Generation: " + Generation); initializeBeaconWorld(World);

}

else if (choice == 3) { clearWorld(World); System.out.println(""); Generation = 0; System.out.println("Generation: " + Generation); initializeBeehiveWorld(World); } else if (choice == 4) { clearWorld(World); System.out.println(""); Generation = 0; System.out.println("Generation: " + Generation); initializeRpentominoWorld(World); } else if (choice == 5) { clearWorld(World); System.out.println(""); Generation = 0; System.out.println("Generation: " + Generation); initializeRandomWorld(World); } else if (choice == 6) { System.out.println( "Enter a pattern using " + Config.ALIVE + " for alive and " + Config.DEAD + " as dead cells."); System.out.println("To end the pattern, type END on its own line."); scnr.nextLine(); initializeCustomWorld(scnr, World); System.out.println(""); Generation = 0; System.out.println("Generation: " + Generation);

} else if (choice == 7) { System.out.println("----------------------------"); System.out.println("End of Conway's Game Of Life"); return; }

printWorld(World);

System.out.print("Press Enter for next generation, 'end' to stop: "); Line = scnr.nextLine().trim(); continue; } }

/** * Prints out the world showing each cell as alive or dead. * * Loops through every cell of the world. If a cell is alive, print out the * Config.ALIVE character, otherwise print out the Config.DEAD character. * * Counts how many cells are alive and prints out the number of cells alive. * For 2 or more cells alive, for 1 cell alive and 0 cells alive the * following messages are printed: 5 cells are alive. 1 cell is alive. No * cells are alive. * * @param world * The array representation of the current world. */ public static void printWorld(boolean[][] world) { int count = 0; for (int i = 0; i < Config.WORLD_ROWS; i++) { for (int j = 0; j < Config.WORLD_COLUMNS; j++) { if (world[i][j]) { count++; System.out.print(Config.ALIVE); }

else { System.out.print(Config.DEAD); } } System.out.println(""); } if (count == 0) { System.out.println("No cells are alive."); }

if (count == 1) { System.out.println("1 cell is alive.");

}

else { System.out.println(count + " cells are alive."); }

}

/** * This method clears the world by setting all the cells in the world to * false (dead). This method uses array lengths, not constants, to determine * the size of the world. * * @param world * the world to clear */ public static void clearWorld(boolean[][] world) {

for (int i = 0; i < world.length; i++) { for (int j = 0; j < world[i].length; j++) { world[i][j] = false; } } }

/** * This method expects an integer to be entered by the user between and * including the values of min and max. If the value entered is not an * integer or is an integer but less than min or greater than max the * following message is displayed: Enter a number between 1 and 5: Assuming * that min was 1 and max was 5 when this method was called. * * @param input * The Scanner instance for reading from System.in. * @param min * The minimum acceptable integer. * @param max * The maximum acceptable integer. * @return An integer between and including min and max. */ public static int getIntChoice(Scanner input, int min, int max) { int returnValue = 0; while (true) { if (!(input.hasNextInt())) { System.out.print("Enter a number between " + min + " and " + max + ": "); input.nextLine(); continue; } int Pattern = input.nextInt(); if (Pattern > max || Pattern < min) { System.out.print("Enter a number between " + min + " and " + max + ": "); input.nextLine(); continue; }

returnValue = Pattern; GameOfLife.first = false; return returnValue;

} }

/** * Initializes the world to the Glider pattern. * *

 * .......... * .@........ * ..@@...... * .@@....... * .......... * .......... * .......... * .......... * 

* * The world may have any pattern within it when passed into this method. * After this method call, the only living cells in the world is the Glider * pattern as shown. * * @param world * the existing double dimension array that will be reinitialized * to the Glider pattern. */ public static void initializeGliderWorld(boolean[][] world) { for (int i = 0; i < world.length; i++) { for (int j = 0; j < world[i].length; j++) { if (i == 1 && j == 1) { world[i][j] = true; } else if (i == 2 && j == 2) { world[i][j] = true; } else if (i == 2 && j == 3) { world[i][j] = true; } else if (i == 3 && j == 1) { world[i][j] = true; } else if (i == 3 && j == 2) { world[i][j] = true; } else { world[i][j] = false; } } }

}

/** * Initializes the world to the Beacon pattern. * *

 * .......... * .@@....... * .@........ * ....@..... * ...@@..... * .......... * .......... * .......... * 

* * The world may have any pattern within it when passed into this method. * After this method call, the only living cells in the world is the Beacon * pattern as shown. * * @param world * the existing 2-dimension array that will be reinitialized to * the Beacon pattern. */ public static void initializeBeaconWorld(boolean[][] world) {

world[1][1] = true; world[1][2] = true; world[2][1] = true; world[3][4] = true; world[4][3] = true; world[4][4] = true;

}

/** * Initializes the world to the Beehive pattern. * *

 * .......... * ..@@...... * .@..@..... * ..@@...... * .......... * .......... * .......... * .......... * 

* * The world may have any pattern within it when passed into this method. * After this method call, the only living cells in the world is the Beehive * pattern as shown. * * @param world * the existing double dimension array that will be reinitialized * to the Beehive pattern. */ public static void initializeBeehiveWorld(boolean[][] world) {

world[1][2] = true; world[1][3] = true; world[2][1] = true; world[2][4] = true; world[3][2] = true; world[3][3] = true;

}

/** * Initializes the world to the R-pentomino pattern. * *

 * .......... * ..@@...... * .@@....... * ..@....... * .......... * .......... * .......... * .......... * 

* * The world may have any pattern within it when passed into this method. * After this method call, the only living cells in the world is the * R-pentomino pattern as shown. * * @param world * the existing double dimension array that will be reinitialized * to the R-pentomino pattern. */ public static void initializeRpentominoWorld(boolean[][] world) {

world[1][2] = true; world[1][3] = true; world[2][1] = true; world[2][2] = true; world[3][2] = true;

}

/** * Initialize the GameOfLife world with a random selection of cells alive. * * For testing purposes, implementations should use the Config.CHANCE_ALIVE * constant and Config.SEED. Create an instance of the java.util.Random * class, setting the seed to the SEED constant. For each cell, if the * returned value of the nextDouble() method is less than * Config.CHANCE_ALIVE then the cell is alive. * * @param world * the existing double dimension array that will be reinitialized * to a Random pattern. */ public static void initializeRandomWorld(boolean[][] world) {

Random rand = new Random(Config.SEED); for (int i = 0; i < Config.WORLD_ROWS; i++) { for (int j = 0; j < Config.WORLD_COLUMNS; j++) { double num = rand.nextDouble(); if (num < Config.CHANCE_ALIVE) { world[i][j] = true; } else { world[i][j] = false; } } }

}

/** * Prompt for a pattern of cells. Each line of input corresponds to one row * in the world. Continue reading lines until 'END' is entered on a line of * its own. Ignore case and leading and trailing spaces when comparing to * 'END'. (See String methods such as trim() method.) * * The maximum size is the size of the world passed into this method. Any * additional characters typed by the user are ignored. When interpreting * the characters typed in, only the Config.ALIVE character is used to * determine which cells are alive. All other characters are interpreted as * dead cells. * * @param input * The Scanner instance that reads from System.in. * @param world * The world array that is filled with the pattern the user * enters. */ public static void initializeCustomWorld(Scanner input, boolean[][] world) { line = input.nextLine(); clearWorld(world); int j = 0; int k = 0; while (!line.equalsIgnoreCase("end")) { for (int i = 0; i < line.length(); i++) { if (i >= world[0].length) { break; } if (line.charAt(i) == Config.ALIVE) { world[j][k] = true; k++; continue; } k++;

} line = input.nextLine(); j++; k = 0; } if (world[0][0]) { } }

/** * Checks whether a specific cell is alive or dead. * * Note that cellRow and cellColumn may not be valid indexes into the world * array. Return false for any cell outside the world array. Checks the * values of cellRow and cellColumn to make sure they are valid prior to * looking in the world array. Does not use try-catch blocks or other * exception handling mechanisms. * * @param world * The current world. * @param cellRow * The row of the cell which we are wanting to know whether it is * alive. * @param cellColumn * The column of the cell which we are wanting to know whether it * is alive. * * @return Whether the specified cell is alive. */ public static boolean isCellAlive(boolean[][] world, int cellRow, int cellColumn) {

if (cellRow < 0 || cellRow > world.length) { return false; } if (cellColumn < 0 || cellColumn > world[0].length) { return false; }

return world[cellRow][cellColumn]; }

/** * Counts the number of neighbors that are currently living around the * specified cell. * * A cell has eight neighbors. The neighbors are the cells that are * horizontally, vertically and diagonally adjacent. * * Calls the isCellAlive method to determine whether any specific cell is * alive. * * @param world * The current world. * @param row * The row of the cell for which we are looking for living * neighbors. * @param column * The column of the cell for which we are looking for living * neighbors. * * @return The number of neighbor cells that are currently living. */ public static int numNeighborsAlive(boolean[][] world, int row, int column) { if (row >= 0 && row < world.length && column >= 0 && column < world[0].length) { int count = 0; for (int i = row - 1; i <= row + 1; i++) { if (i >= 0 && i < world.length) { for (int j = column - 1; j <= column + 1; j++) { if (j >= 0 && j < world[i].length) if (i != row || j != column) if (isCellAlive(world, i, j)) count++; } } }

return count; } return -1;

}

/** * Whether a cell is living in the next generation of the game. * * The rules of the game are as follows: 1) Any live cell with fewer than * two live neighbors dies, as if caused by under-population. 2) Any live * cell with two or three live neighbors lives on to the next generation. 3) * Any live cell with more than three live neighbors dies, as if by * overcrowding. 4) Any dead cell with exactly three live neighbors becomes * a live cell, as if by reproduction. * * @param numLivingNeighbors * The number of neighbors that are currently living. * @param cellCurrentlyLiving * Whether the cell is currently living. * * @return true if this cell is living in the next generation, otherwise * false. */ public static boolean isCellLivingInNextGeneration(int numLivingNeighbors, boolean cellCurrentlyLiving) { boolean retval = false; if (cellCurrentlyLiving) { if (numLivingNeighbors == 2 || numLivingNeighbors == 3) retval = true; else if (numLivingNeighbors == 3) retval = true; }

return retval; }

/** * Determines the cells living in the next generation of the world. The next * generation is created by applying the 4 rules simultaneously to every * cell in the previous generation. Births and deaths occur simultaneously. * In other words, look only at whether cells are living in the current * generation to determine whether a cell lives in the new generation. Don't * look at other cells in the new generation. * * For each cell in the current generation, determine whether the cell at * the same coordinates is living in the next generation using the * numNeighborsAlive and the isCellLivingInNextGeneration methods. * * @param currentWorld * The world currently shown. * @param newWorld * The new world based on the rules of life. */ public static void nextGeneration(boolean[][] currentWorld, boolean[][] newWorld) {

for (int i = 0; i < currentWorld.length; i++) { for (int j = 0; j < currentWorld[i].length; j++) {

int num = numNeighborsAlive(currentWorld, i, j);

newWorld[i][j] = isCellLivingInNextGeneration(num, currentWorld[i][j]); } }

for (int i = 0; i < currentWorld.length; i++) { for (int j = 0; j < currentWorld[i].length; j++) { currentWorld[i][j] = newWorld[i][j]; } } }

/** * This shows each generation of the simulation starting with generation 0. * The display of the world is by calling the printWorld method and then * prompting the user for whether to calculate and show the next generation. * Then, for any input other then 'end', this calculates the next generation * using the nextGeneration method and shows it. Any case of 'end' is * acceptable, and also ignore leading and trailing whitespace. (See String * trim() method.) * * Note that any number of generations are possible to implement with only * the world passed as the parameter and one other 2-dimensional array the * same size. Create the second world the same size as the world passed in, * by using the length attributes rather than using constant values. The * world passed in will be rectangular and not irregular. * * @param input * The Scanner object used to read from System.in. * @param world * The initialized world to show as generation 0. */ public static void runSimulation(Scanner input, boolean[][] world) { int Generation = 1; boolean[][] array = new boolean[world.length][world[0].length]; String line = input.nextLine().trim(); while (!line.equalsIgnoreCase("end")) { nextGeneration(world, array); System.out.println(""); System.out.println("Generation: " + Generation); printWorld(array); world = array; Generation++; line = input.nextLine().trim(); } return; }

}

Config Class:

import java.util.Random;

/** * Contains constants used by GameOfLife. * * Constants that are defined here must be used by name because we may * change these values to ensure that your program works with any * values. * * @author Jim Williams jimw@cs.wisc.edu */ public class Config { /** * The number of rows and columns of cells in the world. * * For full credit, use these named constants to create the world array * in GameOfLife.java rather than integer values such as 8 and 10. * A programmer should be able to change the number of rows and columns * in this file and, without any other changes, the world size should * change and the program should work correctly. * * For testing, we may set WORLD_ROWS and WORLD_COLUMNS to any value * between and including, 5 and 80. */ public static final int WORLD_ROWS = 10; public static final int WORLD_COLUMNS = 20; /** * The character displayed in the world if that cell is alive. */ public static final char ALIVE = '&'; /** * The character displayed in the world if that cell is dead. */ public static final char DEAD = '_'; /** Used to seed the java.util.Random object for generating * random numbers used by the initializeRandomWorld method. * By seeding the Random generator, we can predict * the "pseudo-random" values that will be generated. * This predictability aids in program development * and allows for automated grading. */ public static final int SEED = 234; /** CHANCE_ALIVE is used in the initializeRandomWorld method to * initialize the cells that are alive in the initial generation. * For example a value of 0.25 means about 25% of the cells should * be alive. */ public static final double CHANCE_ALIVE = 0.20; }

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!