ulrail.gif

HW J4: Blackjack

  ur-2c.gif urrail.gif
blrail-nonavbar.gif

Home | Resources | Homeworks | Exams
Slides | Labs | Contacts | Submit | TAs

br-2a.gif   br-2c.gif brrail.gif
spacer.gif spacer.gif spacer.gif

Purpose

In this homework, you will gain more experience using loops by implementing a simplified version of the card game Blackjack. 

If you are unfamiliar with Blackjack, you may want to read Wikipedia's Blackjack page.  We also provide a short introduction to the game below.

For those who are familiar with Blackjack, there are a number of rules in blackjack that we are ignoring: splits, doubling down, insurance, an Ace counting as 1 or 11 (and thus "soft" hands), and all issues dealing with money and bets.  The version you submit should not have these parts included.

Background -- Cards and Blackjack

If you know Blackjack, you can skip this section.

A standard deck of cards has 52 cards, the cards are split evenly into four suits: spades (♠), hearts (), diamonds () and clubs (♣).  Note that two of the suits are colored red (hearts and diamonds) and two are colored black (spades and clubs).  In this assignment, we will be abbreviating the suits by their first letter: "S", "H", "D", and "C", respectively.

Each suit has 13 "face cards", values 1 through 13.  1 is called an Ace, 11 is called a Jack, 12 is a Queen, and 13 is a King.  The picture above shows an Ace of hearts and a Jack of clubs.

Blackjack is a card game, where you are the player, and the computer is the dealer. The goal of the game is to get as high a score as possible without going over 21 (going "bust").

At the beginning of each hand, the dealer shuffles the deck. Then, during the game, the dealer draws each card from the top of the deck. Card faces 2 through 10 count 2 through 10 points, respectively.  Face cards (Jack, Queen, and King) count 10 points, and an Ace counts 11. (In the real game aces count 1 or 11, but that makes things too complicated, so we assume here Aces count only 11.) 

The dealer begins by dealing two cards to you, the player, and then two cards to itself. It shows you both of your cards, but it only shows you one of its cards. Your current score is the sum of your two cards.  It then repeatedly gives you the option of drawing another card, until either you decline, hit 21 points, or you go bust (over 21 points). It then deals cards to itself. The computer must draw until it reaches at least 17 points, and must not draw any cards once its total reaches 17 (it "hits" on 16 (i.e. takes another card) and "stands'' on 17 (i.e. doesn't take another card)).

If neither you nor the dealer go bust, the winner of the game is the one with the most points. If both point totals are the same, the game is a tie. You lose immediately if you go bust. This is the "house advantage", and is why casinos make money. In this case no more cards are dealt. If you do not go bust but the computer does, then you win.

Design

Not surprisingly, there will need to be a number of loops in this homework -- many of the steps below require one or more loops.  The game must allow the user to play multiple hands, so there is an outer loop as well. 

Within the program, a number of things must happen:

  • Create the deck.  The deck is just a Vector that contains 52 Card objects (see below for more details).
  • Shuffle the deck (also see below)
  • Deal cards to the computer and the player. 
    • Note that you should not show the dealer's first card until after the player is finished. 
    • The player is dealt one card, then the dealer is dealt a hidden card, then one more to the player, then one more to the dealer.
    • You can hard-code these four dealt cards -- meaning you don't need to use a loop here (and it's probably easiest not to)
  • Ask the player if s/he wants another card, and give the player cards until the user enters 'no'.  Check for a 21 or a bust (going over 21) after each card is dealt.
  • If the player did not bust, deal cards to the computer (until the computer reaches or goes over 17, or busts).
  • Figure out who won.
  • Ask to play again.  If the player is playing again, it's easiest to fully re-create the deck each time.

Your code must be in a public class named Blackjack, in a file named Blackjack.java.  Our solutions required about 100 lines of code.

Note that you should only ask for input (via the YesNoExtractor class) for two things: asking the the player if s/he wants another card (this may happen multiple times in a round), and asking if s/he wants to play another round.

The good programming practices from HW J1 need to be in this homework as well.  However, you do not have to echo input that was read via the askUser() method in the YesNoExtractor class.

Class Card

To assist you a class Card has implemented.  Right click on that link, select "save as", and save it to the SAME directory that your Blackjack.java file is in.  The class has the following public methods.

  • Card(int i)
    • If i is in the inclusive interval 1 ... 52 then a card is configured in the following manner
      • If 1 <= i <= 13 then the card is a club
      • If 14 <= i <= 26 then the card is a diamond
      • If 27 <= i <= 39 then the card is a heart
      • If 40 <= i <= 52 then the card is a spade
      • If i % 13 +1 is 1 then the card is an Ace
      • If i % 13 +1 is 2, then the card is a 2
      • ...
      • If i % 13 +1 is 10, then the card is a 10
      • If i % 13 +1 is 11, then the card is a Jack
      • If i % 13 +1 is 12, then the card is a Queen
      • If i % 13 +1 is 13, then the card is a King
  • String getFace()
    • Returns the face of the card as a String.  For example, an Ace returns an "A", a 2 a "2", an King a "K", etc.
  • String getSuit()
    • Returns the suit of the card as a String ("S", "D", "C", or "H").
  • int getBlackjackValue()
    • Returns the blackjack value of the card -- an Ace is 11, and a Jack, Queen, and King are all 10.
  • int getValue()
    • Returns the value of the card (an Ace is 1, Jack is 11, Queen is 12, and King is 13).
  • String toString()
    • Returns a String version of this card -- useful for printing.

Class YesNoExtractor

The YesNoExtractor class should be used to get user input, and supports the following methods.  Right click on that link, select "save as", and save it to the SAME directory that your Blackjack.java file is in.  This is the same class used in HW J3.

  • public YesNoExtractor()

    • The default constructor configures the new YesNoExtractor so that it displays messages to standard output and extracts information from standard input; that is the YesNoExtractor reads input from the keyboard (System.in) and writes to the screen (System.out).

  • public boolean askUser(String message)

    • Causes the YesNoExtractor to query the user for a yes or no response after printing the message. If the user indicates yes, then true is returned. If the user indicates no, then false is returned. If the user indicates something else, then the question is reissued until a proper reply is given.

    • Note that you can also enter "q" or "quit", which will immediately exit the program (this is new since HW J3).

Hints

There are a few parts of this homework that will be a bit challenging, and some of them are addressed here.

The easiest way to keep your "deck" of cards is in a Vector (if you forgot about Vectors, see HW J2).  Given an int variable i, you can create a Card object via new Card(i) -- then add that to your Vector.  To shuffle your deck, you can use the shuffle() method in the Collections class.  Assuming your Vector is named deck, to shuffle it you would use the following statement.

Collections.shuffle(deck);

To verify that the deck is shuffled, you can use System.out.println (deck.toString());.  Note that this and other similar debugging statements should NOT execute in your final version of the code (leaving them in and commenting them out might be a good approach here).

Then you can pick cards right out of the top of the deck (meaning the front of the Vector).  Recall that when you remove something from a Vector, you need to cast it back to whatever class it is (in HW J2, it was a String; here, it's a Card).  Thus, to get the first card from the deck (and also remove it from the deck), you use (Card) v.remove(0), assuming v is your Vector.  Also recall that you will get some compiler warnings ("uses unchecked or unsafe operations") -- you can safely ignore these.

You don't have to keep track of all the cards that were dealt to the player or the dealer.  Once they are printed out to the screen, you just have to update the player's total (and the dealer's total), and can then forget about the card dealt.

Where to start: Start by implementing each step in succession, and testing those steps out.  You can put in extra print statements to do such.  For example, after you write the code to create and shuffle the deck, print out the deck and run it a few times to make sure it works.  The big loop that allows the player to play multiple hands can be added in at the end.

Sample Execution Run

The text in red is what was entered by the user.  Note that your output doesn't have to precisely match ours, but the general idea should still be there.

Let's play some blackjack!

You are dealt a 6S
Dealer is dealt a hidden card
You are dealt a 2D
Dealer is dealt a 4H
Your total is 8
Would you like another card? (y/n) y
You are dealt a AD
Your total is 19
Would you like another card? (y/n) n

The dealer's hidden card was a 8H
Dealer is dealt a 10C
The dealer's total is 22

Your total is 19
The dealer's total is 22
The dealer busted! You win!

Play another round? (y/n) n

Submission

When you are finished, submit the Blackjack.java file.

spacer.gif
spacer.gif footer-middle.gif spacer.gif