For this first project, we had to simulate a game of Blackjack. It was my first time using Java, so it was a little rough, but I managed somehow.
Task 1 was to create a Card class, which holds info about an individual card. My constructor class has an int parameter that lets the programmer decide what value, from 1-10, the card can have. In the class, there is a private int "cardValue" in which this is stored. The later classes need to access this info a lot. In my main method, I tested the card class by telling it to make a new instance with the value 10, and to print out the value using the getValue method. I used this to do it:
Task 2 was to make a "Hand" class, which represents both the player and the dealer's currently held cards. Since the Card class is in the same directory/package as Hand, I learned that I don't need to import it like in Python. I did, however, need to import ArrayList so I could make an array list for the class that holds Card objects. The hand object therefore inherits all of the methods that an arraylist has, but I still needed to make more. I made an add method to add a card into the hand, a get method to return the card at a given location, and a reset method to empty the hand, for example. There is also a getTotalValue function, which adds up all the values of the card and returns that as an integer, as well as a size method that just says how many cards are in a given hand. Then, from my main function, I created a hand object and new Card objects, added the cards to the hand, and called a method to print out the information about the hand. That method contained the following:
First I print out each value of each card with commas between, and once I get to the last one, I switch to saying "and" before the value. Then I sum up the cards using the getTotalValue method and return the string, which main prints out using System.out.println().
Task 3 was to create a Deck class, where all of the actual cards that would be used were created.To decide which cards and how many of each to add to the array list (I called it "deckArray") holding the cards in this class, I used the following:
I added 4 of each card, looping through from 1-9 to decide which value to give each card object. Then, I made 16 cards with the value 10 in a similar fashion. This was done in my build method. Another important method in this class is shuffle. This needs to make the cards in the deck be in a random order. For this, I copied the contents of the original deckArray into a new array list called "randDeck" and then made the original deckArray into a new empty one. I removed the contents of randDeck randomly and put them into deckArray until it was full. Note that to use a current-time seed for random, I put
at the top of the class.
For Task 4, the actual algorithm for playing a game of Blackjack was created. It begins by dealing both the player and dealer two cards each, then letting the player go first, then the dealer. If the player already has a total card value of 16 or above, it skips any further action, but otherwise, more cards are drawn until the hand is at 16 or up. If a total value of more than 21 is held, the player's turn will end, because the boolean will return false. Upon seeing this, the game will terminate and the dealer will have won. Otherwise, if the player is at or between 16 and 21, the dealer goes next, given less than a total value of 17 is held. The dealer, like the player, can lose by "busting" at 22 or more, and if the dealer has 17 or more but the player has a bigger number than that from the start, the player wins. They can also tie if both players do not want to draw and end up with the same number, or just have the same total after drawing. I checked for these various conditions in a series of if statements, which are in my playGame function. I also have it call the reset method every time, so that the hands are emptied and the Deck is reshuffled and refilled.
Task 5 was just to send a printout of three different runs of the game to a text file. I had the following print out after putting the game algorithm in a for loop to make it run three times:
Task 6 was to make it so the wins return 1s, the losses return -1s, and the ties return 0s. I just followed every outcome possibility and returned the appropriate number.
The last task was to make a class called Simulation that runs through the game 1000 times, recording the number of wins, losses, and ties, and their percentages, as well. I made integers to record the number of each, and then printed the results. Here is an example of this:
The player draws three cards, but then busts, as the output shows. Also, out of 1000 trials, there were 402 wins for the player, 504 wins for the dealer, and 94 ties. I noticed that the player almost always lost, sometimes even if only by a little, to the dealer.
As for extensions, I did extension 3. I made the player stop drawing if their hand was 15 or over, then 17 or over, and then 18 or over. I noticed that the further from 17 the player was, the fewer wins they would have. Out of 28000 runs, for instance, the player stopping after 18 won 37.71 percent of the time, on average. With 15, it was 39.63% on average. With 17, the player won 40.45% of the time. But even with the 17-strategy, I observed that on average, from looking at 12 trials of 1000 results each I ran, the dealer scored 7.08% more. I believe that this is a result of the player drawing cards first, because the player has the chance to bust before the dealer does, which provides extra chances for the dealer to win without doing anything. When I made the number of trials 10,000 I also noticed that there were fewer and fewer times that the player won a higher percentage of the game, but at the same time, the margin by which the dealer won became smaller. As the number of trials increased, the percentage stabilized, and the player usually lost by about 6-8% with results such as 40% to 45% or 42% to 49%. I think that by running around 10,000 trials, there will almost always be a chance to have 10 times in a row of just the dealer winning.
I did another extension, which wasn't on the list, but I thought it would be better to show the card names to better reflect how cards actually look. For all of the cards with the value of 10, they could actually be an ace, queen, king, or jack. I represented these with their first letters. In order to make the Blackjack program recognize when to print out a letter instead of the value, I added a field to the card class called cardName, which was a string that had a method to set and to return it. Then, when building the card in Deck, I divided the 16 cards of value 10 into 4 groups for each of the 4 categories. I added their values like normal, but then I also gave them names for the cardName field. Lastly, in the Blackjack class, where the text that the printed out deck will have is, I checked if the card value was 10, and told it to display the name instead of the value, but proceed on just displaying the values like normal for the rest. The functioning printout showing the letters on the cards is show below, as well as the features from te Card, Deck, and Blackjack classes I mentioned here.
This project taught me a lot about java. I learned about many concepts I'd never heard of, such as class constructor methods, fields, and class types. I learned how to think about what access type to give variables through fixing many errors, and I had several times where I had to restart and approach something that didn't work at a different angle, because sometimes the answer was simpler than I thought.
Many thanks to: