CS100J       Lab 05. Random number game      Spring 2006 

Name _____________________       Section time _______________        Section instructor ___________________

In this lab, you will gain experience with writing simple static methods, learn about random number generation, and learn about class Integer. We suggest you go to the course web page and open this handout in a browser.

We have provided the skeleton code for a game called GuessMyNumber. When complete, the program will choose a random number between 1 and n (where n is a number provided by the player) that the player can try to guess. As the player interacts with the program, the program will respond with appropriate messages.

Task 1. The 'wrapper classes' Integer, Boolean, and Character

After the lab, STUDY SECTION 5.1 OF THE TEXT!

Primitive types are different from class-types like String and JFrame, and one can't use one in a place that requires the other. It would be nice to be able to use values of primitive types as if they were in objects (manilla folders). Java provides "wrapper classes" for this purpose. A manilla folder of class Integer has one field, of type int, which contains an integer. Class Integer is called a "wrapper class", because a folder of that class "wraps around" the int value, much like you wrap a sandwich in saran wrap.

If you want to use the value 52 as an object, then use this expression:

new Integer(52)

which creates a manilla folder of class Integer and puts the int value 52 in it.

In Java, each primitive type has a corresponding wrapper class. They are discussed in Chapter 5 of the text. Here, we discuss only class Integer. Click here to open the API spec for class Integer in a new browser window: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Integer.html. Scan through the methods in class Integer, so you have an idea what is available.

Type the following into the interactions pane and write down the result.  Write "error" if you get an error message.

Integer i= new Integer(7);  
int j= i can't do this!
int j= i.intValue() this will work
j  

String num= "107"  
int k= num can't do this
int k= (int) num or this
int k= Integer.parseInt(num) but you can use a method from class Integer!

Task 2. Understanding the skeleton code for a game

Download the skeleton program from the web, store it in a new folder(!!!), and open it in DrJava. Study the program.We have defined the following variables necessary for the game:

private static Integer myNumber the random number chosen by the computer
private static int max the random number is chosen in the range 1..max, where max ≥ 1
private static int numGuesses the number of guesses attempted by the user
private static boolean playerGuessedMyNumber

true if and only if the player guessed the computer's number correctly. We can say this more succinctly, by saying that its value is the value of this sentence:

"the player guess the number correctly"

We call the collection of definitions of these variables the class invariant. "Invariant" means "unchanging". The class invariant is true when the values of the variables are usch that thevariable specifications (listed in the right column of the table) are true. We expect this class invariant to be true when the program starts and to remain true before and after each call on a method of the class. So, whenever you are writing one of the method bodies, you can assume that this class invariant is true, and the method body that you write must terminate with the class invariant true again. So you have to continually look at these variables and their definitions when writing method bodies.

We have also defined the following method:

public static void chooseNumber(int n) Choose a number between 1 and n. If n < 1, then tell the user the number is not good and simply return without choosing a number.

A player who wants to start a game calls this method, giving as argument the range of integers in which they are willing to guess. So, for a call chooseNumber(10), the program chooses a number in the range 1..10 and the user will try to guess it. For a call chooseNumber(2), the number to be guessed is in the range 1..2 --i.e. it is either 1 or 2.

Take a look at the body of method chooseNumber and read the beginning of Section 5.6 and section 5.6.1 of the class text (you can do the latter after doing this lab, perhaps back in your room). Those sections tell you about random numbers on the computer and show you how a random double number that is nonnegative and less than 1 is changed into an integer in the range 1..n.

Temporarily, make the four fields of the class public, so you can reference them from the Interactions pane of DrJava while testing. Now, in the Interactions pane, call procedure chooseNumber a few times and see what values it puts in field myNumber. This way, you will get an idea how the method is working.

Note that since the method and variables are static, you don't have to create a GuessMyNumber object.

Task 3. Guessing a number

The player needs a way to tell the computer the number that the player guesses. Implement a procedure called guess(int), and make sure it satisfies the following points:

The actual messages are up to you, but they should be something like the following:

"That's right! My number is <myNumber>"
"Sorry, my number is lower than <the player's guess>"
"Sorry, my number is higher than <the player's guess>"
"The computer hasn't chosen a number yet!"
"You've already guessed the correct number!"

The messages shouldn't mention the private variables by name, because the player doesn't know about them.

Before you write the method body, type in the specification-comment for the method and the method header. The specification must be precise and thorough. It should say WHAT the method does. It shouldn't mention the private variables by name, because the player doesn't know about them.

Before beginning the method body, compile the program to make sure the header (and braces { }) are syntactically correct.

Write and test the method body incrementally! For example, above, we listed three tasks the method should perform. Write code for the first and then test what you have done by writing appropriate calls on the method. Only when you are satisfied that that part is correct should you go on to the next one. This business of incremental coding and testing is extremely important.

Task 4. Rating the player

After guessing correctly, the played may want to know how well they played the game. Implement a procedure rateMe(), which satisfies the following points:

Of course, you do not have to print a special message for every possible number of guesses; there could be infinitely many! Instead, form rating groups such as [1-2 guesses], [3-4 guesses], [5-6 guesses], and [7 or more guesses]. Use class variable numGuesses to determine to which group the player belongs and print a message based on that.

For example, you could print the following:

"You're amazing! You needed only <numGuesses> guesses!"
"You're a really good guesser! You needed only <numGuesses> guesses!"
... and so on.

Task 5. Play the game using the Interactions pane of DrJava! :)

When your two methods are finished, and you tested enough to believe they are correct, then make all fields private again. Then, to play a game, do this:

Don't forget to show your TA or consultant the code you wrote!

In rating a player, 7 or more guesses is considered bad. But that doesn't take into account the size of the range. If the range is 1..10000, 7 guesses might be good! If the range is 1..2, 7 guesses is truly bad --the player had to type the wrong guess 8 times! Can you figure out a method for determining a good number of maximum guesses based on the range of the random numbers generated?