我如何编写一种方法来重新排列卡片中的卡片

时间:2011-04-17 21:04:11

标签: java

我需要将一副牌分成两个包:上半部分和下半部分。这个新的卡阵列假设是:来自顶部数据包的第一张卡,来自底部数据包的第一张卡,来自顶部数据包的第二张卡,来自底部数据包的第二张卡等。如果存在奇数数量的卡,则顶部数据包应该比底部数据包多一个。甲板的顶部是阵列的前部。

我将如何做到这一点?

这是我创建的用于生成牌组的方法(我认为它有效):

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

3 个答案:

答案 0 :(得分:5)

在你做你说的话之前,请注意perfect shuffle一个好主意,如果你想要随机化一个套牌的顺序:

  

完美的faro shuffle,卡片完美交替,被认为是卡片操作中最困难的小巧之一,因为它需要洗牌器将牌组切成两个相等的堆叠并在推动半个时施加恰当的压力互相攻击。如果一个人设法连续执行八个完美的faro out-shuffle,那么52张牌的牌组将恢复到原来的顺序。如果一个人可以进行完美的洗牌,那么26次洗牌会改变牌组的顺序,另外26次将使其恢复到原来的顺序。


另一方面,如果你想要随机 shuffle,那么走的路是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位的内部状态,这意味着它只能产生2个 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]

答案 1 :(得分:2)

我在这个问题中寻找类似的东西(洗牌JSONArray):An efficient way to shuffle a JSON array in java?

我最终制作了自己的shuffle方法来实现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;
}

答案 2 :(得分:2)

如果您能够替换非完美的shuffle,请尝试使用Collections.shuffle()。您的代码看起来像这样:

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

或正如@Mark Peters指出的那样,更简洁:

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