Bookmark and Share

Blackjack

Play the game or view the source code.

First, take a break and play the game to get an idea of how it works. You'll see that various elements on the page are dynamically updated, added and removed during the course of play. Be sure to read the rules provided. It will help in understanding much of the program flow and comments in the rest of this article.

Games necessarily require a good deal of interaction and dynamic content. This one demonstrates many features of style sheets, scripting and use of the Document Object Model (DOM). As it is a fairly large script, some details of the code are omitted. The comments in the source should help explain the finer points and other articles on this site provide good information on many of the techniques used, particularly on using CSS and the DOM.

Page Layout

If you look at the HTML for the game page, you'll see that it is broken up into several areas using DIV tags. First there are the areas for the dealer and player made up of a main DIV tag containing other DIVs for the cards and text messages.

<!-- Dealer's area. -->

<div id="dealer" class="playingField">
  <div class="textBox name">Dealer</div>
  <div id="dealerScore" class="textBox">&nbsp;</div>
  <div id="dealerCards" class="cardArea"></div>
</div>

<!-- Main player's area. -->

<div id="player0" class="playingField">
  <div class="textBox name">Player</div>
  <div id="player0Score"  class="textBox">&nbsp;</div>
  <div id="player0Bet"    class="textBox dollars">&nbsp;</div>
  <div id="player0Result" class="textBox result">&nbsp;</div>
  <div id="player0Cards"  class="cardArea"></div>
</div>

The style class textBox specifies float:right; so all the text blocks appear on the far right of these areas while the cardArea DIV takes up the rest of the space in the main DIV. The card area is initially empty but will be filled and cleared dynamically as the game is played.

Additional Player Areas

Although the game is designed for a single player, it does allow "splits." That is, when the player is dealt a pair on his or her first two cards, he or she can split the cards into two separate hands. Likewise, either of these can be split again if another pair is dealt.

To accommodate this, three other sets of DIVs are defined in the code. These are exactly like the main player's area except for the the IDs assigned to each element. The rules limit the player to a maximum of three splits in any round so three additional areas are needed.

<!-- Areas for the player's split hands. -->

<div id="player1" class="playingField" style="display:none;">
  <div class="textBox name">Player</div>
  <div id="player1Score"  class="textBox">&nbsp;</div>
  <div id="player1Bet"    class="textBox dollars">&nbsp;</div>
  <div id="player1Result" class="textBox result">&nbsp;</div>
  <div id="player1Cards"  class="cardArea"></div>
</div>

...

As they are usually not used, they have an inline style specifying display:none; to keep them hidden from view. Should the player split a hand, this style setting will be changed programmatically to display the an area and likewise, set to display:none; again when no longer needed.

Style Note

Setting display:none; differs from setting visibility:hidden; in that a non-displayed element does not take up space on the page while one that is merely hidden does, even though the element itself will not be visible.

Control Buttons

Below the playing areas is a form with several buttons. Each has a function assigned to it using the onclick event to allow the player to take various actions during play.

Some buttons are initially disabled. During the course of the game, individual buttons will be dynamically enabled or disabled by the script depending on various circumstances. This way, the user will only be able to choose from whatever options are valid at any given point in the game.

For example, the player can only surrender at the start of a round when the first two cards are dealt. Should the player choose to hit, stand or take any other option instead, the "Surrender" button is disabled for the remainder of the round.

This helps reduce the amount of code needed as we don't have to check if a given action is valid each time. It also helps the user by giving a visual clue at to what options are available at any given time.

Other Areas

To the right of the control buttons are two more DIVs for displaying the player's current credit line and and his or her default bet. The player will be allowed to change this bet amount before each round and the credits will automatically be updated as hands are played and won or lost.

At the bottom of the page the rules are printed. Like the additional playing areas these are in a DIV tag with display:none; set as an inline style to initially hide it. One of the form buttons calls a function that will toggle this setting, allowing the player to view the text at will.

The Playing Cards

The cards themselves are created using two user-defined JavaScript objects, Card and Stack, which represent individual cards and sets (decks) of cards respectively.

See CSS Playing Cards and JavaScript Card Objects for details.

The Card object also provides a means to dynamically display any given card on the page. As these objects are described in previously featured articles on the site, the details won't be discussed again here. You can view the articles at right for some background information if you haven't already read them.

Suffice to say, these objects will allow us to create a deck of cards, shuffle it, deal cards from it and create DOM nodes for displaying individual cards on the page.

In the interest of reducing file size, the code for the Card and Stack objects has been stripped down in this script to include only the features needed for the game.

Handling the Deck

The deck (or shoe) is initially created by a call to the newDeck() function which creates a new Stack object, fills it with cards and gives it a good shuffle.

function newDeck() {

  // Create a deck.

  deck.makeDeck(numPacks);
  deck.shuffle(numShuffles);

  // Set the burn card.

  burnCard = Math.round(Math.random() * 26) + 13;
}

It also randomly selects a number to signify a "burn" card near the bottom of the deck. Before any new round is started, the number of cards left in the deck is checked against this value. If the burn card has been reached or passed, a brand new deck is created by calling this function again.

This is done to help prevent running out of cards during play. But it's still a possibility (especially if the player splits or even resplits) so whenever a card needs to be dealt, the getNextCard() function is used rather than calling the Stack object's deal() method directly.

function getNextCard() {

  // If there are no cards left, start a new deck.

  if (deck.cardCount() == 0) {
    alert("New Deck");
    newDeck();
  }

  return deck.deal();
}

If first checks whether the deck is empty and if so, creates a new one. It then uses deal() to pull the next card in the deck and return it.