Crown and Anchor game

Assignment 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 thatshown in the diagram:-

2.The game shall be played with three identical dice with the faces of each dice marked with thesymbols 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 flaton 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 uppermostface of the three dice and shall lose if the symbol does not appear.
9. Winning wagers shall be paid at odds not less than:-

10. A person under the age of 18 years shall not participate in the game or be involved in the dealingor conduct of the game.

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.

 Dice.java 

public class Dice {

privateDiceValue value;

public Dice() {

value =  DiceValue.getRandom();

}

publicDiceValuegetValue() {

return value;

}

publicDiceValue roll() {

returnDiceValue.getRandom();

}

public String toString() {

returnvalue.toString();

}

}

 DiceValue.java

importjava.util.HashMap;

importjava.util.Map;

importjava.util.Random;

publicenumDiceValue {

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) {

returnVALUE_REPR_MAP.get(value);

}

public static DiceValuegetRandom() {

int random = RANDOM.nextInt(DiceValue.SPADE.ordinal());

return values()[random];

}

}

 Game.java

importjava.util.Collections;

importjava.util.List;

importjava.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());

}

returnCollections.unmodifiableList(values);

}

publicintplayRound(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;

}

} 

Main.java

importjava.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();

inttotalWins = 0;

inttotalLosses = 0;

while (true)

{

intwinCount = 0;

intloseCount = 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)));

}

} 

Player.java

public class Player {

private String name;

privateint balance;

privateint 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; }

publicintgetBalance() { return balance; }

publicintgetLimit() { 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;

}

publicbooleanbalanceExceedsLimit() {

return (balance > limit);

}

publicbooleanbalanceExceedsLimitBy(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() {

returnString.format(“Player: %s, Balance: %d, Limit: %d”, name, balance, limit);

}

} 

Solution 

Dice.java 

public class Dice {

privateDiceValue value;

public Dice() {

value =  DiceValue.getRandom();

}

publicDiceValuegetValue() {

return value;

}

publicDiceValue roll() {

returnDiceValue.getRandom();

}

public String toString() {

returnvalue.toString();

}

} 

DiceValue.java

importjava.util.HashMap;

importjava.util.Map;

importjava.util.Random;

publicenumDiceValue {

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) {

returnVALUE_REPR_MAP.get(value);

}

public static DiceValuegetRandom() {

int random = RANDOM.nextInt(DiceValue.SPADE.ordinal() + 1);

return values()[random];

}

} 

Game.java

importjava.util.ArrayList;

importjava.util.Collections;

importjava.util.List;

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());

}

returnCollections.unmodifiableList(values);

}

publicintplayRound(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;

int winnings = 0;

for ( Dice d : dice) {

d.roll();

if (d.getValue().equals(pick)) {

matches += 1;

winnings += bet;

}

}

winnings += matches * bet;

if (matches > 0) {

player.receiveWinnings(winnings);

}

return winnings;

}

} 

Main.java

importjava.io.BufferedReader;

importjava.io.InputStreamReader;

importjava.util.List;

import static org.junit.jupiter.api.Assertions.assertTrue;

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();

inttotalWins = 0;

inttotalLosses = 0;

while (true)

{

intwinCount = 0;

intloseCount = 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)

{

game = new Game(new Dice(), new Dice(), new Dice());

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)));

System.out.println();

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)));

}

} 

Player.java

public class Player {

private String name;

privateint balance;

privateint 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; }

publicintgetBalance() { return balance; }

publicintgetLimit() { 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;

}

publicbooleanbalanceExceedsLimit() {

return (balance > limit);

}

publicbooleanbalanceExceedsLimitBy(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() {

returnString.format(“Player: %s, Balance: %d, Limit: %d”, name, balance, limit);

}

} 

Testing.java 

importorg.junit.jupiter.api.Test;

importjava.io.BufferedReader;

importjava.io.IOException;

importjava.io.InputStreamReader;

importjava.util.List;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class Testing

{

@Test

public void testRandom()

{

int k = 0;

for (int i = 0 ; i < 1000 ;i ++)

{

if(DiceValue.getRandom().equals(DiceValue.SPADE)) k++;

}

assertTrue(k>0);

}

@Test

public void  generalTest() throws IOException {

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();

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)

{

game = new Game(new Dice(), new Dice(), new Dice());

turn++;

DiceValue pick = DiceValue.getRandom();

System.out.printf(“Turn %d: %s bet %d on %s\n”,

turn, player.getName(), bet, pick);

intpreviousBalance = player.getBalance();

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());

//checking that winning always increase our balance

assertTrue(previousBalance<player.getBalance());

}

else {

System.out.printf(“%s lost, balance now %d\n\n”,

player.getName(), player.getBalance());

//checking that losing always decrease our balance

assertTrue(previousBalance>player.getBalance());

}

} //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

}

}