1

I have an Array List of cards containing 52 cards. I want to shuffle the deck.

This is what I have done.

  1. Created a new Array List.
  2. Generated random index between 0 to deck size.
  3. Get card at random index and add to new list.
  4. Remove card from deck
  5. Repeat until deck is empty.

Here is my code:

String[] Number = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[] Suits = {"Club","Diamonds","Hearts","Spades"};
ArrayList<Card> deck = new ArrayList<Card>();

// create a deck    

for(int i=0;i<13;i++){
        for(int j=0;j<4;j++){
            Card card = new Card(Suits[j],Number[i]);
            deck.add(card);
        }    
    }

// shuffle of deck

ArrayList<Card> new_deck = new ArrayList<Card>();
    while(deck.size()!=0){   

        Random rand = new Random();
        int  n = rand.nextInt(deck.size());

        new_deck.add(deck.get(n));
        deck.remove(n);
    }

// Display

for(int i=0;i<52;i++){
        System.out.println(new_deck.get(i).getSuit()+" : "+new_deck.get(i).getValue());
    }

Finally, I get the shuffled deck from new ArrayList.

Is its randomness good enough or not?

What should I do to increase randomness?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Sagar Gautam
  • 9,049
  • 6
  • 53
  • 84
  • Is there any particular requirement about Randomness? Why do you feel that randomness is enough or not enough? – Manish Kumar Sharma Apr 29 '17 at 05:05
  • There is no such requirement but I have used custom method for shuffle this is main reason. hopefully you understand – Sagar Gautam Apr 29 '17 at 05:06
  • You haven't effectively used custom method as underlying, it is java.util.Random. You should consider reading, https://docs.oracle.com/javase/7/docs/api/java/util/Random.html and https://blog.tradeshift.com/sources-of-randomness-in-java/ – Manish Kumar Sharma Apr 29 '17 at 05:09
  • size of deck changing every loop so I think this is custom – Sagar Gautam Apr 29 '17 at 05:15
  • Possible duplicate of [How good is java.util.Random?](http://stackoverflow.com/questions/453479/how-good-is-java-util-random) – Peter O. Apr 29 '17 at 11:47
  • I have used custom method after generating random number between 0 to n. That's the reason I have asked for some suggestion – Sagar Gautam Apr 29 '17 at 12:02

4 Answers4

4

Does it's randomness is enough or not ?

Define good enough (!!)

Your current approach is going to give a good shuffle, with no obvious biases ... except for biases that may be introduced by the random number generator.

And in this case, there is real cause for concern. Random is specified to be a linear congruential generator, and LC generations have distinct patterns in the numbers that they generate. (In statistical terms, they show strong auto-correlation.) This is quite clear if you graph the n'th random number against n.

To improve randomness, you should use a better random number generator. The SecureRandom generator should be good enough: javadoc.


The same concern about the randomness applies if you use Collections.shuffle method. For a good (or consistent) shuffle you should use the method overload where you supply a Random implementation ... and choose a good one.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
3

I suggest you can simply use Collections.shuffle() as shown below rather than reinventing the shuffling logic which is already provided by Collections API:

Collections.shuffle(deck);//Pass your ArrayList<Card> object i.e., deck

So, by reusing this existing Collections API clears all your doubts on the randomness of your deck object.

Vasu
  • 21,832
  • 11
  • 51
  • 67
  • This takes away the burden of the randomness and delegates it to the API, is pretty fun to look at the implementation of it http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collections.java#455 and the comment "All permutations occur with equal likelihood assuming that the source of randomness is fair. " – cabolanoz Apr 29 '17 at 05:26
1

You should define your notion of "randomness" in a precise way. "Increasing randomness" is a rather vague term.

I will assume by "random", what you want is a uniform distribution of permutation on your deck. Which is to say, you want your deck to be reordered in such a way that the chance that the next card is a particular card is equal.

There are two different factors at play here:

  • How you shuffle
  • How good a random generator Random is

How you shuffle

As far as how you shuffle goes, it is uniform. It can be proven by conditional probability that any card being in any position is exactly 1/52.

How good util.Random is

First, to be clear, util.Random is not actually random. It is a pseudorandom number generator(PRNG). That means what they do is not to produce truly random numbers. Instead they try to, and depending on application requirements, it will be enough.

util.Random is a linear congruential generator, and as far as PRNGs go, its pretty weak. If you don't care about really randomizing your deck, it will work fine. However if you need something more robust, here is a starting point.

Community
  • 1
  • 1
Passer By
  • 19,325
  • 6
  • 49
  • 96
0

There is one issue not mentioned here about java.util.Random: whether it can choose all permutations of a 52-item list. This is based on the number of seeds it admits. In general, a pseudorandom number generator (PRNG) can't choose more permutations of random number sequences than the number of seeds it admits (see "Shuffling" in my article on randomness for further discussion). Nothing is said here about PRNGs that admit as many or more seeds than the number of permutations or whether the permutations the PRNG can choose have an equal probability of occurring, as opposed to an ideal process of generating perfectly independent uniform random integers.

java.util.Random admits no more than 248 seeds, since it uses a 48-bit seed length. However, there are 52-factorial permutations of a 52-item list, and that's higher than 2225 -- which exceeds this maximum number of seeds by many orders of magnitude. Because of this, there are many, many permutations of a 52-item list that java.util.Random can't generate (using the same shuffling technique). (And this applies to any PRNG that admits fewer than 52-factorial seeds, not just linear congruential generators, like java.util.Random, in particular.) Therefore, an application that needs to shuffle a 52-item list would be well advised to avoid PRNGs that admit fewer than 52-factorial seeds (although even if a PRNG admits as many or more than 52-factorial seeds, that is not enough, by itself, to ensure the PRNG can choose from among all permutations with equal probability).


EDIT: Two recent questions discussed how to generate enough randomness to shuffle a digital "deck" of 52 cards:

Is java.util.Random really that random? How can I generate 52! (factorial) possible sequences?

Where can I get a reliable source of entropy (real randomness byte[])?

See the linked questions for details, and see also my section on nondeterministic sources and seed generation.

EDIT (Aug. 31, 2023): Edited.

Peter O.
  • 32,158
  • 14
  • 82
  • 96