How to really shuffle a deck of cards

2022-09-04 22:47:48

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

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

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

So how do I shuffle cards the right way?

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

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);

答案 1

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.


答案 2

Although you are using a , is still has a limited state. As long as that input seed has a smaller range than 52! it can not be completely random.SecureRandom

In fact, SHA1PRNG is 160 bit seeded, which means it is still not random enough. Follow this link, it has a solution years ago by using a third party library called .UnCommons Math


推荐