How to Lingo Part 8: Blackjack

I'm making one final substitution on the How to Lingo plan, based on the coverage of topics and the generally swift progress of this class. For our last trick we'll be taking on the classic card game Twenty-one, or Blackjack.

By Tuesday, November 4--at which point the entire How to Lingo project is due--you must produce a working Blackjack simulator based on the starter code I will provide. The starter version handles the player's side of the game only. You must modify this code to include a virtual dealer as well.

In the starter version, cards are represented by text strings. For extra credit you may substitute card images.

Rules of Blackjack

Blackjack is played against a dealer. There may be multiple players, but in our version we'll have only one. The dealer begins by dealing herself and the player each one card face down. Player and dealer may each look at their cards but are not allowed to look at each other's cards.

Cards are scored as follows: all suits are the same; face cards (King, Queen, Jack) are each worth 10 points; other cards count according to their number value, i.e., the three of clubs is worth 3 points; in some variations, an Ace may be counted for either 1 point or 10 points as the player prefers, but to make matters easier, we will always count the Ace as 1.

The object of the game is to score as close to 21 as possible without exceeding that number. If a player's total exceeds 21 he is "busted" and loses the game. If a player's cards total 21 exactly she has made "blackjack" and wins unless the dealer also makes blackjack, in which case he wins. If neither player nor dealer scores 21 by the end of the game, the higher score wins. The player announces the end of the game by "standing" or declining to accept any more cards. At this point the dealer reveals her hidden card, scores are totaled and compared.

There are additional rules and variations, but for the sake of simplicity we'll stick with these.

Setup of blackjackStarter.dir

The movie contains six fields and two buttons. On the left side of the screen, two fields represent the cards dealt to the player. The field at the top represents the concealed or "hole" card. The field below shows cards dealt at the player's request. At bottom left are two buttons, Hit and Stand. The player clicks the Hit button to request a card and the Stand button to end play and compare scores. A text field to the left of these buttons displays the player's score as we go.

At right are matching fields to display hole card, dealt cards, and total score for the dealer. The starter code does nothing with these fields so far. Also, the Stand button calls a handler called stand() which presently doesn't exist.

Starter code

All code for the game is contained in the main movie script. Some of this script has been written for you. There is already a startMovie handler that takes care of a few important details, such as setting up global variables for player's and dealer's card scores and blanking out the display fields. This script also creates a List containing the 52 names of the cards in a standard deck. This list is called deck.

The main script also deals the player her first, or "hole" card:

  -- pick a "hole" card for player
  cardPick = random(deck.count)
  newCard = deck[cardPick]
  Member("myHoleCard").text = newCard
  calcCards(newCard)
  deck.deleteAt(cardPick)

We begin by selecting an element from deck at random. The count property of the List gives its current length (52 at this point). We could have just used the number, since it's always the same, but you'll need to use this same logic later in the game with variable values, so I thought I'd introduce it here.

Once we have our card name assigned to the local variable newCard, we place it in the appropriate display field and then call a custom handler called calcCards(), which we'll explain below. Finally we do something really important: we use the deleteAt method of the List deck to remove the name of the card we just dealt. This prevents us from using that card again. It's another method of constraining random selection (the third you've seen so far, if you're counting), and utterly essential to card games.

Now about that calCards() handler. It's already written into the main script, and it looks like this:

on calcCards(theCard)
  
  global myCardsValue
  
  -- calculate value of cards
  if theCard contains "Ace" then
    myCardsValue = myCardsValue + 1
  end if
  if theCard contains "King" then
    myCardsValue = myCardsValue + 10
  end if
  if theCard contains "Queen" then
    myCardsValue = myCardsValue + 10
  end if
  if theCard contains "Jack" then
    myCardsValue = myCardsValue + 10
  end if
  if theCard contains "10" then
    myCardsValue = myCardsValue + 10
  end if
  if charToNum(char 1 of theCard) < 65 
  and charToNum(char 1 of theCard) > 49 then
    myCardsValue = myCardsValue + char 1 of theCard
  end if
  
  if myCardsValue > 21 then
    go to "busted"
  end if
  
  if myCardsValue = 21 then
    go to "winner"
  end if
  
  Member("myCardsValue").text = string(integer(myCardsValue))  
  
end calcCards

First, remember how arguments work. We pass the variable newCard to this handler as its argument. That variable contains the name of a card, selected at random from the deck List. That card name is plugged into the variable theCard. Then we ask a bunch of questions about this variable, or card name. Card names are constructed as valueSuit, so that the Ace of Clubs is "AceClubs," the Three of Diamonds "3Diamonds," etc. We ask if any significant subname such as Ace, King, Queen, or Jack occurs within theCard. We also include the number ten here for reasons that will be clear below. If we have a match at this point, we increment the current score either by 1 (for Ace) or by 10 for face cards and the Ten of any suit.

Then we come to that chunk of code that uses the charToNum() method. This method converts a letter or number into its corresponding ASCII code, an indexing system that assigns a serial number to every character in the standard keyboard set. We can use this number to tell us whether the first character of theCard is a letter or a number greater than 1. If it's a letter, we're dealing with an Ace or a face card. If it's a 1, then we're dealing with a Ten, since there is no One of any suit. If the first character is neither of these, then we're dealing with a number card between Two and Nine. In that case we simply treat the first character as a mathematical value, since it's after all a one-digit number.

Following all this, we test the current score value. If it exceeds 21 then we jump to the "busted" scene. Presently we declare the player the winner if he scores 21 exactly, though that's not according to the rules and you'll need to change it. The last line assigns the score value to a display field.

Your mission...

You'll find two blank handlers in the main script, one called dealCard() and the other stand(). The first is called by the Hit button, the other by the Stand button.

The dealCard() handler must select a card at random from the deck, display that card value in the player's dealt-cards field, pass the name of the card to calcCards(), and--crucially!--delete the card from the deck.

You need to write the code for these transactions. You might start by looking at the code that selects the player's hole card in the startMovie handler.

The stand() handler is more complicated. To make it work you'll first have to figure out how and when the dealer gets cards. Remember that the dealer's hole card must remain concealed until stand() is activated. You'll also need to give the dealer one crucial bit of artificial intelligence: a rule for determining whether to take more cards or stand on the present score. Traditionally, dealers stop taking cards when their score exceeds 16.

Source file

The source file is called blackJackStarter.dir. It was made available for download from the A204Student directory in class on October 28. If you missed this class you may download the file from the mult201 directory on crow.ubalt.edu; or send me email (smoulthrop@ubalt.edu) and I'll send you the file.


University of Baltimore Logo

Copyright © 2003 School of Information Arts and Technologies