Java: Shuffle a Deck of 32 cards?

408 Views Asked by At

I've wrote this method on my own I want to know if there is a better way to do it?

public Card[] shuffle(){
    for(int i = 0; i < Deck.length; i++){
       int x = i + (int) (Math.random() * (32 - i));
       Card temp = Deck[i];
       Deck[i] = Deck[x];
       Deck[x] = temp;
    }
    return Deck;
}
3

There are 3 best solutions below

4
On

I guess you can get a better result if you choose the item to be exchanged from the whole deck and not only from the remaining cards, like this:

public Card[] Shuffle(){
    for(int i = 0; i < Deck.length; i++){
       int x = (int) (Math.random() * 32);
       Card temp = Deck[i];
       Deck[i] = Deck[x];
       Deck[x] = temp;
    }
    return Deck;
}
4
On

You not checking, if ( 32 - i ) ever gives any value less than 0. The algorithm is called Fisher-Yates shuffling algorithm, which resemble very much like yours:

private int [] shuffleMyArray ( int [] array ) {
    int size = array.length, i = 0;
    int temp = 0;
    while ( size != 0 ) {
        i = ( ( int ) ( Math.random () * size-- ) );
        if ( i < 0 ) {
            i = 0;
        }
        temp = array [ size ];
        array [ size ] = array [ i ];
        array [ i ] = temp;
    }
    return array;
}

EDIT 1:

The output of both the algorithms will better make you understand the difference between the two, see how Fisher-Yates take all indices into account, while shuffling.

OUTPUT:

Actual Array
0 1 2 3 4 
Your Implementation output
i: 0 x: 3
i: 1 x: 4
i: 2 x: 3
i: 3 x: 4
i: 4 x: 4
Fisher Yates implementation output
i: 4 size: 4
i: 2 size: 3
i: 1 size: 2
i: 0 size: 1
i: 0 size: 0
0
On

I'm going to make the deck an argument, and the method static. That way it's self contained. In Java, naming conventions are to make variables and method names start with a lower case letter. Next, the shortest way I know is to shuffle the deck in place with Collections.shuffle(List) and Arrays.asList(T...) like

public static void shuffle(Card[] deck) {
    Collections.shuffle(Arrays.asList(deck));
}

If you want to preserve the original deck, then you could copy it and return like

public static Card[] shuffle(Card[] deck) {
    List<Card> al = new ArrayList<>(Arrays.asList(deck));
    Collections.shuffle(al);
    return al.toArray(new Card[deck.length]);
}