我有一张包含52张牌的阵列列表。我想洗牌。
这就是我所做的。
这是我的代码:
String[] Number = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[] Suits = {"Club","Diamonds","Hearts","Spades"};
ArrayList<Card> deck = new ArrayList<Card>();
// create a deck
for(int i=0;i<13;i++){
for(int j=0;j<4;j++){
Card card = new Card(Suits[j],Number[i]);
deck.add(card);
}
}
// shuffle of deck
ArrayList<Card> new_deck = new ArrayList<Card>();
while(deck.size()!=0){
Random rand = new Random();
int n = rand.nextInt(deck.size());
new_deck.add(deck.get(n));
deck.remove(n);
}
// Display
for(int i=0;i<52;i++){
System.out.println(new_deck.get(i).getSuit()+" : "+new_deck.get(i).getValue());
}
最后,我从新的ArrayList获得了混乱的套牌。
它的随机性是否足够好?
我应该怎么做才能增加随机性?
答案 0 :(得分:4)
它的随机性是否足够?
定义足够好(!!)
您当前的方法将提供一个良好的洗牌,没有明显的偏见... 除了可能由随机数生成器引入的偏差。
在这种情况下,确实值得关注。 Random被指定为线性同余生成器,并且LC生成在它们生成的数量中具有不同的模式。 (在统计学上,它们表现出强烈的自相关性。)如果你将第n个随机数与n进行比较,这一点非常清楚。
要提高随机性,您应该使用更好的随机数生成器。 SecureRandom
生成器应该足够好:javadoc。
如果使用Collections.shuffle
方法,则会对随机性产生同样的担忧。对于良好(或一致)shuffle,您应该在提供Random
实现的情况下使用方法重载...并选择一个好的。
答案 1 :(得分:3)
我建议您只需使用Collections.shuffle(),如下所示,而不是重新发明已由Collections
API提供的改组逻辑:
Collections.shuffle(deck);//Pass your ArrayList<Card> object i.e., deck
因此,通过重用现有的Collections
API,您可以清除对deck
对象随机性的所有怀疑。
答案 2 :(得分:1)
你应该定义你的概念&#34;随机性&#34;以一种精确的方式。 &#34;增加随机性&#34;是一个相当模糊的术语。
我将假设&#34;随机&#34;,你想要的是你牌上的uniform distribution permutation。也就是说,你希望你的牌组重新排序,使得下一张牌是特定牌的机会相等。
这里有两个不同的因素:
Random
有多好就你如何洗牌而言,它是统一的。 conditional probability可以证明任何位置的任何卡都是1/52。
util.Random
有多好首先,要清楚,util.Random
不实际上是随机的。这是pseudorandom number generator(PRNG)。这意味着他们所做的不是产生真正随机的数字。相反,他们尝试,并且根据应用要求,它就足够了。
util.Random
是linear congruential generator,就PRNG来说,它非常弱。如果你不关心真的随机化你的套牌,它会正常工作。但是,如果您需要更强大的功能,here是一个起点。
答案 3 :(得分:0)
这里没有提到一个关于java.util.Random
的问题:它是否可以生成52项列表的所有排列。这是基于它的时期。通常,伪随机数发生器(PRNG)不能产生比其周期更多的随机数序列的排列(参见&#34; Shuffling&#34;在我的article on randomness中进行进一步讨论)。
java.util.Random
的周期不高于2 48 ,因为它使用48位种子长度。但是,52个项目列表有52个因子排列,并且高于2个 225 - 超过java.util.Random
个周期的许多订单数量级。因此,java.util.Random
无法生成52个项目列表的许多很多排列(使用相同的混洗技术)。 (这适用于任何 PRNG,其周期小于52因子,而不仅仅是线性同余生成器,尤其是java.util.Random
。)因此,需要对52-进行洗牌的应用程序项目清单建议使用一个生成器,用于生成成本过高而无法预测的随机数(例如Java SecureRandom
)或使用周期为52-factorial或更高的PRNG(尽管高的时期本身可能不足以确保PRNG能够产生该列表的所有排列。)
编辑:最近的两个问题讨论了如何产生足够的随机性来改组数字&#34;套牌&#34; 52卡:
Is java.util.Random really that random? How can I generate 52! (factorial) possible sequences?
Where can I get a reliable source of entropy (real randomness byte[])?
解决方案的要点是,您需要找到一种生成226位或更多 entropy (随机性)的方法,并使用它来帮助生成随机排列。有关详细信息,请参阅相关问题,另请参阅我在nondeterministic sources and seed generation上的部分。