Monte-Carlo Simulation: Blackjack
The main purpose of this project is to give you practice building classes in Java. To do this, we'll simulate a simple version of the card game Blackjack. The objects in a card game include: a Card, a Deck, a Hand, and Game. You'll make a class for each one, connecting them together as appropriate. We'll also start to make use of a few of the many Java library classes.
For this assignment you will implement classes to represent a card, a hand, a deck, and the game Blackjack. The result will be a text-based version of the game that runs in the terminal. You are free to make the game more complex as an extension.
The purpose of the assignment is not to create a Blackjack game for people to play, however, but to study the properties of Blackjack, given a particular rule set, when played over many hands. You are using CS to study the properties of a system defined by a set of rules.
The Card Class
Create a java class called Card, which should hold all information unique to the card. For this assignment, it needs only to hold the value of the card, which must be in the range 1-10. The Card class should have the following methods. In addition, make a main method that uses each of the class methods.
public Card()a constructor with no arguments.
public Card(int v)a constructor with the value of the card, possibly doing range checking.
public int getValue()return the numeric value of the card.
The Hand Class
Create a java class called Hand, which should hold a set of
cards. You can use an ArrayList (
import java.util.ArrayList) to hold
the Card objects. The class should have at least the following
public Hand()initialize the ArrayList.
public void reset()reset the hand to empty.
public void add( Card card )add the card object to the hand.
public int size()returns the number of cards in the hand.
public Card getCard( int i )returns the card with index i. Cast as appropriate.
public int getTotalValue()returns the sum of the values of the cards in the hand.
public String toString()returns a String that has the contents of the hand "written" in a nice format.
The Deck Class
Create a java class called Deck, which should hold a set of cards and be able to shuffle and deal the cards. You should use an ArrayList to hold the cards. The class should support the following methods.
public Deck()builds a deck of 52 cards, 4 each of cards with values 1-9 and 16 cards with the value 10. Note, you probably want the constructor to call the build() method, below.
public void build()builds a deck of 52 cards, 4 each of cards with values 1-9 and 16 cards with the value 10.
public Card deal()returns the top card (position zero) and removes it from the deck.
public Card pick( int i)(optional) returns the card at position i and removes it from the deck.
public void shuffle()shuffles the deck. This method should put the deck in random order. One way to do it is to build a fresh second deck and then make n random picks from it, where n is the size of the deck at the time of the shuffle. Note that the first pick should be in the range [0, n-1], the second pick should be in the range [0, n-2] and so on. You may want to generate a seed for the Random object by using the function
System.currentTimeMillis()so that each run of a game is different. You are expected to implement the shuffle method. Please do not use Collection.shuffle().
public String toString()returns a String that has the contents of the deck "written" in a nice format (so that you can see the ordering of the card values).
The Blackjack Class
Create a class called Blackjack that implements a simple version of the card game. The class will need to have a Deck, a Hand for the player, a Hand for the dealer, and scores for both the dealer and player. The main function for the Blackjack class should implement one complete game.
public Blackjack()should set up and reset the game (call reset(), below).
public void reset( boolean newDeck )should set up and reset the game. If newDeck is true, then the function should create a fresh deck. The deck should be shuffled before the game starts.
public void deal()should deal out two cards to both players.
public String toString()returns a String that has describes the state of the game, including player scores.
public boolean playerTurn()have the player draw cards until the total value of the player's hand is equal to or above 16. The function should return false if the player goes over 21 (bust).
public boolean dealerTurn()have the dealer draw cards until the total of the dealer's hand is equal to or above 17. The function should return false if the dealer goes over 21.
public static void main( String args )the main function should deal, print the state, then have the player go, then have the dealer go. If the player goes bust, the game is over and the dealer wins. If the player does not go bust, but the dealer goes bust, then the game is over and the player wins. Otherwise, the player with the largest hand wins. In the case of a tie, the result is a push.
- Within your main function, you will need to make a rule as to when the deck is reshuffled. You can reshuffle only when the deck has fewer than N cards. The value of N is up to you.
Storing Game Output
Once you have completed the above four classes, generate a printout of three different games. You can send output to a file using the greater than symbol on the command line. For example, the command
java Blackjack > mygames.txt
would play a game and send it to the file mygames.txt.
Add another function to the Blackjack class that plays a game and returns 1 if the player wins, 0 if it is a push, and -1 if the dealer wins.
Make one more class called Simulation. This class should have only a main function that executes 1000 games of Blackjack. It should keep track of how many games the player wins, how many the dealer wins, and many are pushes. Print out the total in the end both as raw numbers and as percentages.
Have the dealer take only one card to start, then make the game interactive so that you can decide whether the player takes another card or not. Add betting. [Obviously, this makes simulating many games impossible, so the point is to make a real interactive game.]
Add in more of the rules for Blackjack. For example, an Ace (value 1 in the default case above) can have the value 1 or 11, whichever is more advantageous. If you add in the Ace rule, then you will also want to take into account a real Blackjack (2 cards totaling 21) when evaluating the winning hand. A Blackjack beats a 21 with more than 2 cards. See how these rules affect the simulation results.
Make your game use 6 decks, and reshuffle if only 1 deck left. Play the game 1000 times, and observe how many games the player wins, how many the dealer wins, and many are pushes.
Run the simulation with different decision rules for the player and see how it affects the outcome percentages over many games (>= 1000).
Add a type of betting strategy to the simulation and see if the player can win money even while losing more games than winning.
Try running the simulation with different numbers of games and see how variable the results are. For example, run the simulation using M games (e.g. M = 100) and do this N times (e.g. N = 10). Then calculate the standard deviation of the results. Then you can plot the standard deviation versus the number of games (M) in the simulation to see how the results stabilize as you use a larger number of games.
For any assignment, a good extension will be to implement a Java class yourself and demonstrate that it has the same functionality as the Java class. For example, you could implement your own ArrayList class for this assignment.
Another good extension for any assignment is to identify in comments when memory is being "lost." (Indicate the line of code in which the last reference to an object in memory is removed.)
Your writeup should have a simple format.
- A brief description of the overall project, in your own words.
- An explanation of your solution, focusing on the interesting bits. In this assignment, for example, shuffling the deck and doing the overall simulation are the interesting bits. You can include code snippets in your writeup to help describe your solution. A code snippet is usually less than 10 lines of code.
- Are 1000 games sufficient to provide an accurate estimate of the win percentage for the player and dealer? What are those percentages?
- What is the number of games the simulation has to play in order for the dealer's win percentage always to be above the player's win percentage over ten runs of the simulation?
- Printouts, pictures, or results to show what you did. For this assignment, you should include the results of the overall simulation.
- Other results to demonstrate extensions you undertook. If you tried different player strategies, for example, show how those affected the overall simulation results.
- A brief conclusion and description of what you learned.
Make your writeup for the project a wiki page in your personal space. If you have questions about making a wiki page, stop by my office or ask in lab.
Once you have written up your assignment, give the page the label:
You can give any wiki page a label using the label field at the bottom of the page. The label is different from the title.
Do not put code on your writeup page or anywhere it can be publicly accessed. To hand in code, put it in your folder on the Courses fileserver. Create a directory for each project inside the private folder inside your username folder.