// Grid.java // CS201J Fall 2002 import java.util.Collection; import java.util.Iterator; import java.util.ArrayList; public class Grid { // OVERVIEW: A Grid is a rows x columns 2-dimensional array of cells. /*@spec_public@*/ private int rows; //@invariant rows >= 0; /*@spec_public@*/ private int columns; //@invariant columns >= 0; /*@non_null@*/ Cell [][] cells; private Class cellClass; //@invariant cells.length == rows; //@invariant (\forall int i; (0 <= i && i < rows) ==> (cells[i] != null && cells[i].length == columns)); // invariant (\forall int i; (0 <= i && i < rows) ==> (\forall int j; (0 <= j && j < columns) ==> (cells[i][j] != null))); Grid (/*@non_null@*/ Class cellClass, int p_rows, int p_columns) // REQUIRES: cellClass must be a subtype of Cell. // EFFECTS: Constructs a new grid corresponding to table. sg8u { rows = p_rows; columns = p_columns; cells = new Cell [rows][columns]; this.cellClass = cellClass; // Initialize the cells. try { for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { Cell newCell = (Cell) cellClass.newInstance (); //@nowarn Cast; //@assume newCell != null; newCell.init (i, j, this); cells[i][j] = newCell; } } } catch (java.lang.InstantiationException e) { System.exit (0); } catch (java.lang.IllegalAccessException e) { System.exit (0); } } public int numRows() // EFFECTS: Returns the number of rows in the grid. //@ensures \result == rows; { return rows; } public int numColumns() // EFFECTS: Returns the number of columns in the grid. //@ensures \result == columns; { return columns; } public /*@non_null@*/ Cell getCellAt(int row, int col) // REQUIRES: 0 >= row < rows && 0 >= col < columns // EFFECTS: Returns the Cell at the specified row and column. // If that grid location is invalid, a dead cell will // be returned. { if ((row < 0) || (row > numRows () - 1)) { throw new RuntimeException ("Bad row parameter to getCellAt: " + row); } if ((col < 0) || (col > numColumns () - 1)) { throw new RuntimeException ("Bad column parameter to getCellAt: " + col); } return cells[row][col]; } boolean isAlive(int row, int col) // REQUIRES: 0 >= row < rows && 0 >= col < columns // EFFECTS: Returns true iff grid location (row, col) is alive. { return getCellAt(row, col).isAlive(); } void step () // MODIFIES: this // EFFECTS: Executes one step for each cell in the grid. Each cell first caluclates its next // state based on the current state of itself and its neighbors. Then, all cells advance // to their next state. { CellState [][] nextStates = new CellState [rows][columns]; // Because we need to update all cells synchronously, we first calculate the next state // for each cell, and store it in a temporary array. Then, we update all the cells. for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { nextStates [i][j] = getCellAt (i, j).getNextState (); } } for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { getCellAt (i, j).setState (nextStates[i][j]); } } } }