import java.util.ArrayList; public abstract class ListEnv extends SquareEnvironment { private ArrayList objectList; public ListEnv() { objectList = new ArrayList(); } public abstract int numRows(); public abstract int numCols(); public abstract boolean isValid(Location loc); // The rest of the methods copied from UnboundedEnv /** Returns the number of objects in this environment. * @return the number of objects **/ public int numObjects() { return objectList.size(); } /** Returns all the objects in this environment. * @return an array of all the environment objects **/ public Locatable[] allObjects() { Locatable[] objectArray = new Locatable[objectList.size()]; // Put all the environment objects in the list. for ( int index = 0; index < objectList.size(); index++ ) { objectArray[index] = (Locatable) objectList.get(index); } return objectArray; } /** Determines whether a specific location in this environment is * empty. * @param loc the location to test * @return true if loc is a * valid location in the context of this environment * and is empty; false otherwise **/ public boolean isEmpty(Location loc) { return (objectAt(loc) == null); } /** Returns the object at a specific location in this environment. * @param loc the location in which to look * @return the object at location loc; * null if loc is empty **/ public Locatable objectAt(Location loc) { int index = indexOf(loc); if ( index == -1 ) return null; return (Locatable) objectList.get(index); } /** Creates a single string representing all the objects in this * environment (not necessarily in any particular order). * @return a string indicating all the objects in this environment **/ public String toString() { Locatable[] theObjects = allObjects(); String s = "Environment contains " + numObjects() + " objects: "; for ( int index = 0; index < theObjects.length; index++ ) s += theObjects[index].toString() + " "; return s; } // modifier methods /** Adds a new object to this environment at the location it specifies. * (Precondition: obj.location() is a valid empty location.) * @param obj the new object to be added * @throws IllegalArgumentException if the precondition is not met **/ public void add(Locatable obj) { // Check precondition. Location should be empty. Location loc = obj.location(); if ( ! isEmpty(loc) ) throw new IllegalArgumentException("Location " + loc + " is not a valid empty location"); // Add object to the environment. objectList.add(obj); } /** Removes the object from this environment. * (Precondition: obj is in this environment.) * @param obj the object to be removed * @throws IllegalArgumentException if the precondition is not met **/ public void remove(Locatable obj) { // Find the index of the object to remove. int index = indexOf(obj.location()); if ( index == -1 ) throw new IllegalArgumentException("Cannot remove " + obj + "; not there"); // Remove the object. objectList.remove(index); } /** Updates this environment to reflect the fact that an object moved. * (Precondition: obj.location() is a valid location * and there is no other object there. * Postcondition: obj is at the appropriate location * (obj.location()), and either oldLoc is * equal to obj.location() (there was no movement) or * oldLoc is empty.) * @param obj the object that moved * @param oldLoc the previous location of obj * @throws IllegalArgumentException if the precondition is not met **/ public void recordMove(Locatable obj, Location oldLoc) { int objectsAtOldLoc = 0; int objectsAtNewLoc = 0; // Look through the list to find how many objects are at old // and new locations. Location newLoc = obj.location(); for ( int index = 0; index < objectList.size(); index++ ) { Locatable thisObj = (Locatable) objectList.get(index); if ( thisObj.location().equals(oldLoc) ) objectsAtOldLoc++; if ( thisObj.location().equals(newLoc) ) objectsAtNewLoc++; } // There should be one object at newLoc. If oldLoc equals // newLoc, there should be one at oldLoc; otherwise, there // should be none. if ( ! ( objectsAtNewLoc == 1 && ( oldLoc.equals(newLoc) || objectsAtOldLoc == 0 ) ) ) { throw new IllegalArgumentException("Precondition violation moving " + obj + " from " + oldLoc); } } // 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++ ) { Locatable obj = (Locatable) objectList.get(index); if ( obj.location().equals(loc) ) { // Found the object -- return its index. return index; } } // No such object found. return -1; } }