// Class: ArrayListGrid
//
// Author: Alyce Brady
//
// This class is based on the College Board's UnboundedEnv class,
// as allowed by the GNU General Public License. UnboundedEnv is a
// component of the AP(r) CS Marine Biology Simulation
// case study (see
// http://www.collegeboard.com/student/testing/ap/compsci_a/case.html).
//
// License Information:
// This class is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation.
//
// This class is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
package edu.kzoo.grid;
import java.util.ArrayList;
/**
* Grid Container Package:
*
* The ArrayListGrid
class encapsulates two public inner
* classes that extend the Grid
class to
* model a two-dimensional grid by keeping track of their contents
* in ArrayList
objects. The first public inner class,
* ArrayListGrid.Bounded
, represents a bounded grid
* using an ArrayList
, while the second public inner class,
* ArrayListGrid.Unbounded
, represents an unbounded grid
* using an ArrayList
.
*
*
* Methods of both ArrayListGrid
classes have the
* following time and space characteristics:
*
numObjects | O(1 ) | |
allObjects | O(n ) | |
isEmpty, objectAt | O(n ) | |
add | O(1 ) [amortized] | |
remove | O(n ) | |
space | O(n ) |
n
is the number of objects in the grid.
*
*
* The ArrayListGrid
classes are based on the
* College Board's UnboundedEnv
class, as allowed
* by the GNU General Public License.
*
* @author Alyce Brady
* @version 20 March 2004
* @see Direction
* @see Location
* @see GridObject
*/
public class ArrayListGrid
{
// ArrayListGrid is a scoping mechanism, not meant to be instantiated.
private ArrayListGrid()
{
}
/** An ArrayListGrid.Bounded
object is a rectangular,
* bounded two-dimensional container data structure implemented as
* an ArrayList
of the objects it contains. It can contain
* any kind of object that can be modeled using an extension of the
* GridObject
class. For example, a bounded grid could
* be used to model a board for a tic-tac-toe or chess game, an
* environment of fish for a marine biology simulation, etc.
*
*
* ArrayListGrid.Bounded
methods have the
* following time and space characteristics:
*
numObjects | O(1 ) | |
allObjects | O(n ) | |
isEmpty, objectAt | O(n ) | |
add | O(1 ) [amortized] | |
remove | O(n ) | |
space | O(n ) |
n
is the number of objects in the grid.
**/
public static class Bounded extends Grid
{
// instance variables: encapsulated data for each Bounded grid object
private int numRows;
private int numCols;
// constructors
/** Constructs an empty ArrayListGrid.Bounded object with the given
* dimensions.
* A cell's neighbors include only the cells to its north, south,
* east, and west, not the cells on the diagonals.
* (Precondition: rows > 0
and cols > 0
.)
* @param rows number of rows in grid
* @param cols number of columns in grid
* @throws IllegalArgumentException if the precondition is not met
**/
public Bounded(int rows, int cols)
{
// Construct and initialize inherited attributes.
this(false, rows, cols);
}
/** Constructs an empty ArrayListGrid.Bounded object with the given
* dimensions.
* Each cell in this grid will have at most four or eight
* adjacent neighbors, depending on the value of the
* includeDiagonalNeighbors
parameter. Cells along
* the grid boundaries will have fewer than the maximum four or
* eight neighbors. If includeDiagonalNeighbors
is
* true
, a cell's adjacent neighbors include the
* cells to its north, south, east, and west and the cells on
* the diagonals, to the northeast, southeast, northwest, and
* southwest. If includeDiagonalNeighbors
is
* false
, a cell's adjacent neighbors include only
* the four cells to its north, south, east, and west.
* (Precondition: rows > 0
and cols > 0
.)
* @param includeDiagonalNeighbors whether to include the four
* diagonal locations as neighbors
* @param rows number of rows in grid
* @param cols number of columns in grid
* @throws IllegalArgumentException if the precondition is not met
**/
public Bounded(boolean includeDiagonalNeighbors,
int rows, int cols)
{
// Construct and initialize inherited attributes.
super(new ArrayListGridRep(
new Grid.BoundedGridValidityChecker(rows, cols)),
includeDiagonalNeighbors);
numRows = rows;
numCols = cols;
}
// accessor methods dealing with grid dimensions
/** Returns number of rows in this grid.
* @return the number of rows in this grid
**/
public int numRows()
{
return this.numRows;
}
/** Returns number of columns in this grid.
* @return the number of columns in this grid
**/
public int numCols()
{
return this.numCols;
}
}
/** An ArrayListGrid.Unounded
object is an unbounded
* two-dimensional container data structure implemented as
* an ArrayList
of the objects it contains. It can contain
* any kind of object that can be modeled using an extension of the
* GridObject
class. For example, a bounded grid could
* be used to model a board for a tic-tac-toe or chess game, an
* environment of fish for a marine biology simulation, etc.
*
*
* ArrayListGrid.Unbounded
methods have the
* following time and space characteristics:
*
numObjects | O(1 ) | |
allObjects | O(n ) | |
isEmpty, objectAt | O(n ) | |
add | O(1 ) [amortized] | |
remove | O(n ) | |
space | O(n ) |
n
is the number of objects in the grid.
**/
public static class Unbounded extends Grid
{
// constructors
/** Constructs an empty ArrayListGrid.Unbounded object.
* A cell's neighbors include only the cells to its north, south,
* east, and west, not the cells on the diagonals.
* (Precondition: rows > 0
and cols > 0
.)
**/
public Unbounded()
{
// Construct and initialize inherited attributes.
this(false);
}
/** Constructs an empty ArrayListGrid.Unbounded object.
* Each cell in this grid will have at most four or eight
* adjacent neighbors, depending on the value of the
* includeDiagonalNeighbors
parameter. If
* includeDiagonalNeighbors
is true
,
* a cell's adjacent neighbors include the cells to its north,
* south, east, and west and the cells on the diagonals, to
* the northeast, southeast, northwest, and southwest. If
* includeDiagonalNeighbors
is false
,
* a cell's adjacent neighbors include only the four cells to
* its north, south, east, and west.
* (Precondition: rows > 0
and cols > 0
.)
* @param includeDiagonalNeighbors whether to include the four
* diagonal locations as neighbors
**/
public Unbounded(boolean includeDiagonalNeighbors)
{
// Construct and initialize inherited attributes.
super(new ArrayListGridRep(new Grid.UnboundedGridValidityChecker()),
includeDiagonalNeighbors);
}
// accessor methods dealing with grid dimensions
/** Returns number of rows in this grid.
* @return the number of rows, or UNBOUNDED if the grid is unbounded
**/
public int numRows()
{
return Grid.UNBOUNDED;
}
/** Returns number of columns in this grid.
* @return the number of columns, or UNBOUNDED if the grid is unbounded
**/
public int numCols()
{
return Grid.UNBOUNDED;
}
}
/** Internal representation for an ArrayList
-based
* implementation of a Grid
class.
**/
public static class ArrayListGridRep
implements Grid.InternalRepresentation
{
// instance variables: encapsulated data for each ArrayListGridRep object
private ArrayList objectList; // list of objects in a grid
private Grid.ValidityChecker locationValidityChecker;
// constructors
/** Constructs an empty ArrayListGridRep representation of a grid.
* @param checker an object that knows how to check the validity
* of a location in a grid
**/
protected ArrayListGridRep(Grid.ValidityChecker checker)
{
objectList = new ArrayList();
locationValidityChecker = checker;
}
// accessor methods
/** Verifies whether a location is valid in this grid.
* @param loc location to check
* @return true
if loc
is valid;
* false
otherwise
**/
public boolean isValid(Location loc)
{
return locationValidityChecker.isValid(loc);
}
/** Returns the number of objects in this grid.
* @return the number of objects
**/
public int numObjects()
{
return objectList.size();
}
/** Returns all the objects in this grid.
* @return an array of all the grid objects
**/
public GridObject[] allObjects()
{
// Copy them to an array.
int numObjects = objectList.size();
GridObject[] theObjects = new GridObject[numObjects];
for ( int i = 0; i < numObjects; i++ )
theObjects[i] = (GridObject) objectList.get(i);
return theObjects;
}
/** Returns the object at a specific location in this grid.
* @param loc the location in which to look
* @return the object at location loc
;
* null
if loc
is not
* in the grid or is empty
**/
public GridObject objectAt(Location loc)
{
int index = indexOf(loc);
if ( index == -1 )
return null;
return (GridObject) objectList.get(index);
}
// modifier methods
/** Adds a new object to this internal grid representation at the
* location it specifies.
* (Precondition: obj.grid()
is this grid and
* obj.location()
is a valid empty location;
* verified by the Grid
object.)
* @param obj the new object to be added
**/
public void add(GridObject obj)
{
// Add object to the internal grid representation.
objectList.add(obj);
}
/** Removes the object from this internal grid representation.
* (Precondition: obj
is in this grid; verified
* by the Grid
object.)
* @param obj the object to be removed
**/
public void remove(GridObject obj)
{
// Find the index of the object and then remove it.
objectList.remove(indexOf(obj.location()));
}
// internal helper method
/** Get the index of the object at the specified location.
* @param loc the location in which to look
* @return the index of the object at location loc
* if there is one; -1 otherwise
**/
protected int indexOf(Location loc)
{
// Look through the list to find the object at the given location.
for ( int index = 0; index < objectList.size(); index++ )
{
GridObject obj = (GridObject) objectList.get(index);
if ( obj.location().equals(loc) )
{
// Found the object -- return its index.
return index;
}
}
// No such object found.
return -1;
}
}
}