By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,993 Members | 1,947 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,993 IT Pros & Developers. It's quick & easy.

Game of Life. I've isolated where the problem is

P: 16
So, I've been working on this Game of Life (http://www.bitstorm.org/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:
Expand|Select|Wrap|Line Numbers
  1. Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
  2.     at Cell.prepareNextTurn(Cell.java:82)
  3.     at GameStart.runastep(GameStart.java:42)
  4.     at Display.paint(Display.java:57)
  5.     at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
  6.     at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
  7.     at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
  8.     at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
  9.     at java.awt.event.InvocationEvent.dispatch(Unknown Source)
  10.     at java.awt.EventQueue.dispatchEvent(Unknown Source)
  11.     at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
  12.     at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
  13.     at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
  14.     at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
  15.     at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
  16.     at java.awt.EventDispatchThread.run(Unknown Source)

Here's the code fragment I believe to be the problem:
Expand|Select|Wrap|Line Numbers
  1.         int[][] adjacent = {{1,1},{1,0},{0,1},{1,-1},{-1,1},{0,-1},{-1,0},{-1,-1}};
  2.  
  3.         for(int i = 0; i < adjacent.length; i++)
  4.         {
  5.             //System.out.println("myX" + myX + " myY" + myY + " context" + context.length);
  6.             if(context[myY + adjacent[i][0]][myX + adjacent[i][1]].getAlive())
  7.             {
  8.                 myNeighbors++;
  9.             }

Here's my Cell.java File:

Expand|Select|Wrap|Line Numbers
  1. import java.awt.Color;
  2. import java.awt.Graphics;
  3.  
  4. /**
  5.  * @author administrator
  6.  *
  7.  * TODO To change the template for this generated type comment go to
  8.  * Window - Preferences - Java - Code Style - Code Templates
  9.  */
  10. public class Cell {
  11.     public static int cellCounter = 0;    // Each time a new cell is created, this is incremented
  12.     private int myX, myY;        // x,y position on grid
  13.     private boolean myAlive;    // alive (true) or dead (false)
  14.     private int myNeighbors;    // count of neighbors with respect to x,y
  15.     private boolean myAliveNextTurn;    // Used for figuring out state in next iteration
  16.     private Color myColor;        // Based on alive/dead rules
  17.     private final Color DEFAULT_ALIVE = Color.ORANGE;
  18.     private final Color DEFAULT_DEAD = Color.GRAY;
  19.     private Cell[][] context; // this is how we can check our neighbors!
  20.  
  21.     public Cell(Cell[][] thegrid) {
  22.         // Object() is called by default
  23.         myAlive = false; // dead
  24.         myColor = Color.GRAY;
  25.         context = thegrid;
  26.     }
  27.  
  28.     public Cell(int x, int y, boolean alive, Color color, Cell[][] thegrid) {
  29.         myAlive = alive;
  30.         myColor = color;
  31.         myX = x;  myY = y;
  32.         cellCounter++;
  33.         context = thegrid;
  34.     }
  35.  
  36.     public boolean getAlive() { return myAlive; }
  37.     public int getX() { return myX; }
  38.     public int getY() { return myY; }
  39.     public Color getColor() { return myColor; }
  40.  
  41.  
  42.     public void setAlive (boolean alive, Color color) {
  43.         myColor = color;
  44.         myAlive = alive;
  45.     }
  46.  
  47.     public void setAlive (boolean alive) { 
  48.         if (alive) {
  49.             setAlive(true, DEFAULT_ALIVE);
  50.         } else {
  51.             setAlive(false, DEFAULT_DEAD);
  52.         }
  53.     }
  54.  
  55.     public void toggle(){
  56.       //System.out.println("ok, what do you want to happen to cell[" + myX +"][" + myY +"]?");
  57.         if(context[myY][myX].getAlive())
  58.         {
  59.             context[myY][myX].setAlive(false);
  60.         }
  61.         else
  62.         {
  63.             context[myY][myX].setAlive(true);
  64.         }
  65.     }
  66.  
  67.  
  68.     /**************this method has to check all the neighbors to 
  69.      * count how many are living cells. Depending on the answer,
  70.      * and whether or not the cell is CURRENTLY alive, it will
  71.      * determine whether it will be alive or not NEXT turn
  72.      */
  73.  
  74.     public void prepareNextTurn()
  75.     {
  76.         //System.out.println("you need to fill this in!");
  77.         int[][] adjacent = {{1,1},{1,0},{0,1},{1,-1},{-1,1},{0,-1},{-1,0},{-1,-1}};
  78.  
  79.         for(int i = 0; i < adjacent.length; i++)
  80.         {
  81.             //System.out.println("myX" + myX + " myY" + myY + " context" + context.length);
  82.             if(context[myY + adjacent[i][0]][myX + adjacent[i][1]].getAlive())
  83.             {
  84.                 myNeighbors++;
  85.             }
  86.         }
  87.         System.out.println(myX);
  88.         System.out.println(myY);
  89.         if(context[myX][myY].getAlive())
  90.         {
  91.             if(myNeighbors < 2 || myNeighbors > 3)
  92.             {
  93.                 context[myY-1][myX-1].toggle();
  94.             }
  95.             else
  96.             {
  97.                 //stay alive
  98.             }
  99.         }
  100.         else
  101.         {
  102.             if(myNeighbors == 3)
  103.             {
  104.                 context[myY][myX].toggle();
  105.             }
  106.             else
  107.             {
  108.                 //stay dead
  109.             }
  110.         }
  111.     }
  112.  
  113.  
  114.     /**********************bookkeeping
  115.      * this method updates the turn,
  116.      */
  117.  
  118.     public void setNextTurn()
  119.     {
  120.         //System.out.println("you also need to fill this in!");
  121.  
  122.     }
  123.  
  124.  
  125.  
  126.     public void setColor (Color color) { myColor = color; }
  127.  
  128.  
  129.     /****maybe I should have the method for drawing a cell in the Display class!
  130.        but this is ok and needs no modification 
  131.        **************/
  132.  
  133.     public void draw (int x_offset, int y_offset, int width, int height, Graphics g) {
  134.         // I leave this understanding to the reader
  135.         int xleft = x_offset + 1 + (myX*(width+1));
  136.         int xright = x_offset + width + (myX*(width+1));
  137.         int ytop = y_offset + 1 + (myY*(height+1));
  138.         int ybottom = y_offset + height + (myY*(height+1));
  139.         Color temp = g.getColor();
  140.  
  141.         g.setColor(myColor);
  142.         g.fillRect(xleft, ytop, width, height);
  143.             }
  144. }
Here's my starter file, GameStart.java:

Expand|Select|Wrap|Line Numbers
  1. import java.awt.Color;
  2. import javax.swing.JFrame;
  3. import java.util.Random;
  4.  
  5. public class GameStart {
  6.     public static final int ROWS = 80, COLS = 100;
  7.     public static Cell[][] cell = new Cell[ROWS][COLS];
  8.     public static Display display = new Display(cell);
  9.  
  10.     public static void main(String[] args) {
  11.         initialize();
  12.         // Bring up a JFrame with squares to represent the cells
  13.         display.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  14.         display.setVisible(true);
  15.     }
  16.  
  17.     public static void initialize() {
  18.         for (int i = 0; i < ROWS; i++) {
  19.             for (int j = 0; j < COLS; j++) {
  20.                 cell[i][j] = new Cell(j, i, false, Color.GRAY, cell);
  21.                 if (java.lang.Math.random() < 0.25){
  22.                     cell[i][j].setAlive(true);
  23.                     }
  24.  
  25.   /*****one way to seed the Grid with some random data:
  26.                 if (java.lang.Math.random() < 0.25){
  27.                 cell[i][j].setAlive(true);
  28.                 }
  29.      ********************but you could do many other things, too!   **/            
  30.  
  31.             }
  32.         }
  33.         System.out.println(Cell.cellCounter);    // demonstrates use of a class variable
  34.  
  35.     }
  36.  
  37.     public static void runastep(){
  38.         //first run  through grid calculating what next turn status will be
  39.         for (int i = 0; i < ROWS; i++) {
  40.             for (int j = 0; j < COLS; j++) {
  41.              // what do you think should be here?
  42.                 cell[i][j].prepareNextTurn();
  43.              }
  44.         }
  45.  
  46.         //then go back and run grid, moving next turn status into place
  47.  
  48.         for (int i = 0; i < ROWS; i++) {
  49.             for (int j = 0; j < COLS; j++) {
  50.             //what do you think should be here?
  51.             cell[i][j].setNextTurn();
  52.             }
  53.         }
  54.  
  55.  
  56.  
  57.     }
  58. }
  59.  

And finally, here's the class that handles the display, Display.java:

Expand|Select|Wrap|Line Numbers
  1. import java.awt.*;
  2. import java.awt.event.*;
  3.  
  4. import javax.swing.*;
  5.  
  6. // Note that the JFrame is set up to listen for mouse clicks
  7. // and mouse movement.  To achieve this, the MouseListener and
  8. // MousMotionListener interfaces are implemented and there is additional
  9. // code in init() to attach those interfaces to the JFrame.
  10.  
  11. public class Display extends JFrame implements MouseListener, MouseMotionListener {
  12.     private final int DISPLAY_WIDTH = 750;
  13.     private final int DISPLAY_HEIGHT = 600;
  14.     private final int X_GRID_OFFSET = 25;  // 10 pixels from left
  15.     private final int Y_GRID_OFFSET = 40;  // 10 pixels from top
  16.     private final int CELL_WIDTH = 5;
  17.     private final int CELL_HEIGHT = 5;
  18.     private final Cell[][] myCell;
  19.     private StartButton startStop = new StartButton();
  20.     private boolean paintloop = false;
  21.  
  22.     public Display(Cell[][] cell) {
  23.         myCell = cell;
  24.         init();
  25.     }    
  26.  
  27.     public void init() {
  28.         setBackground(Color.WHITE);        
  29.         setSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
  30.         getContentPane().setLayout(null);
  31.  
  32.         // Example of setting up a button.
  33.         // See the StartButton class nested below.
  34.         add(startStop);
  35.         startStop.setBounds(100,500,72,36);
  36.         startStop.setVisible(true);
  37.  
  38.         addMouseListener(this);
  39.         addMouseMotionListener(this);
  40.         repaint();
  41.     }
  42.  
  43.     public void paint(Graphics g) {
  44.         g.setColor(Color.BLACK);
  45.         drawGrid(g);
  46.         drawCells(g);
  47.         drawComponents();  // buttons, etc., go here
  48.         if (paintloop) {
  49.             try {
  50.  
  51.                 Thread.sleep(50);  //you can change this value!
  52.             } catch (InterruptedException e) {
  53.                 // TODO Auto-generated catch block
  54.                 e.printStackTrace();
  55.             }
  56.             //nextGeneration();
  57.             GameStart.runastep();  //this method will run one generation
  58.             repaint();
  59.  
  60.         }
  61.     }
  62.  
  63.     void drawComponents() {
  64.         startStop.repaint();
  65.     }
  66.  
  67.     void drawGrid(Graphics g) {
  68.         for (int i = 0; i <= GameStart.ROWS; i++) {
  69.             g.drawLine(X_GRID_OFFSET, 
  70.                        Y_GRID_OFFSET + (i*(CELL_HEIGHT+1)),
  71.                        X_GRID_OFFSET + GameStart.COLS*(CELL_WIDTH+1), 
  72.                        Y_GRID_OFFSET + (i*(CELL_HEIGHT+1)));
  73.         }
  74.         for (int i = 0; i <= GameStart.COLS; i++) {
  75.             g.drawLine(X_GRID_OFFSET + (i*(CELL_WIDTH+1)), 
  76.                        Y_GRID_OFFSET,
  77.                        X_GRID_OFFSET + (i*(CELL_WIDTH+1)), 
  78.                        Y_GRID_OFFSET + GameStart.ROWS*(CELL_HEIGHT+1));
  79.         }
  80.     }
  81.  
  82.     void drawCells(Graphics g) {
  83.         // Have each cell draw itself
  84.         for (int i = 0; i < GameStart.ROWS; i++) {
  85.             for (int j = 0; j < GameStart.COLS; j++) {
  86.                 // The cell cannot know for certain the offsets nor the height
  87.                 // and width; it has been set up to know its own position, so
  88.                 // that need not be passed as an argument to the draw method
  89.                 myCell[i][j].draw(X_GRID_OFFSET,Y_GRID_OFFSET,CELL_WIDTH,CELL_HEIGHT,g);
  90.             }
  91.         }
  92.     }
  93.  
  94.     void painter() { repaint(); }
  95.  
  96.  
  97.     /*************************THIS IS AN INNER CLASS*************************
  98.      * that is, a class defined within a class, all it does is run the start
  99.      * button.  When start is clicked, the "paintloop" variable in the
  100.      * Display object is set to true; when stop is clicked, it's set to false.
  101.      * when paintloop is true, the game will be running, when it's false
  102.      * it won't (and perhaps the board may be edited)
  103.      */
  104.     class StartButton extends JButton implements ActionListener {
  105.         StartButton() {
  106.             super("Start");
  107.             addActionListener(this);
  108.         }
  109.  
  110.         public void actionPerformed(ActionEvent arg0) {
  111.             if (this.getText().equals("Start")) {
  112.                 paintloop = true;
  113.                 setText("Stop");
  114.             } else {
  115.                 paintloop = false;
  116.                 setText("Start");
  117.             }
  118.             painter();
  119.         }        
  120.     }    
  121.  
  122.  
  123.     /*********************************************************
  124.      * Note that the Display is ALSO listening for mouse clicks!
  125.      * there is a MouseEvent class that contains information about
  126.      * MouseClicks; all we need to know is the locaton of the click
  127.      * IF IT HAPPENS WHEN THE START BUTTON HAS NOT BEEN PRESSED,
  128.      * THIS WILL ALLOW THE USER TO set cells to be ALIVE or DEAD
  129.      */
  130.  
  131.     public void mouseClicked(MouseEvent me) { 
  132.         if (paintloop==false){
  133.             //CONVERTS THE LOCATION OF THE CLICK IN PIXELS TO THE
  134.             //CORRECT ROW AND COLUMN IN THE GRID
  135.             int  x = (me.getX() - X_GRID_OFFSET-1)/(CELL_WIDTH+1);
  136.             int y =  (me.getY() - Y_GRID_OFFSET - 1)/(CELL_HEIGHT+1);
  137.             //be sure the click is actually IN the grid 
  138.             //to avoid ArrayIndexOutOfBounds Exception
  139.             if ((0<=x)&& (x< myCell.length)&& (0<=y)&&(y<myCell[0].length)){
  140.                 myCell[y][x].toggle();
  141.                 repaint();
  142.             }
  143.             //System.out.println("clicked on (" + x + ","+ y + ") element");
  144.  
  145.         }
  146.  
  147.     }
  148.  
  149.     /*************************
  150.      * a MouseListener must include ALL the methods for the MouseListener
  151.      * interface; but we don't actually need to do anything for these:
  152.      */
  153.     public void mouseEntered(MouseEvent arg0) { }
  154.  
  155.     public void mouseExited(MouseEvent arg0) { }
  156.  
  157.     public void mousePressed(MouseEvent arg0) { }
  158.  
  159.     public void mouseReleased(MouseEvent arg0) { }
  160.  
  161.     public void mouseDragged(MouseEvent arg0) { }
  162.  
  163.     public void mouseMoved(MouseEvent arg0) { }
  164.  
  165. }

Thanks in advance for your help!
Dec 1 '09 #1
Share this Question
Share on Google+
2 Replies


mrjohn
P: 32
It does look like looking for cells "off the edge" is what is causing the null pointer exception. I do have one question though. Is context supposed to be context[x][y] or context[y][x]? Because you seem to use context[myX][myY] as well as context[myY][myX]. I recommend making your code use just the Cartesian X/Y version, as it makes the grid more intuitive.

As far as going "around the world" goes, consider the fact that once you the cross the far side of the map (Element 99), the next element is 0, instead of 100.
So if the number of the destination cell on the X-axis is greater or equal to the grid's length, you need to subtract the length of the map.
If the number is less than 0, you need to add the length of the map.

Same goes for the Y-axis.
Dec 1 '09 #2

P: 16
Yes, I see that. I actually caught that mistake minutes before I read your post. :) Thank you so much for the help though. Your advice on the toroidal structure was very useful. Much thanks.
Dec 2 '09 #3

Post your reply

Sign in to post your reply or Sign up for a free account.