So, I've been working on this Game of Life (http://www.bitstorm.or g/gameoflife/) project, and all the code has been written. However, it will not run. First, I will post the error message and the fragment of code I think to be the cause of the problem. Then, I will post the code to all 3 of my java files in their entirety should you wish to reference them. Any help would be much appreciated.
Also, if it would help fix my error, I would like guidance as to make these cells live on a toroid, meaning that any cells that hit the bottom pop up at the top and any cells that hit the left edge come out on the right.
Here's the error message:
Here's the code fragment I believe to be the problem:
Here's my Cell.java File:
Here's my starter file, GameStart.java:
And finally, here's the class that handles the display, Display.java:
Thanks in advance for your help!
Also, if it would help fix my error, I would like guidance as to make these cells live on a toroid, meaning that any cells that hit the bottom pop up at the top and any cells that hit the left edge come out on the right.
Here's the error message:
Code:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1 at Cell.prepareNextTurn(Cell.java:82) at GameStart.runastep(GameStart.java:42) at Display.paint(Display.java:57) at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source) at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source) at java.awt.event.InvocationEvent.dispatch(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)
Here's the code fragment I believe to be the problem:
Code:
int[][] adjacent = {{1,1},{1,0},{0,1},{1,-1},{-1,1},{0,-1},{-1,0},{-1,-1}};
for(int i = 0; i < adjacent.length; i++)
{
//System.out.println("myX" + myX + " myY" + myY + " context" + context.length);
if(context[myY + adjacent[i][0]][myX + adjacent[i][1]].getAlive())
{
myNeighbors++;
}
Here's my Cell.java File:
Code:
import java.awt.Color;
import java.awt.Graphics;
/**
* @author administrator
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class Cell {
public static int cellCounter = 0; // Each time a new cell is created, this is incremented
private int myX, myY; // x,y position on grid
private boolean myAlive; // alive (true) or dead (false)
private int myNeighbors; // count of neighbors with respect to x,y
private boolean myAliveNextTurn; // Used for figuring out state in next iteration
private Color myColor; // Based on alive/dead rules
private final Color DEFAULT_ALIVE = Color.ORANGE;
private final Color DEFAULT_DEAD = Color.GRAY;
private Cell[][] context; // this is how we can check our neighbors!
public Cell(Cell[][] thegrid) {
// Object() is called by default
myAlive = false; // dead
myColor = Color.GRAY;
context = thegrid;
}
public Cell(int x, int y, boolean alive, Color color, Cell[][] thegrid) {
myAlive = alive;
myColor = color;
myX = x; myY = y;
cellCounter++;
context = thegrid;
}
public boolean getAlive() { return myAlive; }
public int getX() { return myX; }
public int getY() { return myY; }
public Color getColor() { return myColor; }
public void setAlive (boolean alive, Color color) {
myColor = color;
myAlive = alive;
}
public void setAlive (boolean alive) {
if (alive) {
setAlive(true, DEFAULT_ALIVE);
} else {
setAlive(false, DEFAULT_DEAD);
}
}
public void toggle(){
//System.out.println("ok, what do you want to happen to cell[" + myX +"][" + myY +"]?");
if(context[myY][myX].getAlive())
{
context[myY][myX].setAlive(false);
}
else
{
context[myY][myX].setAlive(true);
}
}
/**************this method has to check all the neighbors to
* count how many are living cells. Depending on the answer,
* and whether or not the cell is CURRENTLY alive, it will
* determine whether it will be alive or not NEXT turn
*/
public void prepareNextTurn()
{
//System.out.println("you need to fill this in!");
int[][] adjacent = {{1,1},{1,0},{0,1},{1,-1},{-1,1},{0,-1},{-1,0},{-1,-1}};
for(int i = 0; i < adjacent.length; i++)
{
//System.out.println("myX" + myX + " myY" + myY + " context" + context.length);
if(context[myY + adjacent[i][0]][myX + adjacent[i][1]].getAlive())
{
myNeighbors++;
}
}
System.out.println(myX);
System.out.println(myY);
if(context[myX][myY].getAlive())
{
if(myNeighbors < 2 || myNeighbors > 3)
{
context[myY-1][myX-1].toggle();
}
else
{
//stay alive
}
}
else
{
if(myNeighbors == 3)
{
context[myY][myX].toggle();
}
else
{
//stay dead
}
}
}
/**********************bookkeeping
* this method updates the turn,
*/
public void setNextTurn()
{
//System.out.println("you also need to fill this in!");
}
public void setColor (Color color) { myColor = color; }
/****maybe I should have the method for drawing a cell in the Display class!
but this is ok and needs no modification
**************/
public void draw (int x_offset, int y_offset, int width, int height, Graphics g) {
// I leave this understanding to the reader
int xleft = x_offset + 1 + (myX*(width+1));
int xright = x_offset + width + (myX*(width+1));
int ytop = y_offset + 1 + (myY*(height+1));
int ybottom = y_offset + height + (myY*(height+1));
Color temp = g.getColor();
g.setColor(myColor);
g.fillRect(xleft, ytop, width, height);
}
}
Code:
import java.awt.Color;
import javax.swing.JFrame;
import java.util.Random;
public class GameStart {
public static final int ROWS = 80, COLS = 100;
public static Cell[][] cell = new Cell[ROWS][COLS];
public static Display display = new Display(cell);
public static void main(String[] args) {
initialize();
// Bring up a JFrame with squares to represent the cells
display.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
display.setVisible(true);
}
public static void initialize() {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
cell[i][j] = new Cell(j, i, false, Color.GRAY, cell);
if (java.lang.Math.random() < 0.25){
cell[i][j].setAlive(true);
}
/*****one way to seed the Grid with some random data:
if (java.lang.Math.random() < 0.25){
cell[i][j].setAlive(true);
}
********************but you could do many other things, too! **/
}
}
System.out.println(Cell.cellCounter); // demonstrates use of a class variable
}
public static void runastep(){
//first run through grid calculating what next turn status will be
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
// what do you think should be here?
cell[i][j].prepareNextTurn();
}
}
//then go back and run grid, moving next turn status into place
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
//what do you think should be here?
cell[i][j].setNextTurn();
}
}
}
}
And finally, here's the class that handles the display, Display.java:
Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// Note that the JFrame is set up to listen for mouse clicks
// and mouse movement. To achieve this, the MouseListener and
// MousMotionListener interfaces are implemented and there is additional
// code in init() to attach those interfaces to the JFrame.
public class Display extends JFrame implements MouseListener, MouseMotionListener {
private final int DISPLAY_WIDTH = 750;
private final int DISPLAY_HEIGHT = 600;
private final int X_GRID_OFFSET = 25; // 10 pixels from left
private final int Y_GRID_OFFSET = 40; // 10 pixels from top
private final int CELL_WIDTH = 5;
private final int CELL_HEIGHT = 5;
private final Cell[][] myCell;
private StartButton startStop = new StartButton();
private boolean paintloop = false;
public Display(Cell[][] cell) {
myCell = cell;
init();
}
public void init() {
setBackground(Color.WHITE);
setSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
getContentPane().setLayout(null);
// Example of setting up a button.
// See the StartButton class nested below.
add(startStop);
startStop.setBounds(100,500,72,36);
startStop.setVisible(true);
addMouseListener(this);
addMouseMotionListener(this);
repaint();
}
public void paint(Graphics g) {
g.setColor(Color.BLACK);
drawGrid(g);
drawCells(g);
drawComponents(); // buttons, etc., go here
if (paintloop) {
try {
Thread.sleep(50); //you can change this value!
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//nextGeneration();
GameStart.runastep(); //this method will run one generation
repaint();
}
}
void drawComponents() {
startStop.repaint();
}
void drawGrid(Graphics g) {
for (int i = 0; i <= GameStart.ROWS; i++) {
g.drawLine(X_GRID_OFFSET,
Y_GRID_OFFSET + (i*(CELL_HEIGHT+1)),
X_GRID_OFFSET + GameStart.COLS*(CELL_WIDTH+1),
Y_GRID_OFFSET + (i*(CELL_HEIGHT+1)));
}
for (int i = 0; i <= GameStart.COLS; i++) {
g.drawLine(X_GRID_OFFSET + (i*(CELL_WIDTH+1)),
Y_GRID_OFFSET,
X_GRID_OFFSET + (i*(CELL_WIDTH+1)),
Y_GRID_OFFSET + GameStart.ROWS*(CELL_HEIGHT+1));
}
}
void drawCells(Graphics g) {
// Have each cell draw itself
for (int i = 0; i < GameStart.ROWS; i++) {
for (int j = 0; j < GameStart.COLS; j++) {
// The cell cannot know for certain the offsets nor the height
// and width; it has been set up to know its own position, so
// that need not be passed as an argument to the draw method
myCell[i][j].draw(X_GRID_OFFSET,Y_GRID_OFFSET,CELL_WIDTH,CELL_HEIGHT,g);
}
}
}
void painter() { repaint(); }
/*************************THIS IS AN INNER CLASS*************************
* that is, a class defined within a class, all it does is run the start
* button. When start is clicked, the "paintloop" variable in the
* Display object is set to true; when stop is clicked, it's set to false.
* when paintloop is true, the game will be running, when it's false
* it won't (and perhaps the board may be edited)
*/
class StartButton extends JButton implements ActionListener {
StartButton() {
super("Start");
addActionListener(this);
}
public void actionPerformed(ActionEvent arg0) {
if (this.getText().equals("Start")) {
paintloop = true;
setText("Stop");
} else {
paintloop = false;
setText("Start");
}
painter();
}
}
/*********************************************************
* Note that the Display is ALSO listening for mouse clicks!
* there is a MouseEvent class that contains information about
* MouseClicks; all we need to know is the locaton of the click
* IF IT HAPPENS WHEN THE START BUTTON HAS NOT BEEN PRESSED,
* THIS WILL ALLOW THE USER TO set cells to be ALIVE or DEAD
*/
public void mouseClicked(MouseEvent me) {
if (paintloop==false){
//CONVERTS THE LOCATION OF THE CLICK IN PIXELS TO THE
//CORRECT ROW AND COLUMN IN THE GRID
int x = (me.getX() - X_GRID_OFFSET-1)/(CELL_WIDTH+1);
int y = (me.getY() - Y_GRID_OFFSET - 1)/(CELL_HEIGHT+1);
//be sure the click is actually IN the grid
//to avoid ArrayIndexOutOfBounds Exception
if ((0<=x)&& (x< myCell.length)&& (0<=y)&&(y<myCell[0].length)){
myCell[y][x].toggle();
repaint();
}
//System.out.println("clicked on (" + x + ","+ y + ") element");
}
}
/*************************
* a MouseListener must include ALL the methods for the MouseListener
* interface; but we don't actually need to do anything for these:
*/
public void mouseEntered(MouseEvent arg0) { }
public void mouseExited(MouseEvent arg0) { }
public void mousePressed(MouseEvent arg0) { }
public void mouseReleased(MouseEvent arg0) { }
public void mouseDragged(MouseEvent arg0) { }
public void mouseMoved(MouseEvent arg0) { }
}
Thanks in advance for your help!
Comment