Here we will exercise a robot that uses a strategy to do its work. This robot is given a number and asked to compute the square of that number (n), by placing a beeper on avenue n and street n squared.
Here is the code for this class. Note that the only reason this isn't derived from UrRobot is that we need to reset between computations. You could write a strategy to do this, of course.
[ User Guide] [.FrontPage] [.RecentChanges]
| kareltherobot.KarelFixture | ||||
| kareltherobot.XSquareRobot | ||||
| World | reset | |||
| Create | karel | |||
| Message | karel | compute | 3 | |
| Message | karel | compute | 4 | |
| Message | karel | compute | 50 | |
| Assert | BeepersAt | 9 | 3 | 1 |
| Assert | BeepersAt | 16 | 4 | 1 |
| Assert | BeepersAt | 2500 | 50 | 1 |
Here is the code for this class. Note that the only reason this isn't derived from UrRobot is that we need to reset between computations. You could write a strategy to do this, of course.
/*
* Created on Oct 12, 2003
*
*/
package kareltherobot;
import java.awt.Color;
/** A robot that can use a Compute Strategy to compute the function y=x^2;
* @author jbergin
*
*/
public class XSquareRobot extends AugmentedRobot
{
/** These robots always start at the origin and there is no need for
* the other parameters
* @param badge the color badge that the robot wears
*/
public XSquareRobot( Color badge)
{
super(1, 1, East, infinity, badge);
}
/** These robots always start at the origin and there is no need for
* the parameters
*/
public XSquareRobot()
{
super(1, 1, East, infinity);
}
private void reset()
{ faceWest();
while(frontIsClear())move();
turnLeft();
while(frontIsClear())move();
turnLeft(); // at origin facing East
counter = LevelTwo.NULL;
computeStrategy = ComputeStrategy.NULL;
}
/** Do an ordinary move, by also remember the new y
* coordinate.
*
*/
private void moveAndLearn()
{ move();
counter = new OuterCounter(counter);
}
/** The robot world's origin is (1,1) not (0,0) so we adjust
* at the end of a computation.
*/
private void adjust()
{ turnLeft();
move();
turnLeft();
move();
}
/** After executing moveAndLearn zero or more times execute this once
* to compute the y coordinate by moving there.
*
* PostCondition: The robot has turned off.
*/
private void compute()
{ turnLeft();
counter.apply(this);
adjust();
putBeeper();
}
/** If the number of times that moveAndLearn has been sent is k then
* this will be sent k times and each time it is sent the robot (this)
* will move k steps.
*/
private void moveMany()
{ computeStrategy.compute(this);
}
public void compute(int n)
{ reset();
for(int i = 0; i < n; ++i)
{ moveAndLearn();
}
compute();
}
interface LevelTwo
{ void apply(XSquareRobot robot);
public static final LevelTwo NULL = new NullStrategy();
public class NullStrategy implements LevelTwo
{ public void apply(XSquareRobot robot)
{ // nothing
}
}
}
class OuterCounter implements LevelTwo
{ public OuterCounter(LevelTwo decorated)
{ this.decorated = decorated;
computeStrategy = new ExtraMove(computeStrategy);
}
public void apply(XSquareRobot robot)
{
robot.moveMany();
decorated.apply(robot);
}
private LevelTwo decorated = null;
}
/** This class is used to decorate a strategy by adding
* one more move to whatever else is known to do.
* @author jbergin
*
*/
private class ExtraMove implements ComputeStrategy
{ public ExtraMove(ComputeStrategy decorated)
{ this.decorated = decorated;
}
public void compute(UrRobot who)
{ who.move();
decorated.compute(who);
}
ComputeStrategy decorated = null;
}
private LevelTwo counter = LevelTwo.NULL;
private ComputeStrategy computeStrategy = ComputeStrategy.NULL;
}
[ User Guide] [.FrontPage] [.RecentChanges]