Search code examples
javaandroidrandomshuffleplaying-cards

How to really shuffle a deck of cards


When I need to shuffle a deck of poker cards in Java/Android, I use Collections.shuffle(List<?> list), of course. I've ever been doing this and the results seemed acceptable. But they aren't.

As outlined in this paper, there are 52! possible unique shuffles of a 52 card poker deck. That amounts to about 2^226.

But Collections.shuffle(List<?> list) uses new Random() by default which uses a 48-bit seed and can therefore only create 2^48 unique shuffles - which is only 3.49*10^(-52) percent of all possible shuffles!

So how do I shuffle cards the right way?

I've started using SecureRandom, but is that enough, finally?

List<Card> cards = new ArrayList<Card>();
...
SecureRandom secureRandom;
try {
    secureRandom = SecureRandom.getInstance("SHA1PRNG");
}
catch (NoSuchAlgorithmException e) {
    secureRandom = new SecureRandom();
}
secureRandom.nextBytes(new byte[20]); // force SecureRandom to seed itself
Collections.shuffle(cards, secureRandom);

Solution

  • You may only be able to get 248 different hands from a specific starting arrangement but there's no requirement that you start at the same arrangement each time.

    Presumably, after the deck is finished (poker hands, blackjack and so on), it will be in an indeterminate order, and any one of those rearrangements will be suitable.

    And, if you're worried about the fact that you start from a fixed arrangement each time you start your program, just persist the order when exiting and reload it next time.

    In any case, 248 is still a huge number of possibilities (some 280,000,000,000,000), more than adequate for a card game, more so when you come to a realisation that it's limiting shuffles rather than arrangements. Unless you're a serious statistician or cryptographer, what you have should be fine.