Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 CSC 221: Computer Programming I Spring 2010 interaction & design  modular design: roulette game  constants, static fields  % operator, string equals.

Similar presentations


Presentation on theme: "1 CSC 221: Computer Programming I Spring 2010 interaction & design  modular design: roulette game  constants, static fields  % operator, string equals."— Presentation transcript:

1 1 CSC 221: Computer Programming I Spring 2010 interaction & design  modular design: roulette game  constants, static fields  % operator, string equals  variable scope  logical operators

2 2 Roulette games consider the task of simulating a roulette game  need to be able to spin a wheel  make bets, either by number or even/odd  keep track of winnings/losses (most likely losses!) behaviors?  create a game  initialize the player's bankroll  for each spin of the wheel  get the player's bet  determine if winner and update bankroll accordingly  make sure the player has credits in order to play? we could try modeling a game by implementing a class directly  must model the wheel behavior, also manage the bankroll and bets lots of details to keep track of; not easy to generalize

3 3 A modular design instead, we can encapsulate all of the behavior of a roulette wheel in a class RouletteWheel class:  create a RouletteWheel  spin the wheel, return number  keep track of the number of spins so far once the RouletteWheel class is defined, a RouletteGame will be much simpler RouletteGame class:  create a RouletteGame (with its own RouletteWheel )  add credits to bankroll  check the bankroll balance  take a number bet & determine if a winner  take an even/odd bet & determine if a winner

4 4 RouletteWheel class public class RouletteWheel { private Die roller; private int numSpins; public RouletteWheel() { this.roller = new Die(38); this.numSpins = 0; } public int spin() { int number = this.roller.roll(); this.numSpins++; if (number > 36) { return 0; } else { return number; } public int getNumberOfSpins() { return this.numSpins; } more naturally:  fields store a Die (for generating random numbers) and a counter for the number of spins  constructor creates the Die object and initializes the count  methods access and update these fields to maintain the wheel's state CREATE AND PLAY

5 5 Magic numbers the RouletteWheel class works, but what if we wanted to change to a European-style wheel?  only 1-36 and 0 (no 00)  would have to change die = new Die(38); to die = new Die(37);  having "magic numbers" like 38 in code is bad practice unclear what 38 refers to when reading the code requires searching for the number when a change is desired public class RouletteWheel { private Die roller; private int numSpins; public RouletteWheel() { this.roller = new Die(38); this.numSpins = 0; } public int spin() { int number = this.roller.roll(); this.numSpins++; if (number > 36) { return 0; } else { return number; } public int getNumberOfSpins() { return this.numSpins; }

6 6 Constants better solution: define a constant  a constant is a variable whose value cannot change  use a constant any time a "magic number" appears in code a constant declaration looks like any other field except  the keyword final specifies that the variable, once assigned a value, is unchangeable  the keyword static specifies that the variable is shared by all objects of that class since a final value cannot be changed, it is wasteful to have every object store a copy of it instead, can have one static variable that is shared by all by convention, constants are written in all upper-case with underscores public class RouletteWheel { private final static int MAX_NUM = 36; private final static int NUM_ZEROS = 2; private Die roller; private int numSpins; public RouletteWheel() { this.roller = new Die(RouletteWheel.MAX_NUM + RouletteWheel.NUM_ZEROS); this.numSpins = 0; } public int spin() { int number = this.roller.roll(); this.numSpins++; if (number > RouletteWheel.MAX_NUM) { return 0; } else { return number; } public int getNumberOfSpins() { return this.numSpins; }

7 7 Static fields in fact, it is sometimes useful to have static fields that aren't constants  if all roulette wheels have the same range, there is no reason for every wheel to have its own Die  we could declare the Die field to be static, so that the one Die is shared by all wheels  the first RouletteWheel object creates/inits the field, subsequent objects simply access it note: methods can be declared static as well  e.g., Math.random() MORE LATER public class RouletteWheel { private final static int MAX_NUM = 36; private final static int NUM_ZEROS = 2; private static Die roller = new Die(RouletteWheel.MAX_NUM + RouletteWheel.NUM_ZEROS); private int numSpins; public RouletteWheel() { this.numSpins = 0; } public int spin() { int number = RouletteWheel.roller.roll(); this.numSpins++; if (number > RouletteWheel.MAX_NUM) { return 0; } else { return number; } public int getNumberOfSpins() { return this.numSpins; }

8 using the RouletteWheel class, a RouletteGame class is straightforward  fields store roulette wheel and bankroll  constructor creates the RouletteWheel and inits the bankroll  methods utilize the RouletteWheel methods to produce the game behaviors 8 RouletteGame class public class RouletteGame { private RouletteWheel wheel; private int credits; public RouletteGame() { this.wheel = new RouletteWheel(); this.credits = 0; } public void addCredits(int numCredits) { this.credits += numCredits; } public int checkCredits() { return this.credits; } public String makeBet(int betAmount, int number) { int result = this.wheel.spin(); if (result == number) { this.credits += 35*betAmount; return result + " - winner"; } else { this.credits -= betAmount; return result + " - loser"; } public String makeBet(int betAmount, String betType) { int result = this.wheel.spin(); String resultType = "odd"; if (result % 2 == 0) { resultType = "even"; } if (betType.equals(resultType)) { this.credits += betAmount; return result + " - winner"; } else { this.credits -= betAmount; return result + " - loser"; }

9 the % operator returns the remainder after dividing one number by another  useful for determining odd/even (result % 2) will evaluate to 0 if result is even, 1 if odd 9 RouletteGame details: % and equals public class RouletteGame { private RouletteWheel wheel; private int credits;. public String makeBet(int betAmount, String betType) { int result = this.wheel.spin(); String resultType = "odd"; if (result % 2 == 0) { resultType = "even"; } if (betType.equals(resultType)) { this.credits += betAmount; return result + " - winner"; } else { this.credits -= betAmount; return result + " - loser"; } when comparing two String values, == does not always work as expected (explanation later)  instead, use the equals method defined for Strings str1.equals(str2) will return true if str1 & str2 are identical, else false

10 consider the segment: String resultType = "odd"; if (result % 2 == 0) { resultType = "even"; } 10 RouletteGame details: scope why not? if (result % 2 == 0) { String resultType = "even"; } else { String resultType = "odd"; } key idea: on large software projects, need to be able to develop independent modules independently  in the real world, a software project might get divided into several parts  each part is designed & coded by a different team, then integrated together  internal naming conflicts should not be a problem e.g., when declaring a local variable in a method, the programmer should not have to worry about whether that name is used elsewhere every variable has a scope (i.e., where in the program it exists and can be accessed)  can reuse the same local variable/parameter name in different methods since they exist in different scopes

11 11 RouletteGame details: scope  the scope of a field is the entire class (i.e., all methods can access it)  the scope of a parameter is its entire method  the scope of a local variable is from its declaration to the end of its enclosing block {…} if (result % 2 == 0) { String resultType = "even"; } else { String resultType = "odd"; } since the variable is declared inside { }, it will not exist after the if-else String resultType; if (result % 2 == 0) { resultType = "even"; } else { resultType = "odd"; } this would work – since declared outside the if-else, the variable exists & can be accessed afterwards String resultType = "odd"; if (result % 2 == 0) { resultType = "even"; } if must declare outside the if-else, might as well give it a default value then change only if needed

12 does makeBet work correctly in all cases?  what if the spin is 0? 12 RouletteGame fix? public class RouletteGame { private RouletteWheel wheel; private int credits;. public String makeBet(int betAmount, String betType) { int result = this.wheel.spin(); String resultType = "odd"; if (result % 2 == 0) { resultType = "even"; } if (betType.equals(resultType)) { this.credits += betAmount; return result + " - winner"; } else { this.credits -= betAmount; return result + " - loser"; } 0 should automatically lose  one possible revision if (result == 0) { this.credits -= betAmount; return result + " – loser"; } else if (betType.equals(resultType)) { this.credits += betAmount; return result + " - winner"; } else { this.credits -= betAmount; return result + " - loser"; } these two cases have identical code – would like to combine and avoid duplication

13 13 RouletteGame fix: logical operators public String makeBet(int betAmount, String betType) { int result = this.wheel.spin(); String resultType = "odd"; if (result % 2 == 0) { resultType = "even"; } if (result > 0 && betType.equals(resultType)) { this.credits += betAmount; return result + " - winner"; } else { this.credits -= betAmount; return result + " - loser"; } Java provides logical operators for simplifying such cases (TEST1 && TEST2) evaluates to true if either TEST1 AND TEST2 is true (TEST1 || TEST2) evaluates to true if either TEST1 OR TEST2 is true (!TEST) evaluates to true if TEST is NOT true warning: the tests that appear on both sides of || and && must be complete Boolean expressions (x == 2 || x == 12) OK (x == 2 || 12) BAD!

14 RouletteGame: error checking public void addCredits(int numCredits) { if (numCredits > 0) { this.credits += numCredits; } public String makeBet(int betAmount, int number) { if (betAmount > 0 && this.credits >= betAmount && number >= 1 && number <= 36) { // SAME AS BEFORE else { return "ILLEGAL BET"; } public String makeBet(int betAmount, String betType) { if (betAmount > 0 && this.credits >= betAmount && (betType.equals("odd") || betType.equals("even"))) { // SAME AS BEFORE } else { return "ILLEGAL BET"; } 14

15 RouletteWheel: adding color in addition to odd/even and a specific number, can also bet on a color red: 1, 3, 5, 7, 9, black: 2, 4, 6, 8, 10, 12, 14, 16, 1811, 13, 15, 17, 19, 21, 23, 25, 27,20, 22, 24, 26, 28, 30, 32, 34, 3629, 31, 33, 35 green: 0, 00 how do we alter the RouletteWheel so that we can determine color? how do we alter RouletteGame to allow bets on "red" or "black"? 15


Download ppt "1 CSC 221: Computer Programming I Spring 2010 interaction & design  modular design: roulette game  constants, static fields  % operator, string equals."

Similar presentations


Ads by Google