Overview · Rules · Files · Tasks · Simulation · Testing · Report Format · Checklist
In Project 1 you will build a simplified Blackjack simulation from several
cooperating Java classes: Card, Hand,
Deck, and Blackjack. You will then use those
classes in Simulation to study the outcomes of many games.
ArrayList is now a building block. Both
Hand and Deck must use the ArrayList class you
implemented in Lab 1. Methods such as add, get,
remove, size, and toString now
become tools for building larger classes.
The goal is not primarily to create a game for a person to play. You are using computation to study the behavior of a system defined by a set of rules.
Create a folder named Project1. Leaving
ArrayList.java in the Lab1 folder you
created, make a copy of ArrayList.java and add the copy to
your Project1 folder. Then download the Project 1
skeletons and testers below into the same folder.
A Card stores one integer value. Complete the provided
Card.java.
Card(int val) stores the supplied value.getValue() returns the value.toString() returns the value as a String; a Card with value 5 produces "5".Compile and run CardTester before continuing.
A Hand contains an ArrayList<Card>.
This is your first use of the data structure you implemented in Lab 1
as part of a larger class.
Hand() creates an empty hand.reset() makes the hand empty.add(Card card) adds a Card.size() returns the number of Cards in the hand.getCard(int index) returns the Card at an index.getTotalValue() sums the values of all Cards.toString() includes the Cards and total value. For example: [2, 3, 4] : 9.Compile and run HandTester before continuing.
A Deck also contains an ArrayList<Card>,
but it has different responsibilities: building the complete deck,
dealing Cards, and shuffling the Cards that remain.
Deck() creates the ArrayList and uses build() to create a complete deck.build() replaces the current deck with 52 Cards: four each of values 2–9, sixteen 10s, and four 11s, and then shuffles the completed deck.size() returns the number of Cards currently remaining.deal() returns and removes the Card at index 0.toString() shows the Cards currently in the deck.deal() needs exactly the behavior you implemented in
ArrayList.remove(index): return an element and remove it
from the list.
shuffle() must rearrange the Cards currently in the deck
without adding Cards, losing Cards, or changing their values.
One way to shuffle the Deck is to build a new
ArrayList<Card> in random order.
ArrayList<Card>.To generate a random valid index, you can use:
Random rand = new Random(); int index = rand.nextInt(cards.size());
remove(index) both removes and returns the selected Card.
Each removal also decreases the size of the original ArrayList, so
cards.size() causes the next random index to be selected
only from the Cards that still remain.
For example, conceptually:
Original: [A, B, C, D] Shuffled: [] remove random C Original: [A, B, D] Shuffled: [C] remove random A Original: [B, D] Shuffled: [C, A] remove random D Original: [B] Shuffled: [C, A, D] remove random B Original: [] Shuffled: [C, A, D, B]
When no Cards remain in the original ArrayList, the new ArrayList contains exactly the same Cards in a randomized order. Make the Deck's ArrayList instance variable refer to this new list.
remove(index) returns the removed element and shifts the
remaining elements left, size() changes as elements are
removed, and add() builds the new ArrayList.
Compile and run DeckTester before continuing.
Blackjack brings the previous classes together. It contains
a Deck, a player Hand, and a dealer
Hand.
Blackjack() creates the Deck and the player and dealer Hands. The Deck constructor builds and shuffles the initial deck.reset() clears both Hands. If fewer than 26 Cards remain, call build() to replace the Deck with a complete, shuffled 52-card deck.deal() deals two Cards to each Hand.playerTurn() draws until the player's total is at least 16 and returns whether the player avoided a bust.dealerTurn() draws until the dealer's total is at least 17 and returns whether the dealer avoided a bust.toString() provides a useful representation of the current game.game(boolean verbose) plays one complete game and returns -1 for dealer win, 0 for push (tie), or 1 for player win.
When verbose is true, print the initial hands, final hands,
and the result of the game. When it is false, the method should play the
game without printing the game trace.
game() plays the current game; it does not reset the game
first. After recording the result of a game, call reset()
before playing the next game.
Run BlackjackTester, then run several verbose games yourself.
Complete Simulation.java to run repeated Blackjack games.
Run your simulation for:
For each experiment, record the percentages of player wins, dealer wins, and pushes (ties). You may run these three simulations separately.
Your Simulation program should choose a number of games,
call game(false), record the returned result, and then call
reset() before the next game. Count each possible outcome,
then calculate and print the percentage of each outcome.
game(false) returns -1 for a dealer win,
0 for a push (tie), and 1 for a player win.
We are deliberately not giving you expected outcome percentages. Part of the experiment is to use your simulation results to investigate the long-run behavior of the game.
Look for a trend rather than a particular answer. Compare your results from 100, 1,000, and 10,000 games and observe whether the outcome percentages appear to become more stable as the number of simulated games increases.
Use those observations to make a reasonable estimate of where you think the percentages may be heading. You will discuss this evidence and your interpretation of it in your report.
The provided testers are designed to help you make incremental progress. Work through them in order. Where possible, each test focuses on one method or behavior and shows the operation being called alongside the expected and generated behavior. Use the first failing test to help identify what to work on next.
javac *.java java CardTester java HandTester java DeckTester java BlackjackTester
In particular, DeckTester checks that shuffle preserves the
complete deck and changes its order. It does not attempt to prove the
statistical quality of your shuffle.
Your intended audience for your report is your peers who are not in this class, but who have taken a computer science course. Your reader should be able to understand what you built, the important computer science ideas behind it, what results your program produced, and what those results mean without having completed this assignment themselves.
A good report does more than describe what the program does. It uses output from the program as evidence and explains what can reasonably be concluded from that evidence.
Your project report should contain the following sections. Please include a header for each section.
The Abstract is a brief summary of the entire project, written in your own words. It should be no more than a few sentences.
Identify both sides of the project:
When discussing a data structure, describe what it does and why it is useful, rather than simply describing what its printed output looks like.
A strong abstract should give the reader enough context to understand the purpose of the project and briefly identify the most important result or conclusion. Detailed numerical results belong in the Results section.
The Results section presents evidence generated by your program and your interpretation of that evidence.
For Project 1, include output from three different verbose Blackjack games. Use these examples to demonstrate important game behaviors and explain why the results are consistent with the rules implemented by your program.
Also present the outcome statistics from simulations of:
For each simulation, clearly report the percentages of player wins, dealer wins, and pushes (ties).
Do not simply paste program output into the report. For important results, organize your discussion around these three steps:
Be careful to distinguish what your results show from what you believe explains them. If you propose an explanation, connect it to specific rules or behavior in your program.
Your discussion should address questions such as:
Use specific numerical evidence when making claims about your results.
A few individual games are useful for checking and demonstrating behavior, but they do not prove that the program is correct in every possible case. Describe them as evidence that particular behaviors are working as expected.
Similarly, passing the provided testers is evidence that important cases work; it is not proof that the entire program is correct.
The Results section is not a user's manual. Do not spend significant space
explaining how to compile the program, change constants, edit
main, or run commands unless that information is necessary to
understand a particular result.
Describe any work you completed beyond the required project. Focus on the design and behavior of the extension, rather than providing step-by-step instructions for using it.
Explain:
Include appropriate evidence such as program output, tables, graphs, or figures.
For an interactive extension, for example, do not simply describe which commands the user types. Explain how you changed the program so that user input can affect the behavior of the game.
If you did not complete an extension, simply state that no extension was completed.
List the people and outside resources that contributed to your work.
Include people you worked with or received help from, including TAs and instructors. Also acknowledge anyone whose code you may have seen or discussed, including friends or students who have taken the course in a previous semester.
List outside references or resources that you used while completing the project.
You do not need to list standard Java classes such as Random
simply because you imported them. If an outside source helped you
understand how to use a library, algorithm, or programming technique, cite
the source you actually consulted.
ArrayList.java.Card.java, Hand.java, Deck.java, Blackjack.java, and Simulation.java compile.