Task 3: HuggleWorld


Background

The Story

Fontaine Buggle is very impressed by the creative work of her cousins at the Buggle Bagel Ruggle Company. But she thinks that buggles can use their considerable talents to do more than just drop bagels in interesting patterns.

Inspired by the buggle writing problem of Problem Set 1 (remember "Ellie"?), Fontaine wants buggles to be able to write words using letters of any color drawn in rectangles of arbitrary size and orientation. As a simple example of what can be done with this capability, Fontaine designs the following Valentine card:

Valentine Figure

The card uses the seven letters 'C', 'd', 'G', 'H', 'I', 'P', and 'U'. Note that the 'U' appearing in "CUPId" and "HUG" has the same basic shape even though it is written in rectangles of different sizes (a 5x5 rectangle in the case of the 'U' in "CUPId" and a 7x17 rectangle int the case of the 'U' in "HUG").

Letter Methods and their Contracts

Fontaine recognizes that methods can be used to capture the similarity in shape while abstracting over the color and rectangle size. She defines a new FontBuggle class that is a subclass of Buggle extended with methods that draw the seven letters of the Valentine card. For example, the FontBuggle class has a method for drawing the letter 'U' according to the following contract:

public void U (Color col, int width, int height);

Assume the initial brush state of this buggle is down. Consider the width by height rectangle such that this buggle is in the lower left hand corner facing along the width edge. Executing this method causes this buggle to draw the letter 'U' inscribed in the rectangle, as shown below. The heading of the buggle should not change, but its final position should be width + 1 cells in front of its original position, its final color should be col, and its final brush state should be down.

Fontaine defines similar methods for the other six letters, whose contracts are the same as that for U() except for the shape inscribed in the rectangle. The shapes drawn by the C(), d(), G(), H(), I(), and P() methods are depicted below:

Java Arithmetic

The dimensions in the above pictures are given in terms of Java integer arithmetic. Java integer arithmetic is pretty much what you would expect except that division of two integers always yields the integer that results by truncating (not rounding) the decimal portion of the exact result. For example:

n

n/2

n/3

n/4

5

2

1

1

6

3

2

1

7

3

2

1

8

4

2

2

9

4

3

2

The following equations are also always true (both in Java arithmetic and traditional arithmetic):

1 + (n/2) = (n + 2)/2

1 + ((n - 1)/2) = (n + 1)/2

The reason that we prefer the left-hand side versions to the right-hand side versions in the above diagram is that the left-hand side versions turn out to be more useful when drawing the letters with buggles. (See the note on fencepost errors in the tasks section, below.)

You should also convince yourself that in Java integer arithmetic, the following equation is always true (this equation is not true for traditional arithmetic!):

n = 1 + ((n - 1)/2) + (n/2)

Stringing Letters Together

The final position and heading of a FontBuggle after drawing a letter is designed to facilitate stringing letters together to form words. If the FontBuggle is asked to draw a new letter, both letters will be on the same "baseline", and there will be one cell of space between the previous letter and the new one. For example, consider the following method for drawing the word "CUP":

public void CUP () {
  C(Color.blue, 3, 5);
  U(Color.green, 8, 3);
  P(Color.red, 4, 12);
}

Invoking the CUP() method on a FontBuggle causes it to draw the following letters:

Buggle Jumping

Since letters do not always directly follow one another, it is useful to have the following jump() method, which changes the relative position of a FontBuggle by fwd units in the forward direction and lft units to its left. (Either number may be 0 or negative.)

	public void jump (int fwd, int lft) {
	  brushUp();
	  forward(fwd);
	  left();
	  forward(lft);
	  right();
	  brushDown();
	 }

Because the parameters to jump() are relative to the buggle's current position and heading, the method works regardless of the buggle's initial state. After jumping, it is often desirable to turn the buggle; the following three methods abstract over the three possible ways of turning:

	 public void jumpAndTurnLeft (int fwd, int lft) {
	   jump(fwd,lft);
	   left();
	 }
	 
	 public void jumpAndTurnRight (int fwd, int lft) {
	   jump(fwd,lft);
	   right();
	 }
	 
	 public void jumpAndTurn180 (int fwd, int lft) {
	   jumpAndTurnLeft(fwd,lft);
	   left();
	 }

As an example of buggle jumping, consider the following method:

	public void fourCUPs () {
	  CUP();
	  jumpAndTurnLeft(4, 0);
	  CUP();
	  jumpAndTurnLeft(4, 0);
	  CUP();
	  jumpAndTurnLeft(4, 0);
	  CUP();
	  jumpAndTurnLeft(4, 0);
	}

Invoking fourCups() on a FontBuggle at position (3,3) facing eastward yields the following picture:

fourCUPs Figure

As another example of buggle jumping, consider the following testFont() method that draws the C(), d(), G(), H(), I(), P(), and U() shapes for 5x5, 4x4, 3x5, 4x4, and 4x3 rectangles for both the east and north buggle orientations:

	public void testFont() {
	  testSizes();
	  jumpAndTurnLeft(27,0);
	  testSizes();
	}
	
	public void testSizes() {
	  testLetters(5,5);
	  jump(-42,6);
	  testLetters(4,5);
	  jump(-35,6);
	  testLetters(3,5);
	  jump(-28,6);
	  testLetters(5,4);
	  jump(-42,5);
	  testLetters(5,3);
	  jump(-42,4);
	}
	
	public void testLetters(int w, int h) {
	  C(Color.red, w, h);
	  d(Color.green, w, h);
	  G(Color.black, w, h);
	  H(Color.blue, w, h);
	  I(Color.yellow, w, h);
	  P(Color.magenta, w, h);
	  U(Color.cyan, w, h);
	}

Executing testFont() should yield the following result:

FontTest Figure


Your Tasks

Your tasks in the problem are to define the following eight FontBuggle methods:

You should begin the problem by downloading the HuggleWorld folder from the CS111 download folder. This folder has a file FontBuggle.java that contains skeletons of the eight methods you should define, as well as the jump(), jumpAndTurnLeft(), jumpAndTurnRight(), and jumpAndTurn180() methods described above.

The HuggleWorld folder also contains three applets for testing your methods:

Hints/Notes:


Contest (Everyone should read the following!)

One advantage of methods is that they can be used to significantly shrink the size of a program, as measured by the number of lines of Java code. For the HuggleWorld program, we are having a contest to see how small you can make your FontBuggle class and still have it work correctly. The student who writes the smallest correct FontBuggle class will win a $20 gift certificate to Amazon.com. If more than one student has the same sized smallest code, one will be randomly chosen to win the prize.

Traditionally, program size is measured by the number of lines in the program. Because this metric is very sensitive to the way you format your program (commenting, use of whitespace, placement of squiggly brackets, etc.), we will use a way of measuring the size of a Java program that is insensitive to formatting factors. In particular, we define the following two notions:

  1. The size of a method is one more than the number of statements in the body of the method. The extra one counts the "declaration header" of the method as a statement.
  2. The size of a class is the sum of the sizes of all the methods in the class.

For instance, the size of the jump() method described above is 7, while the three methods jumpAndTurnRight(), jumpAndTurnLeft(), and jumpAndTurn180() each have size 3. So these four methods contribue 16 to the size of the FontBuggle class.

To enter the contest, all you need do is calculate the size of your FontBuggle class and write it on your problem set cover sheet.

Some rules/hints: