Monte-Carlo Simulation: Blackjack
The main purpose of this lab 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.
Documentation for Java 1.5 is located at: Java 1.5 SE API.
Documentation for Java 1.6 is located at: Java 1.6 SE API
If using a terminal is new to you, or you need a refresher, please check out the Terminal tutorial.
Before you start writing code, please take a look at the coding style guide.
You probably want to keep your code on your network directory. You can mount your personal volume using the following URL.
Once mounted, If you are on a terminal on a mac, you can get to the working directory using
From the Finder you can also drag any folder onto a Terminal window and it will create the complete path to the folder.
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.
When you write a class, always include a main function for the class that tests out its capabilities. For example, the card class should try creating a card object, assigning a value to it and then accessing and printing out the value. Ideally, a test function should try out all of the class methods and access all of the class variables. Having a proper test function for each class will be part of the grade for each assignment.
Important: Write complete tests for each class before you try to use the class somewhere else. For example, before you try to use the Card class to make a deck, you should be sure the Card class functions properly on its own. Get in this habit early; it will help you avoid a lot of frustration that comes when integrating even moderately complex systems.
Card - 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.
Hand - 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 getValue() - returns the sum of the values of the cards in the hand.
- public void print() - prints out the hand in a nice format.
Deck - 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
- 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.
- 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 as 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 52 random picks from it. Note that the first pick should be in the range [0, 51], the second pick should be in the range [0, 50] 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.
- public void print() - prints out the deck in some reasonable way so that you can see the ordering of the card values.
Blackjack - 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).
- public void reset( boolean reshuffle) - should set up and reset the game. If reshuffle is True, then the function should create a fresh deck.
- public void deal() - should deal out two cards to both players.
- public void print() - should print out 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.
- static public 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 every game or reshuffle only when the deck has fewer than N cards.
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 -cp . 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.
Each assignment will have a set of suggested extensions. The required tasks constitute about 85% of the assignment, and if you do only the required tasks and do them well you will earn a B+. To earn a higher grade, you need to undertake at least one extension. The difficulty and quality of the extension or extensions will determine your final grade for the assignment. One significant extension, or 2-3 smaller ones, done well, is typical.
- 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 totalling 21) when evaluating the winning hand. A Blackjack beats a 21 with more than 2 cards. See how these rules affect the simulation results.
- 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.
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.
Your writeup should have a simple format.
- A brief description of the overall task, in your own words.
- As 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.
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 handin folder on the Courses fileserver. Create a directory for each project inside the private folder inside your username folder.