Graphic by Keith Ohlfs
CS111, Wellesley College, Fall 2000

Lab 4 Solutions

[CS111 Home Page] [Syllabus] [Lecture Notes] [Assignments] [Programs] [Documentation] [Software Installation] [FAQ] [CS Dept.] [CWIS]


The working code for the following solutions can be downloaded from:

http://cs111.wellesley.edu/~cs111/download/lab_solutions/lab4_solutions.

HurdleWorld Solution

Exercise 1: Running the Hurdles

In HurdleWorld, a hurdle is a 1 square-high wall; the finish line is the right-hand grid wall. A Hurdler object, which starts in position (1,1) runs a race by moving EAST, jumping over all the hurdles, and stopping at the finish line. The race may be decomposed into the possible situations which may occur as the Hurdler runs, and the action to take for that particular situation:

  1. If the Hurdler is at the finish line, stop.
  2. If the Hurdler is at a hurdle, jump over it.
  3. Otherwise, move forward one space.

The HurdleWorld.java file provides the following skeleton:

class Hurdler extends TickBuggle {

public void tick() {

// Flesh out this skeleton

}

public boolean atFinishLine() {

// Flesh out this skeleton

return /* true or false */;

}

public void jumpHurdle() {

// Flesh out this skeleton

}

}

Basically, the tick() method consists of an if-else construct which addresses each of the possible situations listed above:

public void tick() {
if (atFinishLine()) {
// Do nothing

} else if (isFacingWall()) {

jumpHurdle();

} else {

forward();

}

}

The atFinishLine() method is used by tick() to test if the Hurdler is at the finish line. The isFacingWall() method may be used to determine is the buggle is facing a wall; if so, the Hurdler must distinguish between whether the wall is a hurdle or the final wall. To do this, the Hurdler must move up one square and look to see whether it is still facing a wall. If so, it is the finish line, and the method should return true; otherwise, it should return false. In either case, an invariant is applied such that the Hurdler must be restored to its original position and heading before exitting the method.

In this solution, a local boolean variable result is declared at the start of the method. It is not immediately assigned a value, but is used later on to temporarily hold the value of true or false indicating whether or not the finish line has been reached. This local variable is used specifically because of the invariant which requires the Hurdler to be returned to its original position and heading after the result is determined.

public boolean atFinishLine() {
/*
Return true if buggle is facing wall (as opposed to hurdle) and false otherwise.

Should leave buggle in same position and heading as when it starts.

Should not leave any marks behind.

*/

boolean result;

if (isFacingWall()) {

brushUp();

left();

forward();

right();

result = isFacingWall();

left();

backward();

right();

brushDown();

} else {

result = false;

}

return result;

}

The jumpHurdle() method is simply the steps taken by the Hurdler is go up the hurdle, over it, down the opposite side, and finish facing EAST:

public void jumpHurdle() {
left();

forward();

right();

forward();

right();

forward();

left();

}

Exercise 2: TiredHurdler

The TiredHurdler is a Hurdler which can jump no more than a specified number of hurdles. The constructor method for TiredHurdler takes an integer that is the maximum number of hurdles the buggle will jump.

For instance, new TiredHurdler(3) creates a buggle that will jump no more than three hurdles. If it encounters a fourth hurdle, it will stop moving.

Here is the skeleton for a TiredHurdler class in HurdleWorld.java:

class TiredHurdler extends Hurdler {
private int hurdlesLeft;

public TiredHurdler(int hurdlesLeft) {

this.hurdlesLeft = hurdlesLeft;

}

}

public void tick() {
//Flesh this skeleton out

}

}

The class has an integer instance variable hurdlesLeft that keeps track of how many more hurdles the buggle is willing to jump. The constructor method for TiredHurdler initialize this instance variable to the number supplied when the instance is constructed. When a TiredHurdler runs the course, it should decrement this instance variable every time it jumps a hurdle, and refuse to jump a hurdle when this instance variable contains 0.

The solution is very similar to exercise one, but with an additional condition to test for and action to take:

  1. If the Hurdler is at the finish line, stop.
  2. If the Hurdler is at a hurdle, and hurdles are left (i.e. hurdlesLeft > 0), jump over the hurdle and decrement the number of hurdles left (i.e. hurdlesLeft = hurdlesLeft - 1)
  3. If the Hurdler is at a hurdle and no hurdles are left, stop.
  4. Otherwise, move forward one space.

This can be expressed with the following tick() method:

public void tick() {
if (atFinishLine()) {
// Do nothing

} else if ((hurdlesLeft > 0) && isFacingWall()) {

jumpHurdle();

hurdlesLeft = hurdlesLeft - 1;

}else if (isFacingWall()){

//do nothing

} else {

forward();

}

}