posted 21 years ago
This is basically a simulation of an Ocean containing sharks and fishes. My main problem lies within the initialise method. Can anyone help me out?
import phw.ocean.*;
import java.util.Random;
class MyOcean implements Ocean {
///////////////// private fields (may need others)
private final OceanDisplay oceanDisplay;
private final int width, depth;
private int FBA; // fish birth age
private int SBA; // shark birth age
private int SSA; // shark starve age
private int initFishPercentage;
private int initSharkPercentage;
private final Cell[][] cell; // matrix of cells
private final Random random = new Random ();
private final static int NORTH = 0; // may be helpful ...
private final static int EAST = 1;
private final static int SOUTH = 2;
private final static int WEST = 3;
private final static int NORTH_DIAG = 4;
private final static int SOUTH_DIAG = 5;
private final static int TOTAL_NEIGHBOURS = 6; // or, maybe, just 4 ...
///////////////// constructors
/**
* @param oceanDisplay the displayer object to be used for the ocean.
* @param width the width of the ocean.
* @param depth the depth of the ocean.
* @param initFishPercentage the initial percentage of fish in the ocean.
* @param initSharkPercentage the initial percentage of sharks in the ocean.
* @param FBA the Fish Birth Age for the ocean.
* @param SBA the Shark Birth Age for the ocean.
* @param SSA the Shark Starve Age for the ocean.
*
* @throws BadDisplayException if oceanDisplay is null.
* @throws BadWidthException if width is <= 0 or too wide for oceanDisplay.
* @throws BadDepthException if depth is <= 0 or too deep for oceanDisplay.
* @throws BadRateException if the initFishPercentage/initSharkPercentage
* (and their sums) are negative or > {@link #maxRate}.
* @throws BadFBAException if FBA is not in minFBA/maxFBA range.
* @throws BadSBAException if SBA is not in minSBA/maxSBA range.
* @throws BadSSAException if SSA is not in minSSA/maxSSA range.
*/
public MyOcean (OceanDisplay oceanDisplay, int width, int depth,
int initFishPercentage, int initSharkPercentage,
int FBA, int SBA, int SSA)
throws BadDisplayException, BadWidthException, BadDepthException,
BadFBAException, BadSBAException, BadSSAException , BadRateException {
if (oceanDisplay == null)
throw new BadDisplayException ("from MyOcean constructor ...");
if ((width <= 0) || (oceanDisplay.getMaxWidth () < width))
throw new BadWidthException ("from MyOcean constructor ...");
if ((depth <= 0) || (oceanDisplay.getMaxDepth () < depth))
throw new BadDepthException ("from MyOcean constructor ...");
if ((initFishPercentage < 0) || (maxInitFishPercentage < initFishPercentage))
throw new BadRateException ("from MyOcean constructor ...");
if ((initSharkPercentage < 0) || (maxInitSharkPercentage < initSharkPercentage))
throw new BadRateException ("from MyOcean constructor ...");
if ((FBA < minFBA) || (maxFBA < FBA))
throw new BadFBAException ("from MyOcean constructor ...");
if ((SBA < minSBA) || (maxSBA < SBA))
throw new BadSBAException ("from MyOcean constructor ...");
if ((SSA < minSSA) || (maxSSA < SSA))
throw new BadSSAException ("from MyOcean constructor ...");
this.oceanDisplay = oceanDisplay;
this.width = width;
this.depth = depth;
this.initFishPercentage = initFishPercentage;
this.initSharkPercentage = initSharkPercentage;
this.FBA = FBA;
this.SBA = SBA;
this.SSA = SSA;
cell = new Cell[depth][width];
for (int row = 0; row < depth; row++) {
for (int col = 0; col < width; col++) {
Cell[row][col] = Cell.EMPTY;
}
}
oceanDisplay.setCell (cell);
}
public MyOcean (OceanDisplay oceanDisplay, int width, int depth, int initFishPercentage, int initSHarkPercentage, int FBA, int SBA, int SSA)
throws BadDisplayException, BadWidthException, BadDepthException,
BadRateException, BadFBAException, BadSBAException, BadSSAException {
this (oceanDisplay, width, depth, initFishPercentage, initSharkPercentage, FBA, SBA, SSA);
random.setCell (cell); // enables us to choose the cell
}
///////////////// private methods (that may be useful)
/**
* @param max a positive integer > 0.
*
* @return a random integer between 0 and (max - 1) inclusive.
*/
private final int range (int max) {
int n = random.nextInt ();
if (n == Integer.MIN_VALUE) {
n = 42;
}
else if (n < 0) {
n = -n;
}
return ((random.nextInt ()) >>> 1) % max;
}
///////////////// public methods (implementing the Ocean interface)
/**
* The width will have been set by the constructor of the class implementing
* this interface and it can't be changed.
*
* @return the width of the ocean.
*/
public int getWidth () {
return width;
}
/**
* The depth will have been set by the constructor of the class implementing
* this interface and it can't be changed.
*
* @return the depth of the ocean.
*/
public int getDepth () {
return depth;
}
/**
* The initial percentage of fishes will have been set by the constructor
* of the class implementing this interface.
*
* @return the initial percentage of fishes in the ocean.
*/
public int getInitFishPercentage () {
return initFishPercentage;
}
/**
* The initial percentage of sharks will have been set by the constructor
* of the class implementing this interface.
*
* @return the initial percentage of sharks in the ocean.
*/
public int getInitSharkPercentage () {
return initSharkPercentage;
}
/**
* This sets the initial percentage of sharks and fishes.
*
* @param initPercentage the initial percentage of sharks and fishes.
*
* @throws BadRateException if either of the new rates (or their sum)
* is < 0 or > Ocean.maxInitPercentages.
*/
public void setInitPercentages (int initFishPercentage, int initSharkPercentage)
throws BadRateException {
if (((initFishPercentage < 0) || (maxInitFishPercentage < initFishPercentage)) && ((initSharkPercentage < 0) || (maxInitSharkPercentage < initSharkPercentage)))
throw new BadRateException ("from MyOcean.setInitPercentages ...");
this.initFishPercentage = initFishPercentage;
this.initSharkPercentage = initSharkPercentage;
}
/**
* The Fish Birth Age is the number of cycles until the fish gives birth.
*
* @return the Fish Birth Age.
*/
public int getFishBirthAge () {
return FBA;
}
/**
* The Shark Birth Age is the number of cycles until the shark gives birth.
*
* @return the Shark Birth Age.
*/
public int getSharkBirthAge () {
return SBA;
}
/**
* The Shark Starve Age is the number of cycles without feeding
* until the shark dies.
*
* @return the Shark Starve Age.
*/
public int getSharkStarveAge () {
return SSA;
}
/**
* The Fish Birth Age is the number of cycles until the fish gives birth.
*
* @throws BadFBAException if (FBA < minFBA) or (FBA > maxFBA).
*/
public void setFishBirthAge (int FBA) throws BadFBAException {
if((FBA < minFBA) || (FBA > maxFBA))
throw new BadFBAException ("from MyOcean.setFishBirthAge ...");
this.FBA = FBA;
}
/**
* The Shark Birth Age is the number of cycles until the shark gives birth.
*
* @throws BadSBAException if (SBA < minSBA) or (SBA > maxSBA).
*/
public void setSharkBirthAge (int SBA) throws BadSBAException {
if((SBA < minSBA) || (SBA > maxSBA))
throw new BadSBAException ("from MyOcean.setSharkBirthAge ...");
this.SBA = SBA;
}
/**
* The Shark Starve Age is the number of cycles without feeding
* until the shark dies.
*
* @throws BadSSAException if (SSA < minSSA) or (SSA > maxSSA).
*/
public void setSharkStarveAge (int SSA) throws BadSSAException {
if((SSA < minSSA) || (SSA > maxSSA))
throw new BadSSAException ("from MyOcean.setSharkStarveAge ...");
this.SSA = SSA;
}
/**
* This initialises the ocean to some random state of sharks and fishes,
* bearing in mind to keep to the specified initial percentages of each.
*/
public void initialise () {
Random rand = new Random();
int numberOfSharksNeeded = initSharkPercentage;
int numberOfFishesNeeded = initFishPercentage;
while(numberOfSharksNeeded != 0) {
if(cell[row][col] = Cell.EMPTY) {
cell[i][j].type = Cell.SHARK;
}
}
while(numberOfFishesNeeded != 0) {
if(cell[row][col] = Cell.EMPTY) {
cell[i][j].type = Cell.FISH;
}
}
}
/**
* This displays the ocean.
*/
public void display () {
oceanDisplay.show ();
}
/**
* This sets results to the number of empty cells, fishes and sharks
* (respectively) in the ocean. It assumes results has a length of 3.
*
* @param results an array to be given the number of empty cells, fishes and sharks.
*/
public void report (int[] results) {
// missing body
}
///////////////// The following private methods are just a suggestion for
///////////////// supporting an implementation of the public evolve() method.
///////////////// The suggestion only takes you so far ... you may need to
///////////////// design further private methods to assist the implementation
///////////////// of evolveCell(i,j). Feel free to ignore this suggestion
///////////////// and devise your own scheme.
/**
* @param current is a Cell2 containing a fish or a shark.
* @param i is the row coordinate (not necessarily legal) of a cell to be searched.
* @param j is the column coordinate (not necessarily legal) of a cell to be searched.
* @param target is the type of cell being sought - this may be a fish
* (if current is a shark) or empty (if current is a fish or a shark)
*
* This method returns false if (i, j) is outside the bounds of the ocean.
* Otherwise, if cell (i, j) has the type of the sought target, whatever
* animal was in the current cell moves to cell (i, j) and the current cell
* becomes empty - and true is returned. Failing that, it returns false.
*/
private boolean search (Cell current, int i, int j, byte target) {
return true; // missing body (invoked from move - see below)
}
/**
* @param i is a (legal) row coordinate of a cell.
* @param j is a (legal) column coordinate of a cell.
* @param target is the type of cell being sought - this may be a fish
* (if current is a shark) or empty (if current is a fish or a shark)
*
* (i, j) are the (legal) row-column coordinates of a cell containing
* either a shark or a fish. The animal wants to find a target, or some
* empty space, and move there.
* <p>
* A search is made on the (N, S, E, W) neighbours of the (i, j) cell.
* This search must make a random choice of the compass in which to begin
* and continue clockwise (or, if you prefer, anti-clockwise) from there.
* The search stops if a target is found and the fish or shark in (i, j)
* moves there - in which case, this method returns true. If none of the
* neighbours contains a suitable target, nothing moves and this method
* returns false.
*/
private boolean move (int i, int j, byte target) {
return true; // missing body (invoked from evolveCell - see below)
}
/**
* @param i is a (legal) row coordinate of a cell.
* @param j is a (legal) column coordinate of a cell.
*
* This method models the behaviour of whatever is in the (i, j) cell.
* If it's empty, it does nothing. If there is a fish, it models fish
* behaviour - i.e. it may give birth (depending on its age) or move on
* to a random empty neighbouring cell (if there is one). If the (i, j)
* cell contains a shark, it models shark behaviour - i.e. it may die
* it it's been too long since it last ate (and the cell becomes empty),
* it may give birth (depending on its age), it may eat a random fish
* (if there is one in a neighbouring cell) or it may move on (if there
* is room to do so).
*/
private void evolveCell (int i, int j) {
// missing body
}
/**
* Process the ocean top-down and left-right.
*/
private void evolveForwards () {
for (int i = 0; i < depth; i++) {
for (int j = 0; j < width; j++) {
evolveCell (i, j);
}
}
}
/**
* Process the ocean bottom-up and right-left.
*/
private void evolveBackwards () {
// missing body
}
/**
* Just a suggestion
*/
private boolean forwards = false;
/**
* This evolves the ocean forward one cycle.
*/
public void evolve () {
forwards = !forwards;
if (forwards) {
evolveForwards ();
} else {
evolveBackwards ();
}
}
}