Download presentation
Presentation is loading. Please wait.
Published byCharlene Todd Modified over 9 years ago
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
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.