Child pages
  • Yixuan's CS231 Project 1
Skip to end of metadata
Go to start of metadata

1. Summary

In this project, we simulated a simple version of the game Blackjack by implementing classes in Java to referent a card, a deck, hands, and the game Blackjack. The major data structure we use is array lists. I created an array list to represent a deck of cards and simulated the actions of the players by operating on the array list. My analysis did not work quite as expected and my speculation was that the number of games played was not large enough. 

 

2. The Card Class

Card holds all information unique to the card.

In the constructor, I did range checking to make sure the value of the card is in the range of 1-11, otherwise I had it automatically set the value to 2. 

I also created a getValue() method return the numeric value of the card.


3. The Hand Class

Hand holds a set of cards. 

I initialized an ArrayList to hold the Card objects in the constructor and implemented some other useful methods like reset(), add(), size(), getCard().

The getTotalValue() method returns the sum of the values of the cards in the hand.

I used a for each loop to sum up the value of cards in the hand.

The toString method() returns a String that has the contents of the hand.

I used a very similar approach--for each loop--to concatenate the strings.

  

4. The Deck Class

Deck holds a set of cards and is able to shuffle and deal the cards.

In the constructor, I call the build() method to build a deck of 52 cards.

I first created 40 cards with values 2-11 using a double for loop.


And then I built the rest 12 cards with the value 10 using a single for loop.


The shuffle() method is probably the most challenging and interesting part in this class. 

Firstly, I created an array list called old_deck that holds a set of cards and had it point to the array list that the field this.deck is referencing. And then I removed the old reference of this.deck and had it point to a new empty array list. 


Secondly, I created a Random object called rand to generate random numbers that represent the indices of the cards.


Next, I used a while loop to move cards from the old array list(old_deck) to the new array list(this.deck). The condition of the while loop is when n>0, where n is the size of old_deck. If there are still cards in old_deck, the program remove a card with a random index and add the removed card to this.deck. After one card gets removed, n decrements by 1.


The toString() method is roughly the same as that in the Hand class.

 

5. The Blackjack Class

Blackjack implements the card game and has a Deck, a Hand for the player, and a Hand for the dealer. 

The reset() method takes in a boolean parameter newDeck and shuffles a deck if newDeck is true.

The deal() method uses a for loop to deal out two cards to each player.

In the playerTurn() method, I used a while loop to have the player draw cards until the total value of the player's hand is equal to or above 16 and used an if statement to return either false or true depending on whether the player goes over 21.

The dealerTurn() method is basically the same.

The game() method plays a single game of Blackjack. First of all, it checks if the size of the deck gets below 26 and resets if necessary. After dealing out two cards to both players, I declared local variables and assigned them the result of relevant methods to keep track of the states of both players.

 

Based on the procedures, I first created an if statement to check if the player busts. If the player busts, it returns -1.

If the player did not bust, the dealer plays. I made a boolean for checking if the dealer busts and updated the dealer's final value of hand.

Then I used three if else statements to include all the other scenarios and return -1, 0, or 1 depending on the result.

 

Additionally, there is a boolean parameter called verbose. If it is true, then the function will print out the initial and final hands of both players and the result.

In the main function, I played three games with verbose being true.

 

6. Storing Game Output


I played three games and sent the results to the file mygames.txt.

 

7. Simulation

I made a Simulation class that has only a main function executing 1000 games of Blackjack.

Five samples of results are as below.

 


  • Are 1000 games sufficient to provide an accurate estimate of the win percentage for the player and dealer?

I personally do not think 1000 games is sufficient because the results still vary a lot, at least in the above five trials. The chance of the player winning and that of the dealer winning is not stable enough to predict.


 

8. Extensions


  1) Create a new function in your Blackjack class called playerTurnInteractive() that uses input from the terminal to control the player's actions. Then create a new class Interactive that lets you play Blackjack on the terminal.

 

In my Blackjack class, I imported the Scanner. And in my playerTurnInteractive() function, I created a Scanner object called kbd to get user input. 

I then call on kbd the method nextLine() to read a String from the keyboard after user presses enter. 

It will first ask the player whether to hit or stand.

If user enters hit, then a card will be added to the player's hand. And user can see the cards in their hand and the total value of the cards. 

If user enters stand or anything that is not "hit," then the dealer plays.

The rest is basically the same as the procedures in the game function.

Finally, I close the kbd before each return statement to prevent resource leaking.


There are 5 different scenarios:


  2) Make your game use 6 decks, and reshuffle if only 1 deck is left. Play the game 1000 times, and observe how many games the player wins, how many the dealer wins, and many are pushes. Compare with using only a single deck.

 

In my Deck class, I first implemented an overloaded constructor with a boolean argument to control the number of decks, in this case, 6.

Next, I created a method buildSix() in which it calls the build() method six times in a for loop. I also tried to add 312 cards using a double for loop and a single for loop like what I did in the build() function for one deck, since the difference between the simulation results using the two approaches is unpredictable, I eventually chose a more brief way to build 6 decks. I did not modify my shuffle method because I am always shuffling this.deck no matter how many decks there are. 

In my Blackjack class, I made a gameSixDecks() method. It is basically the same idea except the reshuffling condition.

 

I ran the SimulationSixDecks.java file five times and got the results below.

Despite the outlier, the percentage of the player winning is generally lower than that of the dealer winning. The results fluctuate less and are more stable than that of the simulations with only one deck.


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

 

In my Simulation class, I initialized an int M to be 1000 and enabled user to override the value from the command line only if args.length > 0.

As shown below, I can change the number of games I want to play every time I run Simulation by entering a command line argument.

 

I tried 10, 100, 1000, and 10000 number of games respectively. 

 

I ran 10 times for each value of M to calculate the standard deviation of the results and plotted a graph. 

 

As the number of games gets larger, the standard deviation of all three results becomes larger. The standard deviation of the dealer winning increases slower than the other two results do, which means above a certain large number of games, it becomes easier to estimate the percentage of the dealer winning accurately.

 


  • 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?

Roughly 11750.



4) Betting System

 

In my Blackjack class, I made a method called bet(). It uses the Scanner class and a while loop to play games.
It will first ask if the player wants to continue or not. If user enters yes, then it will show the amount of money left in the player's pocket. The initial value is 100.
Next, it will ask how much the player wants to bet. After user inputs the amount of stake, the bet() function calls the game() function in Blackjack and returns a result. Depending on the result represented by an int, the player win or lose the amount of money they bet before. If it is a tie, then the amount of money does not change.
User can quit the betting system if they do not enter 'yes.'

 

5) Indicate the line of code in which the last reference to an object referencing dynamic memory is removed.

Deck.java   line 76

I did not have enough time to find the other, if any.

 

9. Reflection

Through the project, I learned many new concepts of java, such as array lists and the Scanner class. At first, I got confused by the new language and had to think about its syntax that seemed unfamiliar to me, but I gradually became used to it and learned about many familiar but differently approached things like Random, classes, and variables. 


10. Sources

Professor Taylor

Prashant

Owen

Ethan

Caleb Chong

Professor Layton and his lecture notes