Que Logo

Chapter 18

Script Example 4: Blackjack



In This Chapter

Game Time


In our final example, you take a break from the monotony of loans and other boring subjects. It's time to play a few hands of cards and prove that JavaScript is an effective environment for game creation. To this end, you'll cook up a little script that plays a simple game of blackjack.
First, define the ground rules for the game:
Okay, so we cut a few corners with the rules. If you want to extend the game to handle such things as splits, doubles, betting, and Aces that are 1 or 11, please feel free.

Pick a Card


In Chapter 16, you saw how to create a function to generate a random number between 1 and some maximum value using the JavaScript Date object to get the current time (hours, minutes, and seconds). Since time is constantly changing, this provides a very basic, pseudo-random (almost random) generator. For review, here's the random() function:

function random(maxValue)
{
 day = new Date();
 hour = day.getHours();
 min = day.getMinutes();
 sec = day.getSeconds();
 return (((hour + 1) * (min + 1) * sec) % maxValue) + 1;
}

This works quite nicely for your purposes, because you need to randomly pick two things for each card "drawn" from the deck:
Since there are four suits, you can write a function to pick a suit by randomly generating a number between 1 and 4:

function pickSuit()
{
 suit = random(4);

 if(suit == 1)
 return "Spades";

 if(suit == 2)
 return "Clubs";

 if(suit == 3)
 return "Diamonds";

 return "Hearts";
}

You really need to check suit only to see if it's 1, 2, or 3. If it isn't one of those, it must be 4 and you don't have to use an if statement to make sure. This is an "old programmer's trick" that saves a few keystrokes and a couple of steps when the program is running (if you want to drop a buzzword at your next party, this is called program optimization).
The next step is to pick the card from the suit. There are 13 cards in each suit: Ace, 2 through 10, Jack, Queen, and King. You need your card picker to return two things: the value of the card (a number from 2 to 11_remember, Aces are 11) and the name of the card (either the card number or the word "Jack," for instance). This causes a bit of a dilemma: "Jack", "Queen", "King", and "Ace" are all strings, but "2", "3", "5", and so on are numbers. You need both.
Since you need two distinct things from your card picker, make two distinct functions: one to return the value, and one to return the name. The value function simply takes the number of your card (a number from 1 to 13) and returns a value from 2 to 11:

function cardValue(card)
{
 if(card == 1)
 return 11;

 if(card > 10)
 return 10;

 return card;
}

If the card is 1 (an Ace), you say it's worth 11. If the card is a face card, its number will be 11, 12, or 13, so you say it's worth 10. Otherwise, it's worth the number that's passed in.
Figuring out the card name is similar:

function cardName(card)
{
 if(card == 1)
 return "Ace";

 if(card == 11)
 return "Jack";

 if(card == 12)
 return "Queen";

 if(card == 13)
 return "King";

 return "" + card;
}

Since each face card has a different name, you can't just say, "If it's greater than 10…," so you need a separate if statement for each face card. Finally, the number (spot) cards are simply returned, but you convert the value to a string (using the "" + trick).
Now, you can construct your PickACard() function:

function PickACard(strWho)
{
 card = random(13);
 suit = pickSuit();

 alert(strWho + " picked the " + cardName(card) + " of " + suit);

 return cardValue(card);
}

Return the card's value from PickACard() so you can use this function to add to the totals in the dealer's and user's hands. Also, the parameter strWho gives you the flexibility to call PickACard("You") or PickACard("Dealer") and have the alert() dialog say "Dealer picked…" or "You picked…" without having to write two separate functions (remember Rule #3 of JavaScript programming: Never do more typing than you have to).
You can test your card picker with the following short page:

<HTML>
<TITLE>Pick a Card</TITLE>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
<!- Hide from non-JavaScript browsers
function random(maxValue)
{
 day = new Date();
 hour = day.getHours();
 min = day.getMinutes();
 sec = day.getSeconds();
 return (((hour + 1) * (min + 1) * sec) % maxValue) + 1;
}

function pickSuit()
{
 suit = random(4);

 if(suit == 1)
 return "Spades";

 if(suit == 2)
 return "Clubs";

 if(suit == 3)
 return "Diamonds";

 return "Hearts";
}

function cardName(card)
{
 if(card == 1)
 return "Ace";

 if(card == 11)
 return "Jack";

 if(card == 12)
 return "Queen";

 if(card == 13)
 return "King";

 return "" + card;
}

function cardValue(card)
{
 if(card == 1)
 return 11;

 if(card > 10)
 return 10;

 return card;
}

function PickACard(strWho)
{
 card = random(13);
 suit = pickSuit();

 alert(strWho + " picked the " + cardName(card) + " of " + suit);

 return cardValue(card);
}
//->
</SCRIPT>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE=BUTTON VALUE="Pick A Card" onClick=PickACard("You")>
</FORM>
</BODY>
</HTML>

Clicking the Pick A Card button will generate a JavaScript alert box something like this.

Testing the card picker.


Clicking repeatedly will pop up different card selections-so your card picker works! Start putting together the game logic, beginning with the dealer (which is a little more involved than the user).

Dealer Takes a Card


The user takes a card only when he clicks the Hit me button, but the dealer must repeatedly take cards (after the user clicks Stand) until the house's hand goes over 16. This means you have to set up a function that repeats the pickacard() process until 17 is reached or exceeded. If you think this sounds like a job for a while loop, you're right.
Recall the basic form of the while loop: "While {something} is 'true', keep doing something else." In this case, you want to keep picking cards while the total in the dealer's hand is less than 17:

function Dealer()
{
 while(dealerHand < 17)
 {
 dealerHand = dealerHand + PickACard("Dealer");
 }
}

Simple, isn't it? The function for when the user picks a card is even easier:

function User()
{
 userHand = userHand + PickACard("You");
}

And, once everybody has taken all the cards they want, figuring out who won is a snap:

function LookAtHands()
{
 if(dealerHand > 21)
 {
 alert("House busts! You win!");
 }
 else
 if(userHand > dealerHand)
 {
 alert("You win!");
 }
 else
 if(userHand == dealerHand)
 {
 alert("Push!");
 }
 else
 {
 alert("House wins!");
 }
}

But what are userHand and dealerHand? They could be variables, but they really are placeholders for the form fields that you need to display this information to the user on the "game board." It's time to "spread the felt" and set up the gaming table.

Deal Me In


The game page needs two fields (for the house's and user's totals), and three buttons: Hit, Stand, and New Hand. Each button will have its own onClick event handler to process taking a card (for a hit) or having the dealer take cards (if the user chooses to stand). From the functions you've compiled so far, you can see that…
Since you'll be dealing with an HTML <FORM>, you'll make the dealer's total field dealer, and the user's you. This means you have to replace userHand with form.you.value and dealerHand with form.dealer.value. The correct value for form can be passed into
the various functions from inside the HTML form by using the this.form qualifier.
For example:

<INPUT TYPE=BUTTON VALUE="Hit me!" onClick=User(this.form)>

This would pass the form into the User() function, so that you can update the user's total hand:

function User(form)
{
 form.you.value = eval(form.you.value) + PickACard("You");

 if(form.you.value > 21)
 {
 alert("You busted!");
 }
}


JavaScript Is Very Fond of Strings

In fact, JavaScript will convert any form fields that are nothing but numbers into their string equivalents. This means that, if you want to change the value of a number in a field, you should first use the eval() function to make sure that the field value is treated as a number, not a string.
For example, if you had a form field called number and it was holding the value 23, adding 5 to it by:

         form.number.value = form.number.value + 5;
         

would result in number having the value "235", as though you were tacking strings together. Use eval() to keep this from happening:

         form.number.value = eval(form.number.value) + 5;
         

and the result will be "28".
By replacing userHand with form.you.value, you are writing the total of the user's hand back to the form for display. Accessing the dealer's hand information is done the same way.
Using the eval() function guarantees that the information in form.you.value is treated as a number, not a string (JavaScript has a tendency to look at things as strings, whether they are strings or not).
With that said, here's the complete script:

<HTML>
<TITLE>BlackJack</TITLE>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
<!- Hide from non-JavaScript browsers
function random(maxValue)
{
 day = new Date();
 hour = day.getHours();
 min = day.getMinutes();
 sec = day.getSeconds();
 return (((hour + 1) * (min + 1) * sec) % maxValue) + 1;
}

function pickSuit()
{
 suit = random(4);

 if(suit == 1)
 return "Spades";

 if(suit == 2)
 return "Clubs";

 if(suit == 3)
 return "Diamonds";

 return "Hearts";
}

function cardName(card)
{
 if(card == 1)
 return "Ace";

 if(card == 11)
 return "Jack";

 if(card == 12)
 return "Queen";

 if(card == 13)
 return "King";

 return "" + card;
}

function cardValue(card)
{
 if(card == 1)
 return 11;

 if(card > 10)
 return 10;

 return card;
}

function PickACard(strWho)
{
 card = random(13);
 suit = pickSuit();

 alert(strWho + " picked the " + cardName(card) + " of " + suit);

 return cardValue(card);
}

function NewHand(form)
{
 form.dealer.value = 0;
 form.you.value = 0;

 form.dealer.value = eval(form.dealer.value) + PickACard("Dealer");
 form.you.value = eval(form.you.value) + PickACard("You");
}

function Dealer(form)
{
 while(form.dealer.value < 17)
 {
 form.dealer.value = eval(form.dealer.value) + PickACard("Dealer");
 }
}

function User(form)
{
 form.you.value = eval(form.you.value) + PickACard("You");

 if(form.you.value > 21)
 {
 alert("You busted!");
 }
}

function LookAtHands(form)
{
 if(form.dealer.value > 21)
 {
 alert("House busts! You win!");
 }
 else if(form.you.value > form.dealer.value)
 {
 alert("You win!");
 }
 else
 if(form.dealer.value == form.you.value)
 {
 alert("Push!");
 }
 else
 {
 alert("House wins!");
 }
}
//->
</SCRIPT>
</HEAD>
<BODY>
<CENTER><H2>BlackJack</H2></CENTER>
<CENTER>To start a hand, click 'New Hand'.</CENTER>
<CENTER>(Dealer stands on 17)</CENTER>
<HR>

<CENTER>
<FORM>
<TABLE BORDER=3>
<TR>
 <TD>Dealer has</TD>
 <TD><INPUT TYPE=TEXT NAME=dealer></TD>
</TR>
<TR>
 <TD>You have</TD>
 <TD><INPUT TYPE=TEXT NAME=you></TD>
</TR>
</TABLE>

<P>

<CENTER>
<INPUT TYPE=BUTTON VALUE="Hit me!" onClick=User(this.form)>
<INPUT TYPE=BUTTON VALUE="Stand" _onClick="Dealer(this.form);LookAtHands(this.form);">
<INPUT TYPE=BUTTON VALUE="New Hand" onClick=NewHand(this.form)>
</CENTER>

</FORM>
</CENTER>

</BODY>
</HTML>

From inside the browser, your blackjack game looks like this.

Gambling with JavaScript (it's cheaper than Vegas).

The Least You Need To Know


In this example, you looked at creating a game with JavaScript. Using the tools you've collected from previous chapters, you built a simple blackjack player. You also saw how using the while statement makes it possible to continue working inside a function until some condition is met. To make sure that the totals you were building in the form were correct, eval() makes sure that field values are treated as numbers rather than strings.

Previous Chapter

Next Chapter


Beginning of ChapterTable of ContentsBook Home PageQue Home Page


For comments or technical support for our books and software, select Talk to Us.
To order books, call us at 800-716-0044 or 317-228-4366.

© 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon & Schuster Company.