Since you are learning C#
you might as well start thinking about data structures and encapsulation.
What is a PlayingCard
? It should contain two properties, one for the suit and one for the face value, and since there can only take a finite number of possible values, it is natural you declare two enum
structures to hold these values.
public enum SuitValue
{
Clubs,
Diamonds,
Hearts,
Spades
}
public enum FaceValue
{
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
}
and now we can define a PlayingCard
with two properties. Since there are only certain valid cards, I am making the constructor of PlayingCard
private, accepting those two values.
I am also adding a static method CreateStandardDeck()
for the creation of the standard 52 card deck, just like your FillDeckWithPlayingCards()
intended to do. All I needed to do is loop through all the values of suits and faces and added them to the array.
/// <summary>
/// Playing card object holds one suit value and one face value.
/// </summary>
public class PlayingCard
{
/// <summary>
/// Initializes a new playing card.
/// </summary>
PlayingCard(SuitValue suit, FaceValue value)
{
Suit=suit;
Value=value;
}
public SuitValue Suit { get; }
public FaceValue Value { get; }
/// <summary>
/// Creates a standard deck of cards as an array of PlayingCard.
/// </summary>
public static PlayingCard[] CreateStandardDeck()
{
SuitValue[] suits = Enum.GetValues(typeof(SuitValue)) as SuitValue[];
FaceValue[] values = Enum.GetValues(typeof(FaceValue)) as FaceValue[];
List<PlayingCard> cards = new List<PlayingCard>();
for (int j = 0; j < values.Length; j++)
{
for (int i = 0; i < suits.Length; i++)
{
cards.Add(new PlayingCard(suits[i], values[j]));
}
}
return cards.ToArray();
}
/// <summary>
/// Returns a string representation of the card. The format is
/// <code>[F S]</code> with F a code for face value, and S a code for suit value.
/// </summary>
public override string ToString()
{
string suit = Suit.ToString().Substring(0, 1);
string face = Value>FaceValue.Ace && Value<FaceValue.Ten ? ((int)Value).ToString() : Value.ToString().Substring(0, 1);
return $"[{face} {suit}]";
}
}
A Deck
should hold an array of PlayingCard
and also have methods for other functionality, such as shuffling.
/// <summary>
/// Deck objects holds an array of PlayingCard and has to ability
/// to shuffle the cards.
/// </summary>
public class Deck
{
/// <summary>
/// Initializes a new deck of cards and fills them with standard values.
/// </summary>
public Deck()
{
Cards = PlayingCard.CreateStandardDeck();
}
public PlayingCard[] Cards { get; }
static readonly Random rng = new Random();
public void Shuffle(int repeat = 1)
{
for (int i = 0; i < repeat; i++)
{
Array.Sort(Cards, (a, b) => rng.NextDouble()<0.5 ? -1 : 1);
}
}
public override string ToString()
{
const int wt = 12;
var sb = new StringBuilder();
int index = 0;
while (index<Cards.Length)
{
sb.Append($"{Cards[index],wt} ");
index++;
if (index%4 == 0)
{
sb.AppendLine();
}
}
return sb.ToString();
}
}
and finally, a little test program to see if it works as intended.
static class Program
{
static void Main(string[] args)
{
Deck deck = new Deck();
Console.WriteLine(deck);
}
}
with output
[A C] [A D] [A H] [A S]
[2 C] [2 D] [2 H] [2 S]
[3 C] [3 D] [3 H] [3 S]
[4 C] [4 D] [4 H] [4 S]
[5 C] [5 D] [5 H] [5 S]
[6 C] [6 D] [6 H] [6 S]
[7 C] [7 D] [7 H] [7 S]
[8 C] [8 D] [8 H] [8 S]
[9 C] [9 D] [9 H] [9 S]
[T C] [T D] [T H] [T S]
[J C] [J D] [J H] [J S]
[Q C] [Q D] [Q H] [Q S]
[K C] [K D] [K H] [K S]
Note that the Shuffle()
method works if you want to try it before writing to the console.
static class Program
{
static void Main(string[] args)
{
Deck deck = new Deck();
deck.Shuffle();
Console.WriteLine(deck);
}
}