CPSC 124, Spring 2006
Lab 6: Writing Subroutines

In this lab, for the first time, you will be writing some complete subroutines. The main point is to get used to the syntax of subroutine definitions, so the subroutines that you write will perform rather simple tasks. Since you will be working on the first programming project this week, the lab is designed to be short enough to finish during the lab period; if you finish this lab before the end of the lab period, you can start working on the programming project.

To begin the lab, you should start up Eclipse and begin a new project. You will need to put a copy of TextIO.java in the project; you can either import it from /classes/s06/cs124 or copy-and-paste it from one of your other Eclipse projects. You will also need to create a class for your program; you can name it DiceSimulator.

Exercise: The exercise for this lab is to write the "Dice Simulator" program described below. Don't forget to follow the rules of good programming style. This includes writing a comment for each subroutine that describes the purpose of the subroutine. The comment should also describe the purpose of each of the subroutine's parameters.

Writing Subroutines

Subroutines are covered in Chapter 4 of the text. Most of what you need to know for this lab has already been covered in class or can be found in Section 4.2. For this lab, all the subroutines that you write will be private static. That is, they will follow the form:

          private  static  <return-type>  <subroutine-name>  ( <parameter-list> ) {

The <return-type> specifies the type of value that is returned; for a subroutine that is not a function, the <return-type> is given as void. The <subroutine-name> is the name that will be used to call the subroutine. And the <parameter-list> specifies what parameters must be provided when the subroutine is called.

A function (that is a subroutine whose <return-type> is not void) must end with a return statement that returns the value of the function. A return value has the form

         return  <expression>;

where the <expression> is a constant, variable, or formula that gives the value of the function. Note that when a return statement is executed, the function is terminiated immediately and the return value is sent back to the place in the program where the function was called.

The Program: Dice Simulator

We have been working with pairs of dice for a while now, and it's the same (int)(6*Math.ran... formula over and over. It would be nice to code this into a function and forget it. (That's one of the points of subroutines.) Of course, it's not always a pair of dice that you want to role. Sometimes, it's a single die, or maybe three or more. It would be nice to have a single function that can roll any number of dice -- we can do that by making the number of dice a parameter. This will make the fucntion more generally useful. (That's the point of parameters.) To be even more general, we can allow dice with varying numbers of sides. The formula for rolling a single N-sided die, of course, would be (int)(N*Math.random()+1). The defintion of the function will then have the first line:

      private static int rollDice(int numberOfDice, int numberOfSides) {

So, start by writing a function named rollDice that takes two parameters of type int. The first parameter is the number of dice to be rolled, while the second parameter is the number of sides on each die. The function should simulate rolling the specified number of dice, and it should add up all the numbers from the dice. (Use a for loop.) It should return the answer. Note that the return type of the function is int since the answer that it returns is an integer. (If you want to test your function, you can write a main routine that simply says, for example, "System.out.println(rollDice(3,6))".)

Next, write the main() routine of the program. For that, you can simply copy the following main() routine. (The easiest way to do that is to open this web page in a browser and copy-and-paste the main routine from this page into your program. The address of the page is http://math.hws.edu/eck/cs124/s06/lab6/.)

   public static void main(String[] args) {
       int sideCount;   // The number of sides on each die.
       int diceCount;   // The number of dice to be rolled.
       int desiredRoll; // The total roll that user wants to get on the dice.
       boolean again;   // Used to check whether the user wants to go again.
       System.out.println("\n\nThis program will perform the following experiment:");
       System.out.println("N S-sided dice will be rolled repeatedly until a total");
       System.out.println("roll of T is obtained, where N, S, and T are numbers that");
       System.out.println("you will select.  You can choose to use between 1 and 5");
       System.out.println("dice, where each die has  between 2 and 20 sides.\n\n");
       do {
           sideCount = askUser("How many sides are there on each die?", 2, 20);
           diceCount = askUser("How many dice do you want to roll?", 1, 5);
           desiredRoll = askUser("What total do you want to roll for?", 
                                                 diceCount, diceCount*sideCount);
           doRollFor(desiredRoll, diceCount, sideCount);
           System.out.print("\n\nAgain? ");
           again = TextIO.getlnBoolean();
       } while (again);

Note that two more subroutines are used in this main routine, askUser and doRollFor. You will have to provide definitions for these subroutines before you will be able to run the program. (Hint: You can get Eclipse to write the outlines of these subroutines for you.)

The subroutine askUser has a return value of type int and has three parameters. The first parameter is a String; it specifies a question that will be asked of the user. The second and third parameters are the minimum and maximum allowed values for the user's response. The return value should be the user's response, and it should be guaranteed to be in the specified range of values. You should use a loop to make sure that the user inputs a legal value.

The subroutine doRollFor does the experiment that is described in the output statements in the main routine. That is, it rolls the dice until the total comes up to be the desired roll that was specfied by the user. The three parameters of doRollFor specify the desired total roll, the number of dice to roll, and the number of sides on each die. To roll the dice, your subroutine should call the rollDice function that you have already defined. It should count the number of tries that it takes to get the specified total, and it should report this number to the user. doOneRoll is a void subroutine; it does not have a return value. (It prints a value for the user to see, but it does not "return" this value in the sense of subroutines. A return value is returned to the point in the program where the subroutine is called; it is not displayed to the user.)

Once you've completed the program, run it to make sure that it works. Try rolling 5 dice with 20 sides each to get a total roll of 100 -- it will probably take a while!

David J. Eck, February 2006