Overview · Rules · Files · Tasks · Simulation · Testing · Report Format · Checklist

Overview

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.

From Lab 1 to Project 1: Your 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.

Simplified Blackjack Rules

Files Provided

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.

Card.java CardTester.java Hand.java HandTester.java Deck.java DeckTester.java Blackjack.java BlackjackTester.java Simulation.java
Work in order. Each class depends on work from the previous tasks. Get a class working with its tester before building the next layer.

Tasks

Task 1 — Card

A Card stores one integer value. Complete the provided Card.java.

Compile and run CardTester before continuing.

Task 2 — Hand

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.

Compile and run HandTester before continuing.

Task 3 — Deck

A Deck also contains an ArrayList<Card>, but it has different responsibilities: building the complete deck, dealing Cards, and shuffling the Cards that remain.

Part A — Build and use the Deck

Notice the connection to Lab 1: deal() needs exactly the behavior you implemented in ArrayList.remove(index): return an element and remove it from the list.

Part B — Shuffle the Deck

shuffle() must rearrange the Cards currently in the deck without adding Cards, losing Cards, or changing their values.

Shuffling by Building a New ArrayList

One way to shuffle the Deck is to build a new ArrayList<Card> in random order.

  1. Create a new, empty ArrayList<Card>.
  2. While Cards remain in the Deck's current ArrayList:
    • Generate a random valid index.
    • Remove the Card at that index from the current ArrayList.
    • Add the returned Card to the new ArrayList.
  3. When the original ArrayList is empty, make the Deck's instance variable refer to the new ArrayList.

To generate a random valid index, you can use:

Random rand = new Random();
int index = rand.nextInt(cards.size());
Notice what happens as you work: 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.

Connection to Lab 1: This algorithm depends on several behaviors you implemented yourself: 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.

Task 4 — Blackjack

Blackjack brings the previous classes together. It contains a Deck, a player Hand, and a dealer Hand.

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 lifecycle: 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.

Task 5 — Simulation

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.

Remember: game(false) returns -1 for a dealer win, 0 for a push (tie), and 1 for a player win.

What Happens as the Number of Games Increases?

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.

Testing

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
Basic Tester Self Check: Passing the provided testers is an important milestone, but the testers perform only basic checks. Passing all tests does not guarantee that every possible case in the project is correct.

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.

Report Format

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.

Abstract

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.

Before finishing your Abstract, ask yourself:

Results

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).

Evidence → Observation → Interpretation

Do not simply paste program output into the report. For important results, organize your discussion around these three steps:

  1. Evidence: Present the relevant output, table, figure, or numerical result.
  2. Observation: Describe what the result actually shows.
  3. Interpretation: Explain why you think the result occurred and whether it makes sense given the rules and design of your program.

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.

Program Output as Evidence

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.

Keep the Results Focused on Results

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.

Your emphasis should be: What happened? Why is it interesting? Does it make sense?

Extensions

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.

References/Acknowledgements

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.

Before You Submit

Remember: The provided testers perform only basic checks. Passing all of their tests does not guarantee full credit on the project. Your implementation must satisfy the complete project specification.