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
- 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:
Expand|Select|Wrap|Line Numbers
- 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:
Expand|Select|Wrap|Line Numbers
- 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);
- }
- }
Expand|Select|Wrap|Line Numbers
- 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:
Expand|Select|Wrap|Line Numbers
- 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!