这是否足以让一副纸牌洗牌?

时间:2014-04-30 16:38:46

标签: ios objective-c algorithm shuffle

我正在尝试在我的应用中随机播放一副牌,我使用以下代码。这会使甲板充分随机化吗?我几乎肯定会只是想要另一种意见。谢谢!

for (int i = 0; i < 40000; i++) {
    int randomInt1 = arc4random() % [deck.cards count];
    int randomInt2 = arc4random() % [deck.cards count];
    [deck.cards exchangeObjectAtIndex:randomInt1 withObjectAtIndex:randomInt2];

编辑:如果有人想知道或将来会遇到这个问题。这就是我用去洗牌的方式,它是Fisher-Yates算法的一个实现。我从下面提到的@MartinR帖子中找到了它,可以在这里找到:What's the Best Way to Shuffle an NSMutableArray?

NSUInteger count = [deck.cards count];
    for (uint i = 0; i < count; ++i)
    {
        // Select a random element between i and end of array to swap with.
        int nElements = count - i;
        int n = arc4random_uniform(nElements) + i;
        [deck.cards exchangeObjectAtIndex:i withObjectAtIndex:n];
    }

3 个答案:

答案 0 :(得分:7)

如果[deck.cards count]&lt;你的代码应该工作得相当好40000但是追随更好

for (int i = [deck.cards count] - 1; i > 0 ; i--) {
    int randomInt1 = arc4random_uniform(i + 1);
    [deck.cards exchangeObjectAtIndex:randomInt1 withObjectAtIndex:i];
}

来自docs:

  

arc4random_uniform()将返回均匀分布的随机数   小于upper_bound。        arc4random_uniform()建议使用像``arc4random()%upper_bound''这样的结构,因为它避免了        当上限不是2的幂时,“模偏”。

答案 1 :(得分:3)

这是正确实施的Fisher-Yates算法。是的,它会使你的阵列充分随机化,我已经多次使用它并且它非常好!

NSUInteger count = [deck.cards count];
if (count > 0) {
    for (NSUInteger i = count - 1; i > 0 ; --i) {
        [deck.cards exchangeObjectAtIndex:i
                        withObjectAtIndex:arc4random_uniform(i + 1)];
    }
}

答案 2 :(得分:0)

根据甲板的实现方式,您可以简单地使用Collections.sort(),也可以使用ArrayList,前提是您的实现类似于以下内容

    ArrayList<Integer> originalDeck = new ArrayList<Integer>();
    ArrayList<Integer> randomDeck = new ArrayList<Integer>();

    //Initalize array
    for (int i = 0; i < 52; i++) {
        originalDeck.add(i, i);
    }

    //Smart Implementation
    Collections.shuffle(originalDeck);

    Collections.sort(originalDeck);

    //Long Implementation
    int i=0, max = 0;
    while (originalDeck.size() != 0) {
        max = originalDeck.size();
        i = (int) (Math.random() * max); // goes from 0 to size-1 so always in bounds
        randomDeck.add(originalDeck.remove(i));
    }