///GH Shuffle
#include "std_lib_facilities.h"

class Card {
public:
    enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES };
    enum Rank { ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN,
                EIGHT, NINE, TEN, JACK, QUEEN, KING };
    Rank r; ///The rank of a card is typically A,2,3,...,10,J,Q,K
    Suit s;  ///The suit is typically clubs, diamonds, hearts, spades
    Card(Rank ranks, Suit suits) : r(ranks), s(suits) {}
    void showCard() {
        cout << '(' << r << " of " << s << ')';
    }
};

class Deck {
public:
    unsigned number=52;
    vector<Card> deck;
    Deck(unsigned n):number(n) {
        for(unsigned i = 0; i < number; ++i)
            deck.push_back(Card(i%13,i/13));
    }
    void shuffle();
    void show() {
        for(unsigned i = 0; i < number; i++) {
            deck[i].showCard();
            cout  << '\t';
            if((i+1)%4==0) cout << endl;
        }
    }
};
/** Fisher-Yates Shuffle
To shuffle an array a of n elements (indices 0..n-1):
  for i from n − 1 downto 1 do
       j ← random integer with 0 ≤ j ≤ i
       exchange a[j] and a[i]
**/
void Deck::shuffle() {
    unsigned next;
    for(unsigned i = number-1; i>1; i--) {
        next = rand()%i;
        Card temp = deck[i];
        deck[i] = deck[next];
        deck[next] = temp;
    }

}

int main() {
    srand(unsigned(time(0)));
    Deck d1(52);
    d1.show();
    cout << endl;
    d1.shuffle();
    d1.show();
}
