KarelFixture.
ExerciseStrategyRobot
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.


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]