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


go =>
  % Create and print the deck
  deck(Deck),
  print_deck(Deck),
  nl,
 
  % Shuffle the deck
  print_deck(shuffle(Deck)),
  nl,
 
  % Deal 3 cards
  Deck := deal(Deck,Card1),
  Deck := deal(Deck,Card2),
  Deck := deal(Deck,Card3),
 
  println(deal1=Card1),
  println(deal2=Card2),
  println(deal3=Card3),
  % The remaining deck
  print_deck(Deck),
  nl,
 
  % Deal 5 cards
  Deck := deal(Deck,Card4),
  Deck := deal(Deck,Card5),
  Deck := deal(Deck,Card6),
  Deck := deal(Deck,Card7),
  Deck := deal(Deck,Card8),
 
  println(cards4_to_8=[Card4,Card5,Card6,Card7,Card8]),
  nl,
 
  % Deal 5 cards
  Deck := deal_n(Deck,5,FiveCards),
  println(fiveCards=FiveCards),
  print_deck(Deck),
  nl,
 
  % And deal some more cards
  % This chaining works since deal/1 returns the remaining deck
  Deck := Deck.deal(Card9).deal(Card10).deal(Card11).deal(Card12),
  println("4_more_cards"=[Card9,Card10,Card11,Card12]),
  print_deck(Deck),
 
  nl.
 
% suits(Suits) => Suits = ["♠","♥","♦","♣"].
suits(Suits) => Suits = ["C","H","S","D"].
values(Values) => Values = ["A","2","3","4","5","6","7","8","9","T","J","Q","K"].
 
% Create a (sorted) deck.
deck(Deck) => 
  suits(Suits), 
  values(Values),
  Deck =[S++V :V in Values, S in Suits].sort().
 
% Shuffle a deck
shuffle(Deck) = Deck2 => 
  Deck2 = Deck,
  Len = Deck2.length,
  foreach(I in 1..Len) 
    R2 = random(1,Len),
    Deck2 := swap(Deck2,I,R2)
  end.
 
% Swap position I <=> J in list L
swap(L,I,J) = L2, list(L) =>
  L2 = L,
  T = L2[I],
  L2[I] := L2[J],
  L2[J] := T.
 
 
% The first card is returned as the out parameter Card.
% The deck is returned as the function value.
deal(Deck, Card) = Deck.tail() => Card = Deck.first().
 
% Deal N cards
deal_n(Deck, N, Cards) = [Deck[I] : I in Len+1..Deck.length]  =>
   Len = min(N,Deck.length),
   Cards = [Deck[I] : I in 1..Len].
 
% Print deck 
print_deck(Deck) =>
  println("Deck:"),
  foreach({Card,I} in zip(Deck,1..Deck.len))
     printf("%w ", Card),
     if I mod 10 == 0 then
       nl
     end
  end,
  nl.