Project 1: Monte-Carlo Simulation: Blackjack Assigned: Sun Sep 08 2013 Due: 11:59:59 PM on Mon Sep 16 2013 Team Size: 1 Language: Java 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.
Resources
Setup You probably want to keep your code on your network directory. You can mount your personal volume using this URL: smb://filer/personal/students/<first initial>/<username>
Once mounted, If you are on a terminal on a Mac, you can get to the working directory using cd /Volumes/<username>
From the Finder you can also drag any folder onto a Terminal window and it will create the complete path to the folder.
Practice - Create a working directory for today's lab. Then start a Java file,
Shuffle.java . You'll use this to practice creating lists and filling them with random numbers. - At the top of the file, add lines to import the ArrayList and Random packages:
import java.util.ArrayList; import java.util.Random; - Create a Shuffle class with only a main method. The header for that method should look like this:
public static void main(String[] args) { - Your main method will print out ten random numbers. Write appropriate JavaDoc for your main method:
/** * Prints ten random numbers. * @param args This parameter is unused. */ public static void main(String[] args) { - In your main method, initialize a new ArrayList object and a new Random object. Then use a for loop to add ten random integers between 0 and 99 to the list. (Use the API resources listed above to determine how to use the ArrayList and Random classes.) Have your for loop print out the random numbers as they are generated (use
System.out.println(...) ). - Add another loop that iterates through the list and prints out each value in turn.
- Iterate again through the list. Each time through, remove one element and print out the remaining numbers. (You can print without adding a new line using
System.out.print instead.) The output of this part should look something like:
Removed: 42. In List: 66, 23, 7, 12, 81, 16, 37, 55, 12, Removed: 66. In List: 23, 7, 12, 81, 16, 37, 55, 12, Removed: 23. In List: 7, 12, 81, 16, 37, 55, 12, Removed: 7. In List: 12, 81, 16, 37, 55, 12, Removed: 12. In List: 81, 16, 37, 55, 12, Removed: 81. In List: 16, 37, 55, 12, Removed: 16. In List: 37, 55, 12, Removed: 37. In List: 55, 12, Removed: 55. In List: 12, Removed: 12. In List:
You can probably get your output to be more awesome than that! :) - Change things around so that instead of assigning random numbers to the list, it assigns each of the values 1 through 10 once. Run your program multiple times and look at the behavior. (Make sure each element only appears once!)
- How can you programatically create a random permuatation of a set of elements? Come up with two alternatives and decide which is easier to program. In this week's assignment, shuffling a deck of playing cards involves creating a random permutation of the set of cards in the deck.
Once you're comfortable with this practice, move on to the next part.
Assignment Tasks 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. This is known as a unit test. Ideally, a unit test should try out all of the class methods and access all of the class variables. Having a proper unit test 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 class JavaDoc and header should look something like this:
/** * This models a Blackjack card. * * @author <Your Name> */ public class Card {
This class should have the following methods. In addition, make a main method that uses each of the class methods. (I've provided the JavaDoc and headers for this class as examples.)- A no-argument constructor:
/** * Class constructor. */ public Card() { - A constructor with the value of the card.
/** * Class constructor. * * @param value The numeric value of the card (1-10). */ public Card(int value) { - A getter for the card's value.
/** * Gets the numeric value of the card. * * @return The integer value of the card, between 1 and 10. */ public int getValue() { - Returns a String representation of the card. This method is automatically called by Java in common String operations.
/** * Returns a String representation of this. * * @return A nice String representation of this. */ public String toString() { - Don't forget the unit test!
/** * Main method for unit testing. Usage examples: java Card java Card 8 * * @param args Command line arguments for this. */ public static void main(String[] args) {
- 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 methods:
public Hand() - initialize the ArrayList.public void reset() - empty the hand.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 index) - returns the i-eth card in the hand. For the JavaDoc on this one, you will need lines to describe both the parameter and return value.public int getTotalValue() - returns the sum of the values of the cards in the hand.public String toString() - returns a nice string representation of this.- Don't forget the unit test! (Do this for all classes, even if it's not listed.)
- 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 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.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 index) - (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 String toString() - returns a nice string representation of the deck so 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, and a Hand for the dealer.
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 start with a fresh, shuffled deck.public void deal() - should deal out two cards to both players.public String toString() - returns a nice string representation of 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 void play() - the play method should deal, print the state, then have the player go, and 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. 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 the output to the file MyGames.txt. - Add another (public) method 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.
Extensions 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.
Hand-In 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: cs231f13project1 . 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.
This is an adaptation of this project by Bruce A. Maxwell.
|