DrJava Debugger

Preparation

  1. Read http://www.drjava.org/docs/user/ch09.html .

What to do

  1. Start DrJava.
  2. If you don't have a blank definitions (editor) pane, click on New to create one.
  3. Copy the buggy TwentyOnePickup.java program at the end of this page, and paste it into the DrJava editor.
  4. 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).
  5. Compile and run the program once.
  6. Try and remove 3 stones. Take a look at the output. You should see that there is a problem.
  7. 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.
  8. Click reset to terminate the execution.
  9. Switch to debugging mode by selecting "Debug mode" from the Debugger menu.
  10. Run it again and try to again remove 3 stones.
  11. This time the program should pause at the breakpoint.
  12. Type "numberOfStones" at the prompt in the Interactions pane.
  13. What is the current value of numberOfStones?
  14. Resize the Watches pane so it is about half the width of the window.
  15. Click below name and enter "numberOfStones" (without the quotes).
  16. You have now seen two ways to examine variables when execution is paused.
  17. Again click in the Name column of the Watches pane but this time enter "move".
  18. What is the current value of move?
  19. Click "Step Into" three times, noticing where the cursor moves to each time.
  20. 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.
  21. Now what is the value of move?
  22. Click "Step Into" (or "Step Over" it makes no difference here) once more.
  23. Now what is the value of numberOfStones?
  24. Now click "Step Out" (you could also click "Step Over" twice).
  25. 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.
  26. After fixing the problems in main (the same mistake was made on two different lines), compile the program and run it again.
  27. 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?
  28. The program contains another bug (that I know about). Run the program again. This time try and remove 1 stone on your first move.
  29. How many stones does the computer remove?
  30. Click "Reset" to end the execution and switch again to Debug Mode then click "Run".
  31. Again enter 1 for the player move.
  32. Execution should again pause at the call to computerMove().
  33. Single step using "Step Into" until a value has been assigned to move and the value shows in the Watches pane.
  34. 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);
}