2015-06-10 8 views
5

Ich habe diese Methode selbst geschrieben Ich möchte wissen, ob es einen besseren Weg gibt, es zu tun?Java: Mische ein Deck aus 32 Karten?

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

Sieht nicht so schlecht aus. Abgesehen von der offensichtlichen Alternative, auf die bereits hingewiesen wurde, würde ich empfehlen, Java-Namenskonventionen zu übernehmen und Kleinbuchstaben für Methoden- und Variablennamen zu verwenden. –

+0

@jangroth danke für den Rat. –

Antwort

-1

Ich denke, man kann ein besseres Ergebnis erhalten, wenn Sie das Element wählen aus dem gesamten Deck ausgetauscht werden und nicht nur von den übrigen Karten, wie folgt aus:

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

Überraschenderweise ist es tatsächlich schlimmer, eine Karte aus dem vollen Sortiment zu wählen. [Hier] (http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Potential_sources_of_bias) ist eine gute Diskussion über Implementierungsfehler; Die Verwendung der vollen Reichweite ist ein häufiges Problem. – dasblinkenlight

+0

@dasblinkenlight Überraschenderweise, in der Tat. Danke, dass du darauf hingewiesen hast. –

+0

Dies kann zu einem schlechten Shuffle führen, was bedeutet, dass die Zufallszahl niemals bestimmte Karten aus dem Deck auswählt. –

2

Sie nicht überprüft, ob (32 - i) gibt immer einen Wert unter 0. Der Algorithmus ist Fisher-Yates schlurfenden Algorithmus genannt, die wie Ihnen sehr ähneln:

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:

Der Ausgang der beiden Algorithmen besser machen Sie den Unterschied zwischen den beiden zu verstehen, wie Fisher-Yates berücksichtigen Sie alle Indizes beim Mischen.

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

Hier fand ich eine sehr gute Seite zum Lernen solcher [Algorithmen] (http://bost.ocks.org/mike/algorithms/#shuffling) –

+1

Ja, Sie haben Recht, ich habe es nicht überprüft. Kannst du erklären warum ich? Weil es offensichtlich nie weniger als Null sein wird. –

+1

@HaroutTatarian: Sie sind wahr, in diesem. Ich habe in dieser begrenzten Zeit noch nie so genau hingeschaut, als ich mich auf den Weg zu meinem Arbeitsplatz machte. Nun, da ich hierher gekommen bin, habe ich es geschafft, die Ausgabe beider Algorithmen für Sie zu erstellen, nur um zu überprüfen, wie sie beide unterschiedliche Indizes für den Austausch verwenden. Die Ausgabe ist beschreibend genug, um den Unterschied zu erkennen, zwischen welchem ​​Ansatz effizienter ist. –

1

Ich werde die deck ein Argument, und das Verfahren static machen. So ist es in sich geschlossen. In Java sollen Namenskonventionen dafür sorgen, dass Variablen und Methodennamen mit einem Kleinbuchstaben beginnen. Als nächstes weiß der kürzeste Weg I ist das Deck an Ort und Stelle mit Collections.shuffle(List) und Arrays.asList(T...) wie

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

zu mischen Wenn Sie die ursprünglichen deck erhalten wollen, dann können Sie sie kopieren und return wie

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