Graphic by Keith Ohlfs

CS111, Wellesley College, Spring 1998

Problem Set 9

Due: Friday, April 17 by 4:00 p.m.

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


Notes:


Reading Assignment:

Take-Home Exam Announcement

CS111 Exam 2 will be a take-home exam that will be handed out on Friday, April 17, and will be due on the morning of Monday, April 27. You will have no other assignments during this period of time. The take-home exam will be very much like a problem set, except that (1) you may not collaborate with anyone else on the exam and (2) it counts for more points toward your final grade than a problem set does.

About this Problem Set

The purpose of this problem set is to give you practice with iteration via tail recursion, while loops, and for loops. Homework Problem 2, which involves the abstractions that model hands of playing cards, gives you some initial experience with data abstraction and processing collections of objects. These will be the themes for the rest of the course.

There are 2 pieces to this problem set: the laboratory assignment and the homework assignment. There is no pre-lab assignment for this problem set. You are required to do both pieces. We recommend that you do the laboratory problem during your lab section and the homework problems after completing the prelab and lab assignments.

All code for this problem set can be found in the ps9_programs folder, which you can download from the CS111 download folder.

How to turn in this Problem Set

Laboratory Problem: Save the modified PolygonWorld.java and FlowerWorld.java files in the Polygons folder. Upload the entire folder to your ps9 drop folder. Turn in a hardcopy of the PolygonWorld.java and FlowerWorld.java files.

Homework Problems :

For Homework Problem 1, save the modified NestedFrames.java file in the NestedFrames folder. Upload the entire folder to your ps9 drop folder. Turn in a hardcopy of the NestedFrames.java file.

For Homework Problem 2, save the modified Honest.java, Safe.java, and Hoarder.java files in the Cards folder. Upload the entire Cards folder to your ps9 drop folder. Turn in a hardcopy of the Honest.java, Safe.java, and Hoader.java files. If you keep getting "Connection not in place errors" when uploading, then upload the Cards folder in smaller chunks rather than all at once. That is, select one quarter to one half of the files and move the selection into the Fetch folder. Do this until you have moved all of the files.

Turn in only one package of hardcopy materials. Staple your files together with the cover page, and submit your hardcopy package by placing it in the box outside of Jennifer's office (E104, directly across from E101).

Reminders


Laboratory Problem: Polygons

Task 1. Polygons

In this lab you will program turtles to draw regular polygons. A regular polygon has sides of equal length and angles of equal length, as shown in the following images:

We will draw these polygons using three strategies for expressing iteration:

To begin this problem, download the ps9_programs folder from the CS111 download folder. Open the project file Polygons.proj in the Polygons folder, and then open PolygonWorld.java. In this task, you will be fleshing out skeletons for various methods defined in the PolygonMaker class within PolygonWorld.java.

A turtle can draw a polygon by repeatedly drawing a side and then turning by an angle of (360.0/sides), until it has drawn the specified number of sides. One strategy for encoding this iteration is to use tail recursion. Below is the skeleton for such a such a strategy. The polygon() method invokes the tail recursive polygonTail() method with the appropriate initial parameters for the state variables of the iteration. Your first goal is to fill in the missing body of polygonTail().

	public void polygon (int sides, int length) {
		double angle = 360.0/(double)sides;
		polygonTail(sides, length, angle);
	}
	
	public void polygonTail(int numSides, int length, double angle){
		// Flesh out this body. 
	}

Next, flesh out the bodies of the polygonWhile() and polygonFor() methods. As suggested by their names, the polygonWhile() method should express the polygon-drawing iteration via a while loop, and the polygonFor() method should express this iteration via a for loop. You can test your methods by selecting the appropriate checkbox in the Parameter window before pressing the Run button in the Turtle window.

2. Polygon Flowers

Now that you can draw a polygon, you can use this method to draw polygon flower. A polygon flower is defined by the number of petals and the number of sides of each petal. Each petal is a regular polygon, and the petals are rotated with respect to one another. The angle of rotation is equal to (360.0/petals). Some sample flowers are as follows:

As with the polygon, we will write methods to draw these flowers using tail recursion, while loops and for loops. Fill out the skeletons for flowerTail(), flowerWhile(), and flowerFor() in the FlowerWorld.java file. Test out your methods by executing FlowerWorld.html and selecting the checkbox corresponding to the method you want to test.

Submission Details: For your softcopy submission, turn in your final version of the Polygons folder to your PS9 drop folder. For your hardcopy submission, turn in your final versions of PolygonWorld.java and FlowerWorld.java.


Homework Problem 1: Nested Frames

In this problem you will use iteration in to draw two-colored nested frame patterns like those shown below:

Each of the four patterns pattern consists of concentric rectangular frames that have the same thickness and alternate between two colors. In the above example, each target has 10 nested frames, each of whose thicknesses is 1/20 of the dimensions allocated to the pattern.

In Picture World, such patterns can be drawn as a sequence of concentric filled rectangles, where the rectangles are draw from the outside in. You have been provided with the following method for creating a centered rectangular picture:

public Picture centeredRect (double fraction, Color c)
Returns a rectangle filled with color c that is centered in the picture canvas in which it is drawn. The width and height of the rectangle are each the given fraction of the enclosing picture canvas's width and height. The fraction argument must be between 0 and 1.

For example, using this method, here is a recursive implementation of the nested pattern:

	public Picture nestedRec(int levels, double thickness, Color c1, Color c2) {
		if (levels == 0) {
			return empty();
		} else {
			return overlay(nestedRec(levels - 1, thickness, c2, c1),
			               centeredRect(levels*thickness, c1));
		}
	}

Here, levels is the number of nested frames, thickness is the thickness of each frame edge, c1 is the outermost color, and c2 is the color that alternates with c1. The recursion accumulates a final picture that consists of levels centered rectangles overlayed on top of one another. Note how each level of the recursion decrements levels by 1 and swaps c1 and c2 (so that c2 is the outermost color in the nested subpicture). This strategy is not a tail recursive one, since there is still a pending overlay operation to be performed after the recursion returns.

In the rest of this problem, you will expore three iterative strategies for expressing the nested box pattern. You will be fleshing out the following skeletons in the file NestedFrames.java within the folder NestedFrames:


public Picture nestedIter(int n, double thickness, Color c1, Color c2) { // This method contains the initial call to nestedTail, which does all the work. return nestedTail(n, thickness, c1, c2, empty()); } public Picture nestedTail(int n, double thickness, Color c1, Color c2, Picture ans) { // nestedTail should be a tail recursive method that returns a Picture // that is the nested frames pattern.   // Replace the following stub by a correct definition. return empty(); } public Picture nestedWhile(int n, double thickness, Color c1, Color c2) { // Use a while loop to accumulate and return a Picture // that is the nested frames pattern.   // Replace the following stub by a correct definition. return empty();   } public Picture nestedFor(int n, double thickness, Color c1, Color c2) { // Use a for loop to accumulate and return a Picture // that is the nested frames pattern.   // Replace the following stub by a correct definition. return empty(); }

Your task is to flesh out all three methods so that they have the same behavior as nestedRec. You can test your methods by executing the NestedFrames.html applet. This will give you a window like that pictured at the beginning of this problem. By selecting an integer in the righmost choice box, you can change the nesting level of the patterns. Your code does not have to take care of calculating the thickness; this calculation is already performed by the testing enviroment.

The patterns are arranged as follows inside the NestedFrames Applet window:

In your definitions, pay attention to the following notes:

Submission Details: For your softcopy submission, turn in your final version of the NestedFrames folder to your PS9 drop folder. For your hardcopy submission, turn in your final version of NestedFrames.java.


Homework Problem 2: I Doubt It!

In this problem set, you will study, experiment with, and extend a Java implementation of a card game known as "I Doubt It". (The game is also known by several other names, most of which are not printable here!)

The Rules of The Game

Here are the rules for a game of I Doubt It:

  1. The game is played by players sitting around a table. There can be any number of players, but we will assume four players in the Java version of the game. We will refer to the players in clockwise order (looking down on the table from above) as Player0, Player1, Player2, and Player3. (Labelling the players starting with 0 may seem strange, but it turns out that this corresponds to the most convenient numbering scheme in Java.)
  2. A deck of cards is shuffled, and all the cards are dealt to the players in cyclic order around the table. Each player keeps her cards secret from the other players.
    1. The goal of the game is to be the first player to get rid of all her cards. On each move, the current player is asked to discard cards with a certain value from her hand. Play starts with a request for Player0 to discard her twos, and proceeds in clockwise order around the table, with the value incrementing on each move. That is, Player1 is asked to discard threes, Player2 is asked to discard fours, Player 3 is asked to discard fives, Player0 is asked to discard sixes, and so on. When the value reaches aces, it then wraps back to twos for the next player. Note that the next player is always to the left of the current player (relative to the player, not looking down from above); and the previous player is to the right of the current player.
  3. When asked to discard a particular value, the current player removes 0 to 4 cards from her hand and places them face down on a discard pile in the center of the table. She then declares the number of cards of the requested value that she is discarding. She may be telling the truth or she may be bluffing. If she is telling the truth, then she really did discard the number of the requested value of cards that she declared. However, she may also be bluffing, in which case one or more of her discards do not have the requested value. A player typically bluffs when she does not have any cards of the requested value but want to pretend like she does. (In the real game, the player may also lie about the number of cards they have discarded, e.g. claiming to discard four cards while actuallly discarding 5 or 6. To simplify matters, we will assume that a player always tells the truth about the number of cards she is discarding.)
  4. After a player has declared her discards, one of the following takes place:
    • If the current player has discarded 0 cards, she must pick up all the cards in the discard pile and add them to here hand. Since the goal is to get rid of cards and not accumulate them, a player will often bluff rather than discard 0 cards.
    • If the current player has discarded 1 to 4 cards, the other players are asked in clockwise order if they believe the current player is telling the truth.
      • If another player believes the current player is telling the truth, she says so.
      • If another player believes the current player is bluffing, she declares "I Doubt It!". There are two possible outcomes in this situation:
        1. If the doubting player is correct (i.e., the current player is bluffing), then the current player must pick up all the cards in the discard pile.
        2. If the doubting player is incorrect (i.e., the current player is telling the truth), then the doubting player must pick up all the cards in the discard pile.
  5. Play proceeds in the above fashion until one player discards all of her cards, at which point she wins the game.

The IDoubtIt Applet

The I Doubt It game has been encoded into an applet that you should experiment with before proceeding with this problem. Execute the Applet Viewer on the IDoubtIt.html applet within the Test subfolder of the Cards folder in the ps9-programs folder. (Do not run the version of IDoubtIt.html that is directly in the Cards folder; you will need to finish your assignment before this version will work correctly.)

Executing this applet will create a window that allows you to select the strategies for four computer players that will play the I Doubt It game. Here is a brief description of the strategies:

After selecting the four strategies, you can play any number of games by pressing the Play button with a text field value specifying the number of games. If the verbose? checkbox is turned on, a transcript of the moves and sequence of states in the games will be displayed in the standard output window (stdout). Study the first few moves of a game to make sure that you understand how each strategy is working. At the end of the sequence of games, a summary is printed that indicates how many times each strategy one. If you turn the verbose? checkbox off, a single line will be printed for each game followed by the summary. This makes it easier to experiment with larger numbers of games.

You must be somewhat careful in your selection of four strategies if you want to avoid an infinite loop. For example, four Clueless players will never make any progress on a game, nor will four Hoarders.

The Java Implementation of the Game

The Cards folder contains numerous Java files that implement various aspects of the game. Most of these files are complete working versions. The only files that are not completely fleshed out are three of the strategy files: Honest.java, Safe.java, and Hoarder.java. You will need to modify these in your assignment (see below).

Most of the files implement various class that are useful abstractions in the game. For example:

To work on this assignment, you do not need to understand the implementation details of these classes. As with any good data abstraction, all you need to understand is the contracts for these classes. Many of these can be found in the Card Contracts.doc file in the Cards folder. Jennifer discussed these in her class last Friday, and Lyn will discuss them in class this Wednesday. Also, a significant portion of this Wednesday's lecture will be devoted to talking about the contracts and structure of the I Doubt It program.

Other classes implement details of the game:

Of this latter bulleted list of classes, you should study all the classes except for the IDoubtIt user interface,whose details are not important. Again, we will spend time in lecture discussing details of these classes.

The Homework Assignment

Although you are asked to study much code for this assignment, the amount of code you have to write is fairly small. In particular, you have to flesh out three methods, one in each of the files Honest.java, Safe.java, and Hoarder.java.

Before explaining the assignment, a few notes on the structure of an I Doubt It player class. Each such class must be a subclass (direct or indirect) of the Player class. Every player class must implement two methods:

public Hand discard (Value v);
The player has been asked to discard cards with value v.The player removes some cards from her hand and returns the collection of discarded cards as a Hand instance.In this version of the game, it is illegal to return a handwith more than four cards, though not all the cards need have value v. Returning an empty hand is an admission that the player does not have any cards with the given value; in this case the player must pick up the entire discard pile.

abstract public boolean doubt (Player p, int num, Value v);
Player p has claimed to have discarded num cards with value v. Returns true if this player doubts player p's claim, and false otherwise.

For example, here are the methods that implement the behavior of the Clueless class:

	public Hand discard (Value v) {
		return new Hand();
	}
	
	public boolean doubt (Player p, int num, Value v) {
		return false;
	}

You should also study these methods in the Liar, Erratic, and Bluffer classes to see how they work.

In the following problems, you will be implementing these methods, or related auxiliary methods, in the Honest, Safe, and Hoarder classes.

Part a. Honest

Flesh out the implementation of the discard() method to implement the honest strategy. Be careful of the order in which you remove cards or you may miss some of them!

Part b. Safe

In order to determine whether it's safe to doubt another player, a Safe player calls the following auxiliary method:

public int countCardsWithValue(Value v)
Return the number of cards in this player's hand that have value v.

Implement this method.

Part c. Hoarder

In order to determine whether she is in hoarding mode or jettison mode, a Hoader player must know whether she has a hand that contains at least one of each value of card. Complete the definition of Hoarder by fleshing out the skeleton of the following method:

public boolean haveAtLeastOneOfEachValue()
Return true if this player's hand contains at least one of each possible card value.Otherwise return false.