Task

Create a data structure and the associated methods to define and manipulate a deck of   playing cards.

The deck should contain 52 unique cards.

The methods must include the ability to:

   make a new deck
   shuffle (randomize) the deck
   deal from the deck
   print the current contents of a deck 
Each card must have a pip value and a suit value which constitute the unique value of the card.

Related tasks:

 Card shuffles
 Deal cards_for_FreeCell
 War Card_Game
 Poker hand_analyser
 Go Fish


import std.stdio, std.typecons, std.algorithm, std.traits, std.array,
       std.range, std.random;
 
enum Pip {Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten,
          Jack, Queen, King, Ace}
enum Suit {Diamonds, Spades, Hearts, Clubs}
alias Card = Tuple!(Pip, Suit);
 
auto newDeck() pure nothrow @safe {
    return cartesianProduct([EnumMembers!Pip], [EnumMembers!Suit]);
}
 
alias shuffleDeck = randomShuffle;
 
Card dealCard(ref Card[] deck) pure nothrow @safe @nogc {
    immutable card = deck.back;
    deck.popBack;
    return card;
}
 
void show(in Card[] deck) @safe {
    writefln("Deck:\n%(%s\n%)\n", deck);
}
 
void main() /*@safe*/ {
    auto d = newDeck.array;
    d.show;
    d.shuffleDeck;
    while (!d.empty)
        d.dealCard.writeln;
}