Welcome back! The previous part has the class for the card, in this part we create the class for the deck. The deck contains the cards, 1 from each. Of course we have to shuffle the deck before every new game and we have to draw a card from the shuffled deck. Now we now what properties and methods should have this class:
- card list
- shuffle method
- draw method
The list property with private and public fields:
private List cards; public List Cards { get { return this.cards; } set { this.cards = value; } }
The constructor:
public Deck() { Cards = new List(); ShuffleNewDeck(); }
As you can see, every time you create a new deck it will be shuffled. So let’s see the shuffle method:
public void ShuffleNewDeck() { cards.Clear(); for (int i = 1; i < 5; i++)//CardSuits { for (int j = 1; j < 14; j++)//CardValues: 2...10,J,Q,K,A = 13 different values { Card card = new Card(); card.Value = (CardValue)j; card.Suit = (CardSuit)i; cards.Add(card); } } Random r = new Random(); cards = cards.OrderBy(x => r.Next()).ToList(); }
This method walks through on every card, add them to a list (deck). The OrderBy Linq will randomize (shuffle) the deck.
Of course, we have to be able to draw a card, so:
public Card DrawCard(Hand hand) { Card drawn = cards[cards.Count - 1]; cards.Remove(drawn); hand.Cards.Add(drawn); return drawn; }
///The hand where the drawn card goes to public Card DrawCard(Hand hand) { Card drawn = cards[cards.Count – 1]; cards.Remove(drawn); hand.Cards.Add(drawn); return drawn; }
Every time you draw a card, you draw it from the top of your deck (from the end of your list). It’s simple.
I have also created an ’empty’ exception class for the deck, called DeckException. You can also write this either in this Deck.cs file or in a new file:
[Serializable] internal class DeckException : Exception { public DeckException() { } public DeckException(string message) : base(message) { } public DeckException(string message, Exception innerException) : base(message, innerException) { } protected DeckException(SerializationInfo info, StreamingContext context) : base(info, context) { } }
This custom exception only shows you how to create the basics of your exception and nothing more. From now you can throw (then catch) your own exception.
Now we need a ‘hand’ that holds the drawn cards, so let’s create its class. It will have 1 property (the list of the cards), 1 constructor with our new custom exception and 1 method that counts our and computer’s total points.
using System.Collections.Generic; namespace BlackJack { public class Hand { private List cards; public List Cards { get { return cards; } } public Hand(int startingHand, Deck deck) { if (deck == null) throw new DeckException("No decks available to draw from!"); else if (deck.Cards.Count == 0) throw new DeckException("No more cards to draw!"); else { cards = new List(); for (int i = 0; i < startingHand; i++) { deck.DrawCard(this); } } } public void AddValue(Card drawn, ref int currentSum) { if (drawn.Value == CardValue.Ace) { if (currentSum <= 10) { currentSum += 11; } else { currentSum += 1; } } else if (drawn.Value == CardValue.Jack || drawn.Value == CardValue.Queen || drawn.Value == CardValue.King) { currentSum += 10; } else { currentSum += (int)drawn.Value; } } } }
As you can see, the constructor waits for a startinghand number that is the starting number of the cards in hand (in this case it is 2) and a Deck type parameter that is the deck that we are going to draw from.
The AddValue method has no return value (void) that’s why we use the currentSum input parameter as ref. We pass this parameter here as a reference, so any changes on this parameter here will be visible from outside of this class (for example on our main form). You’ll see later. The Ace could have 2 possible values: 1 or 11. If our score is not more than 10 it is 11. If our score is at least 11 the Ace is going to be only 1. All the figure cards have the value of 10.
In the final part we create the form and use our classes to be able to play.