2011-04-17 62 views
2

我需要將一副卡片分成兩個數據包:上半部分和下半部分。假設這種新的卡片陣列是:從頂部數據包開始的第一張卡片,從底部數據包開始的第一張卡片,從頂部數據包開始的第二張卡片,從底部數據包開始的第二張卡片等等。如果卡片數量爲奇數,則頂部數據包應該比底部的數據包多一個。甲板的頂部是陣列的前部。我該如何編寫一種重新排列卡片組的方法

我怎麼會去這樣做呢?

這裏是我創建生成的撲克牌的方法(我認爲它的工作原理):

private Card[] cards; 
int value, suit; 
private final int DECK_SIZE = 52; 

public Deck() 
    { 
     int index = 0; 
     cards = new Card[DECK_SIZE]; 
     //0 = spades, 1 = hearts, 2 = clovers, 3 =diamonds 
     int suits[] = {0, 1, 2, 3}; 
     //1 = Ace, 11=jack, 12=queen, 13=king 
     int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; 
     for (int suit : suits) 
      for (int value : values) 
      { 
       cards[index] = new Card(value, suit); 
       index++; 
      } 
    } 
+1

僅供參考他們的俱樂部,沒有三葉草。你最近一直沒有吃幸運咒的麥片粥,對嗎? – 2011-04-17 21:08:47

+1

...和麪卡是傑克女王國王,不是百搭女王國王。 – 2011-04-17 21:09:15

+1

@user:考慮使用enum來表示值。 – 2011-04-17 21:18:00

回答

5

在你走之前這樣做,你說什麼,注意,perfect shuffle一個好主意如果你正在尋找隨機甲板的順序:

一個完美的法魯洗牌,其中卡完全交替,被視爲卡操作最困難的sleights之一,因爲它需要洗牌削減甲板進入兩個相同的疊層,並在將半甲板推入彼此時施加正確的壓力。如果一個人設法連續完成八個完美的法魯出牌洗牌,那麼52張牌組成的牌組將恢復到原來的順序。如果一個人能夠完成洗牌,那麼26次洗牌就會逆轉牌組的順序,另外26次將恢復到原來的順序。


如果你想有一個隨機洗牌,而另一方面,要走的路是Fisher-Yates shuffle。從維基百科頁面:但是

To shuffle an array a of n elements (indexes 0..n-1): 
    for i from n − 1 downto 1 do 
     j ← random integer with 0 ≤ j ≤ i 
     exchange a[j] and a[i] 

注意的是,根據您的隨機性標準,標準的Java隨機數生成器可能不足以:(也從維基百科頁面:)

例如,由許多編程語言和/或庫提供的內置僞隨機數發生器通常可能只有32位內部狀態,這意味着它只能產生不同的數字序列。如果使用這種發電機來洗牌一副52張撲克牌,它只能產生52的一小部分! ≈2 225.6可能的排列組合。內部狀態低於226位的發生器不可能產生52張牌組的所有可能的排列。有人提出[需要引用],洗牌沒有偏見的信心只能通過一個具有超過約250比特狀態的發生器才能達到。

Mersenne Twister是一個衆所周知的隨機數發生器,將是足夠的。


編輯:於文字回答你原來的問題,這裏就是我可能會做它(包括試驗方法):

輸出的
import java.util.Arrays; 

public class Shuffle { 
    /* assumes input and output arrays are same length (N) */ 
    static public <T> void perfectShuffle(T[] input, T[] output, int N) 
    { 
     int itop = 0; 
     int ibottom = N - (N/2); 
     /* bottom has (N/2) elements; for odd N this is rounded down, 
     * and the top part has 1 more element */ 
     int k = 0; 
     while (ibottom < N) 
     { 
      output[k++] = input[itop++]; 
      output[k++] = input[ibottom++]; 
     } 
     // handle last element for N = odd 
     if (k < N) 
      output[k] = input[itop]; 
    } 

    public static void main(String[] args) { 
     int N = 19; 
     String[] in = new String[N]; 
     String[] out = new String[N]; 
     for (int i = 0; i < N; ++i) 
      in[i] = Integer.toString(i); 
     perfectShuffle(in, out, N); 
     System.out.println(Arrays.asList(out)); 
    } 
} 

main()

[0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9] 

最後,你不應該用這個來洗牌:

public static void main(String[] args) { 
    int N = 52; 
    String[] in = new String[N]; 
    String[] out = new String[N]; 
    for (int i = 0; i < N; ++i) 
     in[i] = Integer.toString(i); 

    for (int k = 0; k < 8; ++k) 
    { 
     perfectShuffle(in, out, N); 
     System.out.println(Arrays.asList(out)); 

     String[] tmp = in; 
     in = out; 
     out = tmp;   
    } 
} 

輸出:

[0, 26, 1, 27, 2, 28, 3, 29, 4, 30, 5, 31, 6, 32, 7, 33, 8, 34, 9, 35, 10, 36, 11, 37, 12, 38, 13, 39, 14, 40, 15, 41, 16, 42, 17, 43, 18, 44, 19, 45, 20, 46, 21, 47, 22, 48, 23, 49, 24, 50, 25, 51] 
[0, 13, 26, 39, 1, 14, 27, 40, 2, 15, 28, 41, 3, 16, 29, 42, 4, 17, 30, 43, 5, 18, 31, 44, 6, 19, 32, 45, 7, 20, 33, 46, 8, 21, 34, 47, 9, 22, 35, 48, 10, 23, 36, 49, 11, 24, 37, 50, 12, 25, 38, 51] 
[0, 32, 13, 45, 26, 7, 39, 20, 1, 33, 14, 46, 27, 8, 40, 21, 2, 34, 15, 47, 28, 9, 41, 22, 3, 35, 16, 48, 29, 10, 42, 23, 4, 36, 17, 49, 30, 11, 43, 24, 5, 37, 18, 50, 31, 12, 44, 25, 6, 38, 19, 51] 
[0, 16, 32, 48, 13, 29, 45, 10, 26, 42, 7, 23, 39, 4, 20, 36, 1, 17, 33, 49, 14, 30, 46, 11, 27, 43, 8, 24, 40, 5, 21, 37, 2, 18, 34, 50, 15, 31, 47, 12, 28, 44, 9, 25, 41, 6, 22, 38, 3, 19, 35, 51] 
[0, 8, 16, 24, 32, 40, 48, 5, 13, 21, 29, 37, 45, 2, 10, 18, 26, 34, 42, 50, 7, 15, 23, 31, 39, 47, 4, 12, 20, 28, 36, 44, 1, 9, 17, 25, 33, 41, 49, 6, 14, 22, 30, 38, 46, 3, 11, 19, 27, 35, 43, 51] 
[0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51] 
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51] 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51] 
+0

這應該是一個評論... – Jeff 2011-04-17 21:09:01

+1

我會編輯來解釋如何實現隨機洗牌。否則,這個問題是一個毫無疑問的問題,恕我直言。 – 2011-04-17 21:10:11

+0

我不明白這是如何接近回答用戶問的問題。這是一個洗牌的好帖子,但這不是用戶要求的,而且這個問題的評論顯示,*這個問題已經在其他地方多次得到解答。 – 2011-04-17 21:33:16

2

我一直在尋找類似的東西在這個問題(混排JSONArray),其中:An efficient way to shuffle a JSON array in java?

最後我使我自己的洗牌方法實現this algorithm。對於你的例子,它會是這樣的:

public Card[] shuffle(Card[] cards) { 
    // Implementing Fisher–Yates shuffle 
     Random rnd = new Random(); 
     for (int i = cards.length() - 1; i >= 0; i--) 
     { 
      int j = rnd.nextInt(i + 1); 
      // Simple swap 
      Card card = cards[j]; 
      cards[j] = cards[i]; 
      cards[i] = card; 
     } 
     return cards; 
} 
+1

爲什麼不使用'Collections.shuffle'? 'Collections.shuffle(Arrays.asList(卡))'。 – 2011-04-17 21:23:27

+0

@標記這是我的第一個選項,但是這樣可以避免再次從數組中創建List並返回到數組。在我引用的問題中,我問到效率問題,但沒有人給我一個答案。我甚至將它發佈在代碼審查上,唯一的評論是關於使用泛型(這也是非常正確的)。我明白這個數組不是JSONArray,但問題是相似的,算法很簡單,就這樣做。我不知道有多少套牌會同時洗牌。 – Aleadam 2011-04-17 22:01:11

+1

這種方法效率不高的一個原因是,它只是複製卡來交換它們。這應該永遠不需要,即使它是卡片可變類型(它肯定不應該)。只需重新分配卡而不是創建一個新卡。 – 2011-04-17 22:28:21

2

如果你能夠取代一個非完美的洗牌,嘗試Collections.shuffle()。您的代碼會是這個樣子:

List card_list = Arrays.asList(cards); 
Collections.shuffle(card_list); 

或@馬克彼得斯指出,更簡潔:

Collections.shuffle(Arrays.asList(cards)); 
+0

1)您應該使用泛型,2)您不需要執行'toArray'這一行。我發佈在@ Aleadam的答案上的評論就是你需要做的。 – 2011-04-17 21:36:06

+0

感謝馬克,我實際上是在關注新列表是否由原始數組支持,然後注意到你在我之前。 – 2011-04-17 21:40:16

+0

是啊......我需要在我評論之前學會查看問題的時間戳:-)。 – 2011-04-17 21:41:38