Blackjack game – Part 1.

The following tutorial is only some kind of “thought provoking” one: shows you some logic and class structure using enums and dynamically created images with Winform application.

Maybe I skipped some of the official rules. If so, I’m sorry I’m not a big gambler. This tutorial is not for teaching you Blackjack, but showing you some C# practices.

Here are some of the rules I have implemented:

  • we have a shuffled deck of 52 cards
  • the player starting hand has 2 cards
  • the computer hand has also 2 cards: one of them is visible the other one is not
  • the Jack, Queen and King has the value of 10
  • the Ace has the value of 11 or 1 if 11 would be too much in hand
  • the player starts to draw (official phrase is HIT)
  • the main goal is to stop at 21 (or close to 21)
  • the player can skip the drawing phase (STAY) if the total score is 16 at least
  • if player stays, the computer turn comes
  • first we can see the computer’s second (hidden) card
  • the computer starts to draw using the same rules as ours mentioned before

To show you how to use System.Drawing.Graphics class, I create the images of the cards by cutting 1 big image into pieces. Click on the following image to download it:

I have 3 main classes: Card, Deck and Hand. Of course the form has its own Form1 class.

I also have 2 enums: CardValue and CardSuit. Both enum indexing starts from 1. The CardValue contains the type of the cards (Ace, King, 9, 7, 2, etc.). The CardSuit contains the colors (hearts, spades, etc.).

Create a new class: Card.cs

Under the class place the 2 enums:

public enum CardValue
    {
        Ace = 1,
        Two = 2,
        Three = 3,
        Four = 4,
        Five = 5,
        Six = 6,
        Seven = 7,
        Eight = 8,
        Nine = 9,
        Ten = 10,
        Jack = 11,
        Queen = 12,
        King = 13
    }

    public enum CardSuit
    {
        Hearts = 1,
        Spades = 2,
        Clubs = 3,
        Diamonds = 4
    }

The Card class will have 3 properties, 1 constructor, 1 new method and 1 overridden method. What properties does a card have? Of course its value, its color and its picture. So create the private properties with their public encapsulated fields. The Image property won’t have setter, the value and color setter will have the image loader method:

Image image;
CardValue cardValue;
CardSuit suit;

public Image Image
{
    get
    {
        return this.image;
    }
}

public CardValue Value
{
    get
    {
        return this.cardValue;
    }
    set
    {
        this.cardValue = value;
        GetImage();
    }
}

public CardSuit Suit
{
    get
    {
        return this.suit;
    }
    set
    {
        this.suit = value;
        GetImage();
    }
}

With the constructor let’s create a dummy card with no color and value:

public Card()
{
    cardValue = 0;
    suit = 0;
    image = null;
}

The attached image has the following properties: it’s 392 pixel high and 950 wide. So 1 card is about 97 high and 73 wide. The method has to slice the image depending on the following color from the deck (one color in each row on the image) and depending on the value (the image has the values in ascending order).

        private void GetImage()
        {
            if (this.Suit != 0 && this.Value != 0)//so it must be a valid card (see the Enums)
            {
                int x = 0;//starting point from the left
                int y = 0;//starting point from the top. Can be 0, 98, 196 and 294
                int height = 97;
                int width = 73;

                switch (this.Suit)
                {
                    case CardSuit.Hearts:
                        y = 196;
                        break;
                    case CardSuit.Spades:
                        y = 98;
                        break;
                    case CardSuit.Clubs:
                        y = 0;
                        break;
                    case CardSuit.Diamonds:
                        y = 294;
                        break;
                }

                x = width * ((int)this.Value - 1);//the Ace has the value of 1 (see the Enum), so the X coordinate will be the starting (first one), that's why we have to subtract 1. The card 6 has the total width of the first 6 cards (6*73=438) minus the total width of the first 5 cards (5*73=365). Of course it is 73. The starting X coordinate is at the end of the 5th card (or the start of the left side of the 6th card). Hope you understand. :)

                Bitmap source = Resources.cards;//the original cards.png image
                Bitmap img = new Bitmap(width, height);//this will be the created one for each card
                Graphics g = Graphics.FromImage(img);
                g.DrawImage(source, new Rectangle(0, 0, width, height), new Rectangle(x, y, width, height), GraphicsUnit.Pixel);//here we slice the original into pieces
                g.Dispose();
                this.image = img;
            }
        }

And the overridden ToString method, just for fun (not used later in the code):

        public override string ToString()
        {
            string realValue = "";
            switch (cardValue)
            {
                case CardValue.Two:
                case CardValue.Three:
                case CardValue.Four:
                case CardValue.Five:
                case CardValue.Six:
                case CardValue.Seven:
                case CardValue.Eight:
                case CardValue.Nine:
                case CardValue.Ten:
                    realValue = ((int)cardValue).ToString();
                    break;
                case CardValue.Jack:
                case CardValue.Queen:
                case CardValue.King:
                case CardValue.Ace:
                    realValue = cardValue.ToString();
                    break;
            }
            return realValue + " of " + suit.ToString();
        }
    }

In the next chapter I’ll show you how to create the class for the Hand and the Deck.