Java Debugging assignment. (will have to use github)
Bug Report.pdf
Bug Report:
Bug 1: Game does not pay out at correct level.
When player wins on 1 match, balance does not increase.
Bug 2: Player cannot reach betting limit:
Limit set to 0, but game ends with player still with 5 (dollars) remaining.
Bug 3: Odds in the game do not appear to be correct.
Crown and Anchor games have an approximate 8% bias to the house. So the win : (win+lose) ratio
should approximately equal 0.42. This does not appear to be the case.
Please Note: These are the bugs that have been reported. It should not be assumed that these are the
only bugs present. For higher range grades, all bugs must be found and resolved.
Please Also Note: It is not sufficient that bugs are found and eliminated. The debugging process
needs to be documented. In particular, tests need to be written that both demonstrate the bug, and
demonstrate its resolution.
The steps in the debugging process need to be documented. Keep a debugging logbook and record the
series of hypotheses and tests that led you to the origin of each bug. The tests may be informal (ie not
unit tests), but the results need to be noted down.
CrownAndAnchorGame_Java.zip
CrownAndAnchorGame/src/src/Dice.java
CrownAndAnchorGame/src/src/Dice.java
public
class
Dice
{
private
DiceValue
value
;
public
Dice
()
{
value
=
DiceValue
.
getRandom
();
}
public
DiceValue
getValue
()
{
return
value
;
}
public
DiceValue
roll
()
{
return
DiceValue
.
getRandom
();
}
public
String
toString
()
{
return
value
.
toString
();
}
}
CrownAndAnchorGame/src/src/DiceValue.java
CrownAndAnchorGame/src/src/DiceValue.java
import
java
.
util
.
HashMap
;
import
java
.
util
.
Map
;
import
java
.
util
.
Random
;
public
enum
DiceValue
{
CROWN
,
ANCHOR
,
HEART
,
DIAMOND
,
CLUB
,
SPADE
;
private
static
Random
RANDOM
=
new
Random
();
private
static
final
Map
<
DiceValue
,
String
>
VALUE_REPR_MAP
=
new
HashMap
<
DiceValue
,
String
>
();
static
{
VALUE_REPR_MAP
.
put
(
DiceValue
.
CROWN
,
"Crown"
);
VALUE_REPR_MAP
.
put
(
DiceValue
.
ANCHOR
,
"Anchor"
);
VALUE_REPR_MAP
.
put
(
DiceValue
.
HEART
,
"Heart"
);
VALUE_REPR_MAP
.
put
(
DiceValue
.
DIAMOND
,
"Diamond"
);
VALUE_REPR_MAP
.
put
(
DiceValue
.
CLUB
,
"Club"
);
VALUE_REPR_MAP
.
put
(
DiceValue
.
SPADE
,
"Spade"
);
}
public
String
toString
(
DiceValue
value
)
{
return
VALUE_REPR_MAP
.
get
(
value
);
}
public
static
DiceValue
getRandom
()
{
int
random
=
RANDOM
.
nextInt
(
DiceValue
.
SPADE
.
ordinal
());
return
values
()[
random
];
}
}
CrownAndAnchorGame/src/src/Game.java
CrownAndAnchorGame/src/src/Game.java
import
java
.
util
.
Collections
;
import
java
.
util
.
List
;
import
java
.
util
.
ArrayList
;
public
class
Game
{
private
List
<
Dice
>
dice
;
private
List
<
DiceValue
>
values
;
public
Game
(
Dice
die1
,
Dice
die2
,
Dice
die3
)
{
if
(
die1
==
null
||
die2
==
null
||
die3
==
null
)
throw
new
IllegalArgumentException
(
"Dice cannot be null."
);
dice
=
new
ArrayList
<
Dice
>
();
dice
.
add
(
die1
);
dice
.
add
(
die2
);
dice
.
add
(
die3
);
values
=
new
ArrayList
<
DiceValue
>
();
}
public
List
<
DiceValue
>
getDiceValues
()
{
values
.
clear
();
for
(
Dice
d
:
dice
)
{
values
.
add
(
d
.
getValue
());
}
return
Collections
.
unmodifiableList
(
values
);
}
public
int
playRound
(
Player
player
,
DiceValue
pick
,
int
bet
)
{
if
(
player
==
null
)
throw
new
IllegalArgumentException
(
"Player cannot be null."
);
if
(
pick
==
null
)
throw
new
IllegalArgumentException
(
"Pick cannot be negative."
);
if
(
bet
<
0
)
throw
new
IllegalArgumentException
(
"Bet cannot be negative."
);
player
.
takeBet
(
bet
);
int
matches
=
0
;
for
(
Dice
d
:
dice
)
{
d
.
roll
();
if
(
d
.
getValue
().
equals
(
pick
))
{
matches
+=
1
;
}
}
int
winnings
=
matches
*
bet
;
if
(
matches
>
0
)
{
player
.
receiveWinnings
(
winnings
);
}
return
winnings
;
}
}
CrownAndAnchorGame/src/src/Main.java
CrownAndAnchorGame/src/src/Main.java
import
java
.
util
.
List
;
import
java
.
io
.
*
;
public
class
Main
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
BufferedReader
console
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
));
Dice
d1
=
new
Dice
();
Dice
d2
=
new
Dice
();
Dice
d3
=
new
Dice
();
Player
player
=
new
Player
(
"Fred"
,
100
);
Game
game
=
new
Game
(
d1
,
d2
,
d3
);
List
<
DiceValue
>
cdv
=
game
.
getDiceValues
();
int
totalWins
=
0
;
int
totalLosses
=
0
;
while
(
true
)
{
int
winCount
=
0
;
int
loseCount
=
0
;
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
String
name
=
"Fred"
;
int
balance
=
100
;
int
limit
=
0
;
player
=
new
Player
(
name
,
balance
);
player
.
setLimit
(
limit
);
int
bet
=
5
;
System
.
out
.
println
(
String
.
format
(
"Start Game %d: "
,
i
));
System
.
out
.
println
(
String
.
format
(
"%s starts with balance %d, limit %d"
,
player
.
getName
(),
player
.
getBalance
(),
player
.
getLimit
()));
int
turn
=
0
;
while
(
player
.
balanceExceedsLimitBy
(
bet
)
&&
player
.
getBalance
()
<
200
)
{
turn
++
;
DiceValue
pick
=
DiceValue
.
getRandom
();
System
.
out
.
printf
(
"Turn %d: %s bet %d on %s\n"
,
turn
,
player
.
getName
(),
bet
,
pick
);
int
winnings
=
game
.
playRound
(
player
,
pick
,
bet
);
cdv
=
game
.
getDiceValues
();
System
.
out
.
printf
(
"Rolled %s, %s, %s\n"
,
cdv
.
get
(
0
),
cdv
.
get
(
1
),
cdv
.
get
(
2
));
if
(
winnings
>
0
)
{
System
.
out
.
printf
(
"%s won %d, balance now %d\n\n"
,
player
.
getName
(),
winnings
,
player
.
getBalance
());
winCount
++
;
}
else
{
System
.
out
.
printf
(
"%s lost, balance now %d\n\n"
,
player
.
getName
(),
player
.
getBalance
());
loseCount
++
;
}
}
//while
System
.
out
.
print
(
String
.
format
(
"%d turns later.\nEnd Game %d: "
,
turn
,
i
));
System
.
out
.
println
(
String
.
format
(
"%s now has balance %d\n"
,
player
.
getName
(),
player
.
getBalance
()));
}
//for
System
.
out
.
println
(
String
.
format
(
"Win count = %d, Lose Count = %d, %.2f"
,
winCount
,
loseCount
,
(
float
)
winCount
/
(
winCount
+
loseCount
)));
totalWins
+=
winCount
;
totalLosses
+=
loseCount
;
String
ans
=
console
.
readLine
();
if
(
ans
.
equals
(
"q"
))
break
;
}
//while true
System
.
out
.
println
(
String
.
format
(
"Overall win rate = %.1f%%"
,
(
float
)(
totalWins
*
100
)
/
(
totalWins
+
totalLosses
)));
}
}
CrownAndAnchorGame/src/src/Player.java
CrownAndAnchorGame/src/src/Player.java
public
class
Player
{
private
String
name
;
private
int
balance
;
private
int
limit
;
public
Player
(
String
name
,
int
balance
)
{
if
(
name
==
null
||
name
.
isEmpty
())
throw
new
IllegalArgumentException
(
"Name cannot be null or empty"
);
if
(
balance
<
0
)
throw
new
IllegalArgumentException
(
"Balance cannot be negative"
);
this
.
name
=
name
;
this
.
balance
=
balance
;
this
.
limit
=
0
;
}
public
String
getName
()
{
return
name
;
}
public
int
getBalance
()
{
return
balance
;
}
public
int
getLimit
()
{
return
limit
;
}
public
void
setLimit
(
int
limit
)
{
if
(
limit
<
0
)
throw
new
IllegalArgumentException
(
"Limit cannot be negative."
);
if
(
limit
>
balance
)
throw
new
IllegalArgumentException
(
"Limit cannot be greater than balance."
);
this
.
limit
=
limit
;
}
public
boolean
balanceExceedsLimit
()
{
return
(
balance
>
limit
);
}
public
boolean
balanceExceedsLimitBy
(
int
amount
)
{
return
(
balance
-
amount
>
limit
);
}
public
void
takeBet
(
int
bet
)
{
if
(
bet
<
0
)
throw
new
IllegalArgumentException
(
"Bet cannot be negative."
);
if
(
!
balanceExceedsLimitBy
(
bet
))
throw
new
IllegalArgumentException
(
"Placing bet would go below limit."
);
balance
=
balance
-
bet
;
}
public
void
receiveWinnings
(
int
winnings
)
{
if
(
winnings
<
0
)
throw
new
IllegalArgumentException
(
"Winnings cannot be negative."
);
balance
=
balance
+
winnings
;
}
public
String
toString
()
{
return
String
.
format
(
"Player: %s, Balance: %d, Limit: %d"
,
name
,
balance
,
limit
);
}
}
rules_crown___anchor.pdf
Department of Racing, Gaming & Liquor Government of Western Australia
page 1 of 1
RULES FOR PLAYING CROWN AND ANCHOR
1. Crown and Anchor shall be played on a layout mat which is marked in a manner similar to that
shown in the diagram:-
♥ ♦
♣ ♠
2. The game shall be played with three identical dice with the faces of each dice marked with the
symbols of a crown, anchor, heart, diamond, club and spade. 3. The game shall be controlled by a dealer who is not permitted to wager. 4. No person other than the dealer shall throw the dice or activate the dice cage. 5. If any of the three dice fail to come to rest with one surface flat to the base of the dice cage or flat
on the layout mat the dealer shall call "No Spin/Throw” 6. If the dealer calls "No Spin/Throw" all wagers shall be void on that spin/throw. 7. The minimum and maximum wagers shall be prominently displayed on a sign at the table. 8. A wager on a particular symbol shall win if the symbol appears on one or more of the uppermost
face of the three dice and shall lose if the symbol does not appear. 9. Winning wagers shall be paid at odds not less than:-
if the symbol appears on the uppermost face of 3 dice 3 to 1
if the symbol appears on the uppermost face of 2 dice 2 to 1
if the symbol appears on the uppermost face of 1 dice 1 to 1
10. A person under the age of 18 years shall not participate in the game or be involved in the dealing
or conduct of the game.