CS110

Project 3

Betty O’Neil

Finding a good strategy for DiceJack

 

DiceJack: like Blackjack, but using dice (simpler)

Provided files: Project3.zip

At the start of a game, the players and the dealer throw two dice.

The best possible result is sum of 12. This is called a natural 12, and the player holding this automatically wins unless the dealer also has a natural 12. If a player and the dealer each have a 12, the result is a draw. If the dealer has a 12, all players not holding a 12 lose.

After the original two dice have been thrown, the game goes on with each player taking action in turn, as follows.

The player can keep his score as it is (stand) or throw a die again (hit), one at a time, until either the player judges that the score is good enough to go up against the dealer's holding and stands, or until it goes over 12, in which case the player immediately loses (busts).

After all the players have taken their turn, the dealer takes a turn and throws if the dealer score is under 8, and throws a single die again and again until the score is 8 or more. The dealer can bust, in which case any unbusted player wins. If not, the dealer’s final score is compared to each player’s score (unless the player has already won or lost), and higher scores win, and equal scores tie.

Is there a simple strategy to win at this game? That is what we want to find out in this project.

Plan: set up a group of players, each of which plays with a different strategy:  Clearly it is not good to stand on 5 or less, since even an added 6 won't bust.  Thus we start from strategy 6.  Similarly, it's not good to hit on a 12, so the highest strategy uses 11.  

Player 0 stands on 6 or more.

Player 1 stands on 7 or more.

Player 2 stands on 8 or more.  (This player should be even with the dealer)

Player 3 stands on 9 or more.

Player 4 stands on 10 or more.

Player 5 stands on 11 or more.

The dealer, also a Player, stands on 8 or more.

We play the game over and over, and see which strategy is best against the house. We can record how many games are won by player 4, player 5, etc.

You will write the central Player class, with the help of TestPlayer, a provided test program for Player.  A certain Player has two dice to play with, and a certain stand value as listed above. A player must be able to throw the dice on command in the first round of play (the startGame action), and throw one die over and over in the second round of play, until the score reaches the stand value (the takeTurn action). At any time, the Player must be able to provide its current score (the getCurrentValue action), as well as its stand value (the getStandValue action).

At the end of the first round of play, the dealer throws dice, and if the dealer gets a natural 12, the game is over, with all non-dealer Players immediately losing unless they also have a natural 12, in which case they tie.  The house (represented by class GameManager, and separately by TestPlayer) determines this outcome and tells the Player by calling win() or tie().  The Player then adds one to nWins or nTies to tally this game. 

At the end of the first round of play, the dealer throws dice, and if the dealer gets less than 12, the game continues in its second round. Each Player does the takeTurn action, and then the dealer does takeTurn too.  The house determines whether each player wins, loses or ties, by calling win(), lose(), or tie() of Player. The Player then adds one to nWins, nTies, or nLosses to tally this game. 

When the game is done and tallied, Player is then ready to play another game, using the same stand value.  After many games, we have statistics on wins, losses, and ties for each strategy. All a Player has to do is provide the number of wins, losses, and ties to another software entity for display.  That is done by getWins(), getLosses(), and getTies().  As is normal for Java object deep in an application, Player does no direct output to the user, except for debugging/error reporting.

In the FindBest application, the GameManager runs the whole sequence of games, using a Player for each strategy, and later prints out the results of all the games.

The TestPlayer program uses a single Player object, putting it through its paces. It makes sense to concentrate on TestPlayer first, and when you think Player is working, go on to GameManager and FindBest.

Since Player throws dice, it is a challenge to write a TestPlayer program. How can you check that the outcome is correct if you don’t know what the dice will do? The answer is use a “mock Die”, a die that works like a Die, but has known outcomes.  Our MockDie class has roll() and getFaceValue() methods that always return the same number, the one we specify in the constructor: MockDie(3) creates a die that rolls 3 every time, for example.

But how can we fool Player into using a MockDie instead of a Die in TestPlayer? The answer is to use the power of interfaces.  We define the Rollable interface that requires roll() and getFaceValue(), so that Die IS-A Rollable and also MockDie IS-A Rollable.  We make Player use Rollable instead of Die as the working type.  Player will be happy, since it only wants to call roll() on the objects anyway.  Then we use real Die’s in FindBest and MockDie’s in TestPlayer.  We will provide Player with its “dice” at construction time.  Note that it is important that Player does NOT itself construct the dice.  If it did, then it would have the same kind of dice in all cases, but we want it to have mock dice in the testing case.

Step 1. Implement Player.java and test it with TestPlayer.

Here is the class diagram for TestPlayer: You program Player.java. The other Java sources, TestPlayer.java, Rollable.java, and MockDie.java, are provided.  As soon as you have a compilable version of Player, one that can create a Player and do “startGame”, run TestPlayer with it and see the reported problems, if any. Then add further functionality.

 

The diamond and connector to Rollable shows that aggregation is going on.  This means that the two Die/MockDie objects are just parts of Player, probably not important in themselves. The dashed line and triangle mean that MockDie implements Rollable.

Your job here is to write Player.java from scratch, based on the UML above and the discussion above of what a Player needs to do. Test it by running TestPlayer. Include Javadoc comments in your Player class code with @author and @version for the class and with @param and @return for each method.  In the comments for each method, include a brief description of the functions or decisions that your code performs.  

 

Step 2. Create Javadoc for Player in Player.html

 

Run “javadoc Player.java” on the command line to create a webpage describing Player in Player.html. Alternatively, you can use DrJava Tools>Javadoc>Preview Javadoc for Current Class, and then save the result to your Project3 directory as Player.html.

 

Step 3. Get the FindBest application working and find out the best strategy.

Once you get TestPlayer working by implementing Player, turn to finishing up GameManager and FindBest. Here is the UML class diagram for the whole application:

Here GameManager aggregates Players, i.e., GameManager HAS-A group of Players as parts of it, to do its work. GameManager acts as the house as each game runs. A caller can run games by calling playGames after creating a GameManager, and then print out statistics by calling printWins, etc. GameManager is started for you. Just fill in the code indicated by comments. Then the whole application will be working.

Report (memo.txt)

For this project and all projects in this course, the memo.txt file that you upload to the turn-in system MUST BE A PLAIN TEXT FILE - NOT A WORD (.DOC or .RTF) FILE.  On a Windows PC, I recommend that you use Notepad to create this file.  On a MAC, you must use a suitable editor or DrJava to create a plain text file.

Write a report that answers the following questions:

1.  Was it helpful to have the provided TestPlayer class while writing the code in your Player class?  How?

 

2.  What is your conclusion from this experiment, i.e., what is the best strategy to play this game?  Can you expect to win against the house if you follow this strategy? 

3.  We used an ArrayList<Player> for the players held in GameManager. Could we use an array of Player instead?  If so, what line of code would you write to create the array?  If not, why not?

4.  Explain in your own words how the interface Rollable allowed us to use two different “Die” classes with Player.java.

Turning in your Assignment:

Use the secure file transfer program to upload your Project3 folder containing your files (listed below) to your UNIX file directory: “account/cs110/Project3” where “account” is your account ID. 

You must upload the files to our UNIX system before the posted deadline.  You will get no credit for late submissions.  Plan your time carefully so that you have enough time to upload your files.  If you have not finished, upload your files on time anyway - even if the program does not work correctly yet.  That way you are eligible for part credit on the assignment.  If you upload your files more than once, only the most recent copy will be saved. 

Files for Project3 Delivery:

·         All .java files discussed above: Player.java, FindBest.java, GameManager.java, TestPlayer.java, Die.java, MockDie.java, Rollable.java, Histogram.java (only the first two have code you’ve added)

·         memo.txt

·         Player.html: Javadoc for Player.java