CS 120 Lab 08
Making Decisions
Tom Linton, http://www.cs.moravian.edu/~linton
Moravian College, Spring 1999

Name(s):


You may work in pairs on this lab, and it is due in three weeks (one week, plus Spring break, plus another week).

Since this lab is long and has a lot of important information near the top, here is a shortcut (for later use) to the activity questions. 


Introduction and Background:

Chapter 4 introduces several fundamental object-oriented concepts.  The more practice you get using these concepts in the development of programs, the more natural they will become.  This lab walks you through the development of an application that uses objects to play roulette (actually, a slightly simplified version of roulette). You will meet two new concepts in this lab which areclosely related. The first is the basic decision making statement of Java, the if statement, which allows your program to proceed along different routes, depending on the answer to a question. The second involves some of Java’s basic boolean connectives, or "question asking" building blocks and combination methods. Tests for if statements are normally boolean valued (true or false) and many tests are more complicated than simple yes-no or true-false questions. For example, you may have an unknown integer called x. When x is both larger than 1 and less than 10, you want to print x, but if x is larger than 10, or negative, you need to do something else. In order to decide what to do, you need to test if x is bigger than 1 and if x is less than 10, preferably this test could be done "all at once", but that requires the boolean connective "and", to connect the two tests
"is x > 1?" and "is x < 10?".

The main boolean relations are:

The main boolean connectives are:

We won’t use too many boolean connectives nor too many boolean tests, but boolean values are a part of all if statements, so we’ll need a few today.

The if statement's basic syntax:

The syntax for a basic decision making construct in Java is:
if (boolean test condition){
   true;
   statement;
   block;
}
else {
   false;
   statement;
   block;
}
next statement;


When the test condition in parenthesis is true, Java will execute the "true block", skip the "false block" and go on to the next statement after the false block. If the test condition is false, Java will skip the "true block", execute the "false block" and then go on to the next statement following the false block. Suppose you would like to take an integer N (which already exists and is properly declared as an int) and, when N is even, divide it by 2 and then subtract 3 from the result, but when N is odd, you’d like to multiply it by 8 and then subtract 5 from the result, and in both cases, printout the result. The Java code would look like this:
 

if ( (n % 2) == 0) // test if N is even {
   N = N / 2; // do this if N is even, skip if N is odd.
   N = N - 3;
}
else {
   N = 8*N - 5; // do this if N is odd, skip if N is even.
}
System.out.println("The value of N is: " + N); // always do this.


Whenever one of the blocks of statements to execute when the condition is true, or false, consist of a single statement, you can delete the block braces, "{" and "}", so the above code is equivalent to:
 

if ( (n % 2) == 0)
   N = (N / 2) - 3;
else
   N = 8*N - 5;
System.out.println("The value of N is: " + N);


Notice that the condition you’re testing must go inside parenthesis, and that the line containing the reserved word if has no semicolon. It is standard practice (and required in this course) to indent the "true block" and "else block", just like the body of a method. Sometimes, the "else block" will be empty, in which case, you just remove it altogether. For example, if you want to ensure that a double x is positive (by essentially taking its absolute value), you could use:
 

if ( x < 0)
   x = -x;
System.out.println("The absolute value of x is: " + x);
In this case, the indented line will be executed whenever ( x < 0 ) is true, and skipped, whenever ( x < 0 ) is false. In either case, the println statement will be executed.

Activities:

Perform the following activities, in order, recording any information requested in the space provided.
 
  1. Create a directory called lab8 in your account and copy the linked file called Roulette.java, into that folder. The file Roulette.java is shown here for your convenience.
import simpleIO.*;

//*********************************************************************
//   Class Roulette contains the main setup for a roulette game.
//*********************************************************************
public class Roulette {

   //==================================================================
   //  Contains the main processing loop for the roulette game. The
   //  program keeps running as long as done is false.
   //==================================================================
   public static void main (String[] args) {

      //create a new Player, set the bankroll to $100, and initialize
      // the "is done?" boolean flag.
      Player player = new Player (100);
      boolean done = false;

      // Keep playing the game until its done (this is the while loop)
      while  (!done) {
         // display the bankroll and print a blank line.
         player.stdin.displayResult ("Cash available: " + player.cash());
         player.stdin.displayResult (" ");
         done = !player.spinAgain();
         player.stdin.displayResult (" ");
      } // end of the while loop of the main method.
    } // method main.

} // class Roulette.
 
 

//*********************************************************************
//   Class Player represents one roulette player. Note the "legality"
//   of defining two classes in a single file here.!
//*********************************************************************
class Player {
   private int bet, money;
   public SimpleGUI stdin; // stdin abbreviates standard input and
                           // this IO object is used outside the class.

   //==================================================================
   //  This Player constructor sets up the initial bankroll and IO device.
   //==================================================================
   public Player (int initialMoney) {
      money = initialMoney;
      stdin = new SimpleGUI();
   } // constructor Player.

   //==================================================================
   // Returns this player's current bankroll. This is an accessor method.
   //==================================================================
   public int cash() {
      return money;
   }  // accessor method cash.

   //==================================================================
   //  Prompts the user and reads betting information.
   //==================================================================
   public void makeBet() {
      bet = stdin.getInt ("How much (an integer) to bet? ");
      money = money - bet;
   } // method makeBet.

    //==================================================================
    // Determines if the player wants to spin the wheel again.
    // Whenever the user enters a string which begins with y or Y,
    // this method returns true, otherwise it gives false.
    //==================================================================
   public boolean spinAgain() {
      String answer = stdin.getString("Spin again? [y/n] ");
      return ((answer.charAt(0) == ’y’) || (answer.charAt(0) == ’Y’) );
   }  // method spinAgain.

} // class Player.

//*********************************************************************
//   Class Wheel represents a roulette wheel and its operations.  Its
//   data and methods are static because there is only one wheel.
//*********************************************************************
class Wheel {

   final static int RED = 1;
   final static int BLACK = 2;
   final static int NUMBER = 3;
   private static int ballPosition;
   private static int color;
   private final static int POSITIONS = 37;

   //==================================================================
   //  Presents betting options and reads player choice.
   //==================================================================
   public static int betOptions (SimpleGUI ioDevice) {
      ioDevice.displayResult ("1. Bet on red");
      ioDevice.displayResult ("2. Bet on black");
      ioDevice.displayResult ("3. Bet on a particular number");
      return ioDevice.getInt ("Your choice? ", RED, NUMBER);
   } // betOptions method.

} // class Wheel.
 

  1. In its present form, the program simply loops as long as the player responds that they want to spin again, doing nothing more than asking if you’d like to spin again and displaying your bankroll each time. Carefully trace the processing as it currently exists. Compile and execute the program. After you (eventually) answer "no" to the spin again question, close the SimpleGUI window, via the "File" -> "Quit" menu option.
  2. At the beginning of the "while loop" inside the main method, insert a call to the makeBet method of the player object.  At this point the makeBet method simply reads the amount of the bet and deducts it from the available funds or bankroll.  Compile and test the program.  Why does the main method use the player method called cash to determine how much cash is available? Hint: Try to access the datafield money directly and see what happens.
  3. We need a check to ensure that the amount bet is less than or equal to the amount available.  One way to handle a bet that is too high is to print an error message and reprompt, but in this program we’ll simply assume in cases where the amount bet by the user exceeds their current bankroll, that the true amount bet is equal to the current value of money.  Insert that check in the makeBet method.  Print the message "Betting it all!" if appropriate.  Compile and test the program, stressing both possibilities.
  4. Note that there is currently no call to the method betOptions of the Wheel class, which prints the betting possibilities and reads the user’s choice.  Create a new datafield called betType in the Player class.  Then insert a call to the betOptions method from the makeBet method, storing the result in betType.  Note that the method betOptions is static, therefore its invocation is through the Wheel class, not an instance of that class (like the Math class methods).  In fact, we’ll never instantiate (create an object of) the Wheel class.  It is designed assuming there is only one roulette wheel in the game, and therefore all data in the class is static.  Compile and test this modification.
  5. We need to make one more modification to the makeBet method.  If the user wants to bet on a particular number, we must prompt for and read that number. Store it in a variable called numberBetOn in the Player object.  Use the constant Wheel.NUMBER to test for that betType.
  6. We need to be able to spin the roulette wheel. A typical roulette wheel has 37 positions, numbered from 0 to 36. Create a method called spin in the Wheel class that determines and sets the ballPosition variable (use Math.random(), the remainder operator, and rather than literals like 37, use the class constant POSITIONS). Later, we'll want to print messages from the spin method, so it should have a SimpleGUI object as an input parameter (like betOptions does), and spin, like all other methods in the Wheel class, should be static. Insert a call to the spin method in the main loop after the player makes their bet.
  7. The even numbers on the roulette wheel are colored red, and the odd numbers are colored black.  In the spin method, use the remainder operator % to determine the color of the current ball position, and set the color variable of the Wheel class.  Make it correspond to the RED and BLACK constants already defined in the Wheel class.  At the end of the spin method, print the results of the spin, both color and number.  Compile and test your program.
  8. Create a method called payoff in the Wheel class, which accepts parameters representing the bet amount, the bet type, and the number which is being bet on (as in the user is placing a number bet that the wheel will be spun and land on say 23). Note that the third parameter is not needed if the bet is on color (RED or BLACK). The purpose of this method is to return the amount won by the player (which is zero if they lost their bet). Because there are two types of payoff categories, we will define two support methods (private to the Wheel class) to help us determine the payoff amount.  If the bet is on a particular number, invoke a method called numberPayoff, passing in the bet amount and the number which the player bet upon. Otherwise, invoke a method called redBlackPayoff, passing in the bet amount and the bet type (RED or BLACK). The payoff method will be very short, and you cannot compile and test it until you've defined the next two support methods below.
  9. Create the method numberPayoff, such that if the number bet matches the number on the wheel, the payoff is 36 times the bet. Otherwise the payoff is zero. Return the payoff amount.
  10. Create the method redBlackPayoff, such that if the color bet matches the color on the wheel, the payoff is 2 times the bet. Otherwise the payoff is zero. Return the payoff amount.
  11. Create a method called payment in the Player class that determines the winnings using the payoff method, prints the payoff amount, and adds it to the available cash.  Insert a call to payment in the main processing loop after the wheel is spun.  Compile and test the program.
  12. Test the system thoroughly. Note that the chances of betting on a number and winning are relatively small.  How could we modify the program to facilitate the testing of  this issue while still demonstrating confidence in the program’s logic? Hint: Why do you suppose we used the constant POSITIONS?
  13. Make sure your program documentation is up to date and complete. Submit the final version of your program using grade.