Graphic by Keith Ohlfs |
|
The purpose of this problem set is to give you more experience with recursion and writing recursive methods which return values.
Homework Problems :
Save the modified Patchwork.java
, HarvestWorld.java
and
MazeCounterWorld.java
files in the ps5_programs
folder. Submit the entire ps5_programs
folder to your
drop folder on the cs111 server. Turn in a hardcopy of the modified
Patchwork.java
, HarvestWorld.java
and
MazeCounterWorld.java
.
When submitting your hardcopies, we ask that you turn in only one package of materials. Please staple your files together with a cover page, and submit your hardcopy package by placing it in the box outside of Stanzi's office (E106, across from E101).
Reminders
Homework Problem 1: Patchwork
Your goal in this problem is to write a recursive method that draws the following Picture in PictureWorld:
This picture is specified by the following method in the file Patchwork.java within the folder Patchwork:
In this problem, you are to write a recursive definition of the following method:
public Picture patchwork(int levels, Color c1, Color c2, Color c3, Color c4)
Returns a picture of the above pictured staircase pattern nested levels levels deep, using colors c1, c2, c3, and c4
To see the picture created by patchwork(n, Color.red, Color.yellow, Color.blue, Color.green) for values of n between 0 and 6, experiment with the test applet Patchwork.java within the Test subfolder of the Patchwork folder.
In your definition, you should pay careful attention to how the color parameters shift in recursive calls. Your final definition should be very short. You should be able to write the entire definition in a handful of lines without defining any auxiliary methods of your own. However, you should use the following auxiliary methods, which we have provided for you:
public Picture patch(Color c) Return a picture that consists of a solid patch of color c public Picture fourPics(p1, p2, p3, p4) Return a picture that consists of four pictures p1, p2, p3 and p4, with p1 in the upper left corner, p2 in the upper right corner, p3 in the lower left corner and p4 in the lower right corner.
Note: Please read this entire problem carefully. Simply generating the correct final pattern is not enough to get full credit. Each specified method must behave as described below.
Bagels in BuggleWorld grow in fields (you knew that, didn't you?).
Twice a year the Harvester
buggles go out and harvest
bagels so that buggles in BuggleWorld will have bagels to eat and
play with throughout the year. Bagels are the most important
commodity in BuggleWorld. Therefore, their harvesting procedure is
quite complex and elaborate. It is described below:
Harvester
is assigned a field of bagels to
harvest. The buggle does not know the width or height of the bagel
field. The buggle starts in the left bottom corner of the field
and harvests bagels one row at a time (a row is a vertical column
on the BuggleWorld grid). It doesn't matter if the buggle chooses
to harvest the closest row first and work down to the end of the
field or to walk to the end of the field and harvest rows on the
way back to the beginning. Note that there are no bagels planted
in the bottom horizontal row of the field. Instead, that is the
path that buggles walk on to get from row to row.
Harvester
buggles do all the work,
their supervisors want to be able to quickly look at the field
and see how it did. It's a bit difficult to see the entire
field, so the Harvester
buggle must mark each row
indicating whether or not the row did well. Bad rows (fewer
bagels than blank spaces) are marked red and will get more
fertilizer and attention in the next growing season. Good rows
(more bagels than blank spaces) are marked green. Fair rows
(same number of bagels as blank spaces) are left uncolored.
Each row is also tagged with the number of empty spaces (i.e.
spaces covered with black tarp). See the pictures below for
clarification.
Harvester
buggle must count the
number of bagels harvested in the field and report that to her
supervisor.
The following two pictures show the state of a field before and after the buggle has harvested it.
|
|
Your task is to write the methods that will make the
Harvester
buggle do its job. You are free to write any
auxiliary methods needed. At a minimum, you must define the following
methods for the Harvester
class. Each method must perform as
specified in the comments below:
public int harvestField() // This method asks the buggle to harvest each row of a field // and to return the number of bagels harvested. // This method meets the invariant that the buggle's state // (position, heading, color, and brush state) will // not be changed by execution of this method. // Assumes the buggle's brush is initially up.
public int harvestRow() // This method asks the buggle to harvest the row of bagels // to the left of the buggle and return the number of bagels // in this row. Harvesting involves the following steps: // --pick up and count all the bagels in the row // --put the bagels out to dry in a row starting from the bottom // but not including the very bottom row // --pulling the tarp over the rest of each row by walking to the // end of the row and coloring the row black until you've reached // the bagels // --marking the row as fair (no color), good (green), or bad (red) // by coloring the first (bottom) square of each row. // A row produced a good harvest if there are more bagels than // blank spots. A row produced a bad harvest if there are fewer // bagels than blank spots. // --marking the row by dropping the number of blank spots in the // bottom square. // This method meets the invariant that the buggle's state // (position, heading, color, and brush state) will // not be changed by execution of this method. // Assumes the buggle's brush is initially up.
public int harvestBagels() // This method picks up and counts the number of bagels // between the buggle and the wall in front and returns the // number of bagels. // This method meets the invariant that the buggle's state // (position, heading, color, and brush state) will // not be changed by execution of this method. // Assumes the buggle's brush is initially up.
public void stackBagels(int bagelCount) // This method creates a stack of bagels in front of the buggle // with the specified number of bagels. This method assumes that // there will always be at least enough space in front of the buggle // for the bagel stack. // This method meets the invariant that the buggle's state // (position, heading, color, and brush state) will // not be changed by execution of this method. // Assumes the buggle's brush is initially up.
public int pullTarp() // This method draws a black line from the wall in front of the buggle // to the current cell in front of the buggle (ie do not color the cell // the buggle is on when the method is invoked). This method returns // the number of cells colored. // This method meets the invariant that the buggle's state // (position, heading, color, and brush state) will // not be changed by execution of this method. // Assumes the buggle's brush is initially up.
public void markRow(int bagelCount, int spaceCount) // This method colors the cell the buggle is on green if // bagelCount is greater than spaceCount. // The cell is colored red if bagelCount is less than spaceCount. // The buggle also marks the cell with the spaceCount (using dropInt()). // This method meets the invariant that the buggle's state // (position, heading, color, and brush state) will // not be changed by execution of this method. // Assumes the buggle's brush is initially up.
Notes:
With this method, you need not worry about having to move the buggle in order to paint the cell underneath it.
Maisy Buggle comes from a long line of maze-navigating buggles. But unlike other buggles, she is not satisifed with stopping when she finds the first bagel in a maze. She wants to explore the world and find out how many bagels there are in the entire maze! For instance, suppose Maisy starts at "home" (facing eastward at point (1,1)) in the following maze:
Using the same maze-navigating strategy followed by the PathFinder buggle described in lecture 12, Maisy can traverse the entire maze and determine that it contains 17 bagels. (You should review the PathFinder strategy by studying the code for findBagel() in PathFinderWorld.java in lec12_programs, which is located in the CS111 download folder.) Suppose that, after exploring the submaze accessible from a given cell, Maisy writes in the cell the number of bagels in that submaze. Then after she returns to her home position, the maze would be annotated as follows.
Note that the number in each cell is the number of bagels to the left, right, in front of, and under Maisy when she is in a cell (assuming she is facing the direction in which she entered the cell).
To get a better sense for how the above numbers are generated, you should experiment with the test applet MazeCounterWorld.html within the Test subfolder of the MazeCounter folder of ps5_programs. This applet has a parameter window that look like this:
The numbers in yellow control the side length of the maze and the number of bagels placed randomly in the maze. If you change these and press the Reset button, a new maze will be created with these parameters. The cyan-colored box labelled result is where Maisy writes the total number of bagels in the maze when she returns home. For example, after Maisy has explored the maze depicted above, the parameter window changes to:
Before proceeding with this problem, you should play with the test applet and study the above pictures until you understand how the numbers for each cell are determined.
Maisy is a member of the MazeCounter class of buggles. Your goal in this problem is to define a collection of methods in the MazeCounter class that direct Maisy to count the number of bagels in any maze, also annotating the cells with numbers, as shown above. You should flesh out the skeleton of the MazeCounter class in the MazeCounter folder of ps5_programs. This skeleton contains a "stub" version of a method with the following contract.
public int countBagels()
Counts the number of bagels to the left, right, in front of, and under this buggle.Drops this number in the cell under this buggle, and then returns it.Leaves the state of this buggle unchanged.
You should replace the stub with a method that works. As part of your solution, you should define any auxiliary methods that you find helpful. It is strongly recommended that you use a decomposition similar to the one used by the PathFinder buggle in lec12_programs. Your solution should work for any maze size and any number of bagels. (Warning: do not attempt to place more bagels in the maze than there are grid cells. This situation is not handled gracefully, and will cause your machine to crash.)
In order to drop an integer in a cell, you will need to invoke the following brand-spanking-new Buggle primitive. (Only the buggles in MazeCounter world understand this method.)
public int dropInt (int n)
"Drops" the integer n in the cell of this buggle. The cell shows the most recently dropped integer. This method returns the integer that was dropped.