2015-06-10 2 views
5

Я написал этот метод самостоятельно, я хочу знать, есть ли лучший способ сделать это?Java: Shuffle a Deck из 32 карт?

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; 
} 
+6

' Collections.shuffle (convertArrayToCollectionHere) ' –

+2

Не выглядит слишком плохо. Помимо очевидной альтернативы, о которой уже говорилось, я бы рекомендовал принять соглашения об именах Java и использовать имена нижних регистров для имен методов и переменных. –

+0

@jangroth спасибо за совет. –

ответ

-1

Я думаю, вы можете получить лучший результат, если вы выбираете пункт для обмена со всей палубы, а не только от остальных карт, например:

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; 
} 
+2

Удивительно, но выбор карты из полного диапазона на самом деле хуже. [Здесь] (http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Potential_sources_of_bias) - хорошее обсуждение ошибок реализации; использование полного диапазона является общей проблемой. – dasblinkenlight

+0

@dasblinkenlight Удивительно, но действительно. Спасибо что подметил это. –

+0

Это может привести к плохому перетасовке, что означает, что случайное число никогда не может выбрать определенные карты из колоды. –

2

Вы не проверяя, если (32 - i) когда-либо дает любое значение менее 0. Алгоритм называется Fisher-Yates перетасовки алгоритм, напоминающих очень похож на твой:

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:

Выход обоих алгоритмов будет лучше, чтобы вы поняли разницу между ними, посмотреть, как Fisher-Yates учитывать все индексы, перетасовывая.

ВЫВОД:

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 
+1

Здесь я нашел очень хороший сайт для изучения таких [алгоритмов] (http://bost.ocks.org/mike/algorithms/#shuffling) –

+1

Да, вы правы, я не проверял его. Можете ли вы объяснить, почему я должен? Безусловно, он никогда не будет меньше нуля. –

+1

@HaroutTatarian: Ты в этом прав. Я никогда не смотрел так близко в это ограниченное время, поскольку я собирался уехать на свое рабочее место. Теперь, когда я приехал сюда, мне удалось вывести на экран вывод обоих алгоритмов для вас, просто чтобы проверить, как они оба используют разные индексы для подкачки. Вывод достаточно описателен, чтобы сказать разницу между тем, какой подход более эффективен. –

1

Я собираюсь сделать deck аргумент и метод static. Таким образом, это самодостаточно. В Java соглашения об именах заключаются в том, чтобы имена переменных и методов начинались с строчной буквы. Далее, самый короткий путь я знаю, чтобы перетасовать колоду на месте с Collections.shuffle(List) и Arrays.asList(T...) как

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

Если вы хотите сохранить оригинальный deck, то вы можете скопировать его и return как

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