Preparation
- Read http://www.drjava.org/docs/user/ch09.html .
What to do
- Start DrJava.
- If you don't have a blank definitions (editor) pane, click on New to create one.
- Copy the buggy TwentyOnePickup.java program at the end of this page, and paste it into the DrJava editor.
- Click save. It should suggest the proper name for the file, TwentyOnePickup.java (the .java extension won't show in the Save As field but the extension will be added automatically).
- Compile and run the program once.
- Try and remove 3 stones. Take a look at the output. You should see that there is a problem.
- Set a breakpoint by placing the cursor on the line in main() where computerMove() is called and selecting "Toggle Breakpoint on Current Line" from the Debugger menu.
- Click reset to terminate the execution.
- Switch to debugging mode by selecting "Debug mode" from the Debugger menu.
- Run it again and try to again remove 3 stones.
- This time the program should pause at the breakpoint.
- Type "numberOfStones" at the prompt in the Interactions pane.
- What is the current value of numberOfStones?
- Resize the Watches pane so it is about half the width of the window.
- Click below name and enter "numberOfStones" (without the quotes).
- You have now seen two ways to examine variables when execution is paused.
- Again click in the Name column of the Watches pane but this time enter "move".
- What is the current value of move?
- Click "Step Into" three times, noticing where the cursor moves to each time.
- You can use this to "single step" your program and see what it is doing. This can be a powerful learning tool as well as a debugging tool.
- Now what is the value of move?
- Click "Step Into" (or "Step Over" it makes no difference here) once more.
- Now what is the value of numberOfStones?
- Now click "Step Out" (you could also click "Step Over" twice).
- What is the value of numberOfStones now? What happened? Do you see the problem? Hint: Primitive type parameters in Java are passed using call-by-value. Think back to the stack of plates example discussed in class.
- After fixing the problems in main (the same mistake was made on two different lines), compile the program and run it again.
- Run the program to completion, entering 3 as the number of stones to remove each time. Confirm that it appears to be working correctly. How many stones does the computer remove on it's last turn?
- The program contains another bug (that I know about). Run the program again. This time try and remove 1 stone on your first move.
- How many stones does the computer remove?
- Click "Reset" to end the execution and switch again to Debug Mode then click "Run".
- Again enter 1 for the player move.
- Execution should again pause at the call to computerMove().
- Single step using "Step Into" until a value has been assigned to move and the value shows in the Watches pane.
- The winning strategy in this game is to try and always leave the pile with a multiple of 4 stones. Can you see the problem here? Since the winning strategy doesn't work (when you took away 1 stone that left a multiple of 4 and the computer can only take at most 3), the computer needs to do something else. Anything you do to make a legal move would be fine. Legal moves are 1-3 stones.
import java.util.*;
public class TwentyOnePickup {
/**
* WARNING!! This version is intentionally buggy.
* Play the game of Twenty-One Pickup.
* The user and the computer take turns removing
* from 1 to 3 stones from a pile. There are 21
* stones in the pile to start with.
* The last one to remove a stone wins.
*/
public static void main(String[] args) {
printInstructions();
// create the initial pile with 21 stones
int numberOfStones = 21;
// keep track of who moved last
boolean playerMovedLast = false;
while (numberOfStones > 0) {
playerMove(numberOfStones);
playerMovedLast = true;
if (numberOfStones > 0){
computerMove(numberOfStones);
playerMovedLast = false;
}
}
// print the outcome
if (playerMovedLast)
System.out.println("Congratulations, you won.");
else
System.out.println("Better luck next time.");
}
/**
* printInstructions prints the initial instructions
*/
static void printInstructions() {
System.out.println(
"The object of this game is to remove the last"
+ " stone.\n"
+ "There are 21 stones in the pile to start with.\n"
+ "You may remove from 1 to 3 stones on each move.\n"
+ "Good Luck!");
}
/**
* playerMove completes one move by the player.
* @param numberOfStones
* The number of stones reamining in the pile.
* @return
* The number of stones remaining after the user's move.
*/
static int playerMove(int numberOfStones) {
int move = getUserMove(numberOfStones);
numberOfStones = numberOfStones - move;
System.out.println("There are " + numberOfStones
+ " stones remaining.");
return numberOfStones;
}
/**
* computerMove completes one move by the computer.
* @param numberOfStones
* The number of stones reamining in the pile.
* @return
* The numberOfStones remaining after the
* computer's move.
*/
static int computerMove(int numberOfStones) {
int move;
if (numberOfStones < 3) {
move = numberOfStones; /* remove the rest */
}
else {
move = numberOfStones % 4;
}
numberOfStones = numberOfStones - move;
System.out.println("The computer removes " + move
+ " stones leaving " + numberOfStones + ".");
return numberOfStones;
}
/**
* getUserMove reads in the user's move, only
* accepting legal inputs.
* @param numberOfStones
* The number of stones reamining in the pile.
* @return
* The number of stones selected for removal by
* the user.
*/
static int getUserMove(int numberOfStones) {
System.out.println("Your move - how many stones"
+ " do you wish to remove?");
int move = scan.nextInt();
while (move > numberOfStones || move < 1 || move > 3) {
if (numberOfStones >= 3)
System.out.println("Sorry," +
" you can only remove 1 to 3 stones.");
else
System.out.println("Sorry, you can only "
+ "remove 1 to " + numberOfStones + " stones.");
System.out.println("How many stones"
+ " do you wish to remove?");
move = scan.nextInt();
}
return move;
}
static final Scanner scan = new Scanner(System.in);
}