Blackjack: A Real World OOD Example

Download Blackjack.zip
When programmers start creating object oriented designs, several questions pop up consistently:
- How do I know what objects to create?
- What properties should my objects have?
- What methods do I need to create?
- How do I know when to overload an operator?
- How do I structure my classes for inheritance?
- Etc.
The Objects
Let's take a look at a real world example anda fun one as well. The game Blackjack lends itself well to objectoriented design because it has physical objects that can be modeled inobject-oriented code, i.e. players, a dealer, cards, etc.
These objects have relationships to oneanother as well. Players have hands that have cards. The dealer alsohas a hand that has cards. And there's a shoe from which the cards aredealt into the hands.
public class Player
public class Dealer
public class Hand
public class Card
public class Shoe // A shoe is just manydecks of cards, usually 6 in Las Vegas
For our Blackjack game, we're going to havecomputer-controlled players as well as human ones. For that, we'll haveto have a strategy that the computer playersuse. So we can create another object, albeit not a physical one, calledStrategy that takes some input and gives advice on what move to make.The Strategy object is going to belong to the Player objects and eachplayer will need an array of Hand objects (players can split pairs sothey may have more than one hand).
public class Player {
private Strategy plyrStrategy;
private Hand[] hands;
A hand is just an array of Card objects:
public class Hand {
private Card[] cards;
A shoe is also just an array of Card objects:
public class Shoe {
private Card[] cards;
Now when we deal the cards, we just go aroundthe table taking cards from the shoe object and adding them to the handobjects for each of the players and the dealer.
for( int k=0; k<2; k++ )
{
foreach( Player player in players )
{
player.GetHands()[0].Add( shoe.Next() );
}
dealer.Hand.Add( shoe.Next() );
}
Inheriting Interfaces
When a player splits a pair of aces, each ace receives only one more card:
if( CurrentPlayer.CurrentHand[0].FaceValue == Card.CardType.Ace )
{
NextCard();
NextHand();
NextPlayer();
}
Nice code huh? Well that's because there is a lot of supporting codeunderneath this, particularly to implement the line:
if(CurrentPlayer.CurrentHand[0].FaceValue == Card.CardType.Ace )
How does the compiler know what CurrentHand[0]means? To use this kind of syntax,we must implement the IList interface. This is the sameinterface used by the ArrayList class and others that you might befamiliar with. This is easily done by changing our class declarationslightly:
public class Hand : IList
Now there's a little more work to do. When youinherit an interface, you must provide the implementation for all themethods of that interface. ForIList, we need to add:
IsFixedSize
IsReadOnly
Add
Clear
Contains
IndexOf
Insert
Remove
RemoveAt
But the most important method to implement is called Item and it looks like this:
Object IList.this[int index]
{
get { return cards[index]; }
set { cards[index] = (Card)value;}
}
This allows us to use array syntax like CurrentHand[0] which really means nothing until we tellthe compiler that this means the card at position 0 in the array of cards in the hand. Without implementing IList, we would probablyhave to write something like CurrentHand.GetCard(0)which isn't nearly as cool!
What methods do I create?
Notice that the players and the dealer areresponsible for drawing their own hands. This makes it convenient toadd code to the form's paint event like this:
dealer.DrawHand( drawingSurface, showDealerDownCard );
foreach( Player player in players )
{
player.DrawHands( drawingSurface );
}
The players and dealer then loop through each hand, asking the cards to draw themselves:
foreach( Hand hand in hands )
{
foreach( Card card in hand )
{
card.Draw( drawingSurface );
}
}
Sometimes it's easier to envision the code you would like to write and then model your objects to allow it.
Summary
Take a look at the code for this article. Thisis a full-featured Blackjack game with strategiesand graphics and even card counting. But don't let it intimidate you.It really just boils down to the few objects outlined above with a lotof fancy code added to make the game more appealing.
Going back to the design of the objects, youmight be wondering why the Dealer and the Player objects don't inheritfrom some common object. Well, you could do that. But I felt the dealerand the players didn't have enough in common to justify it. The dealercan only have one hand, has no bank, no bet, no strategy, no cardcounting. This will have to be a judgment call on your part and that's why theypay you the big bucks.
You might also wonder where the Deck objectis. Shouldn't the Shoe be composed of many Deck objects which arecomposed of many Card objects? That may be the case in the real world,but this is an example of where the real world and OOD might betterpart ways. A deck object would have just introduced an unneeded layerof complexity. The shoe is easier to implement as an array of cards,though it must be a multiple of the number of cards in a deck (52).
Have fun with this game. Take a look at the Readme.doc file for ideas on how you could improve this application.












No comments yet... Be the first to leave a reply!