-2

I am tasked with Creating a functional deck of cards and I need a bit of guidance. I am making my method to fill the deck(an array) with card objects. I have the logic that will tell the loops when to change suits or ranks and I have made it to where the method will only fill the deck if the deck isn't already at 52 cards. What I need is a bit of guidance on where to proceed forward. I don't want answers, I want to learn why or why not what I have so far is incorrect and where I should proceed. I will put my code so far below.

public static void FillDeckWithPlayingCards(Deck DeckToFill)
    {

        
        if (DeckToFill.DeckOfCards.Length != 52)
        {
            Deck deck = new Deck();
            PlayingCard [] FilledDeck =new PlayingCard [52];

            for (int i = 0; i < DeckToFill.DeckOfCards.Length; i++)
            {
                FilledDeck[i] = DeckToFill.DeckOfCards[i];
            }

            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 13; j++)
                {
                    
                }

            }

                    


    }
jazb
  • 5,498
  • 6
  • 37
  • 44
  • 1) Find the cards that are missing from the deck. 2) Either a) construct a list of the missing cards, shuffle them, and add them to the existing deck, or b) add the missing cards to the existing deck without shuffling. – ProgrammingLlama Feb 14 '22 at 03:14
  • What are the properties of `PlayingCard` and what is the constructor like? More details are needed to effectively answer this question. Please specify _how_ each suit and value is stored for each card and with what order you want the cards filled. Most likely, give an example of how to define the queen of hearts for example. – John Alexiou Feb 14 '22 at 04:28
  • 1
    There are hundreds and hundreds of posts here related to cards, decks of cards, card games and shuffling decks of cards. It would behoove you greatly to do a little basic research – Ňɏssa Pøngjǣrdenlarp Feb 14 '22 at 04:30
  • If you want to ask a better question, then you need to define what the rules apply to "fill the deck". – Jeremy Lakeman Feb 14 '22 at 05:34

1 Answers1

1

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);
    }
}
John Alexiou
  • 28,472
  • 11
  • 77
  • 133
  • I would always display the 10 as T, it lines up better. This is the standard way that poker hands are shown in forums, etc – pm100 Feb 14 '22 at 05:21
  • @pm100 - ty, did not know that. I was considering showing a `0` or a `*`. Of course this being demo code it has a lot of holes. – John Alexiou Feb 14 '22 at 05:23
  • `Array.Sort(...NextDouble...)` doesn't look like a good randomiser (https://stackoverflow.com/questions/1287567/is-using-random-and-orderby-a-good-shuffle-algorithm) – Jeremy Lakeman Feb 14 '22 at 05:37
  • @JeremyLakeman - it is not that different from the accepted answer here (https://stackoverflow.com/a/108836/380384) and I am not replacing the array (it is readonly field), I am just re-arranging the items, which is what `Array.Sort()` is for, – John Alexiou Feb 14 '22 at 13:16
  • @JeremyLakeman - Internally `Random.Next()` calls `Random.NextDouble()` in a way and the `.OrdetBy()` operation calls a comparator just like I have provided. My solution is practically the same as the canon for sorting arrays. – John Alexiou Feb 14 '22 at 13:23
  • One pass of shuffling is only `O(n)`, sorting is at minimum `O(n log n)`, plus you're assuming that the sort routine will terminate when the comparisons aren't stable. – Jeremy Lakeman Feb 15 '22 at 00:19
  • @JeremyLakeman - interesting discussion, but not related to this question at all. Internally it calls the `ArraySortHelper.DepthLimitedQuickSort()` routine which does a finite number of comparisons, and is not subject to an infinite loop situation. – John Alexiou Feb 15 '22 at 01:57