我怎么能不重复已经生成的随机数?

时间:2014-12-23 01:34:26

标签: swift

如何使它在arc4random()集中随机生成的数字永远不会重复。例如,在arc4random(100)中选择1,它将永远不会再次出现。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var card: UIImageView!

    @IBOutlet weak var nextButton: UIButton!


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }




    @IBAction func nextCardTapped(sender: UIButton) {



        //Edit number of cards here for the random card to show up
        var randomCard = arc4random_uniform(100)
        // Edit number of cards here for the random card to show up


        var randomCardString:String = String(format: "card%i", randomCard)


        self.card.image = UIImage(named: randomCardString)

4 个答案:

答案 0 :(得分:1)

您所做的不是生成随机数,而是以随机顺序显示一组数字。

有一种非常简单的算法(也很快)称为Fisher-Yates shuffle。它随机地随机播放一个数组。唯一的缺点是它意味着数组中的任何数字都不能在它开始的地方。 (这可能是也可能不是你的情况下的缺点)。

无论如何,你应该创建你的数字数组。 1-300,然后将它们洗牌。

然后,当你迭代数组时,你将得到完整的300个数字,没有任何重复,每次都是随机顺序。

这是我使用的代码。 (请记住,凌晨3点,我累了,但我必须这样做。)

import UIKit

var numbers: [Int] = []

for number in 1...52 {
    numbers.append(number)
}

for i in 0..<(numbers.count - 1) {
    let j = Int(arc4random_uniform(UInt32(numbers.count - i))) + i
    swap(&numbers[i], &numbers[j])
}

println(numbers)

可能有一种更简洁的方式来编写它。

编辑了这个功能,因为我没有工作。改编自this answer.

答案 1 :(得分:0)

您是要生成这些数字中的一些,还是很多?

如果您只生成一些,那么保留已经收到的列表可能是值得的,并且每当您再次获得其中一个时再次尝试。有点像...

NSMutableArray *uniqueNumbers = [[[NSMutableArray alloc] init] autorelease];

...

randomCard = arc4random_uniform(100);
while ([uniqueNumbers containsObject:[NSNumber numberWithInt:randomCard]]) {
    // try again
    randomCard = arc4random_uniform(100);
}
[uniqueNumbers addObject:[NSNumber numberWithInt:r]];

如果您打算以这种方式生成许多随机数,那么它将变得非常低效。例如,在第99个数字上,您将重复循环,直到您最终得到列表中已有的2个数字中的一个。如果你想生成很多数字,那么用它中的所有数字(1-100)创建一个集合(数组,堆栈等)可能会更有效率并将其洗牌。然后你可以一次将它们从顶部弹出。

NSMutableArray *uniqueNumbers = [[[NSMutableArray alloc] init] autorelease];
// build list
for(int i = 1; i <= 100; i = i + 1)
{
    [uniqueNumbers addObject:[NSNumber numberWithInt:i]];
}
// shuffle list
for(int i = 0; i < 100; i = i + 1)
{
    int n = arc4random() % 100;
    [uniqueNumbers exchangeObjectAtIndex:i withObjectAtIndex:n];
}

答案 2 :(得分:0)

在NSMutableArray上添加以下类别(这是修改过的Fisher-Yates shuffle):

- (void) shuffle
{
    for (NSInteger i = [self count] - 1; i > 0; --i)
    {
        [self exchangeObjectAtIndex:arc4random() % (i+1) withObjectAtIndex: i];
    }
}

按顺序生成数字范围(例如,1-300)并将它们放在NSMutableArray中(作为NSNumber)。然后,使用上面的shuffle方法。

然后,从NSMutableArray(索引0-299)顺序提取结果。您将随机抽取数字而无需替换,我认为这就是您所追求的。

答案 3 :(得分:-3)

Xcode 8•Swift 3

extension Array {
    var shuffled: Array {
        var elements = self
        return elements.shuffle()
    }
    @discardableResult
    mutating func shuffle() -> Array {
        indices.dropLast().forEach { a in
            guard case let b = Int(arc4random_uniform(UInt32(count - a))) + a, b != a else { return }
            swap(&self[a], &self[b])
        }
        return self
    }
}

使用

let numbers = Array(1...100)

let shuffled = numbers.shuffled   // [5, 60, 15, 13, 94, 70, 17, 80, 95, 11, 76, 55, 96, 45, 1, 4, 23, 97, 48, 21, 47, 38, 51, 64, 59, 44, 19, 79, 98, 61, 35, 67, 49, 71, 83, 82, 54, 69, 36, 100, 73, 99, 93, 6, 62, 91, 24, 32, 10, 31, 41, 84, 46, 72, 12, 87, 20, 65, 43, 22, 85, 68, 86, 89, 88, 58, 33, 18, 30, 63, 52, 90, 57, 14, 16, 81, 2, 29, 37, 8, 50, 78, 9, 66, 3, 7, 77, 53, 39, 56, 28, 42, 25, 27, 34, 92, 26, 74, 75, 40]

let get10randomNumbers = numbers.shuffled.prefix(10)   // [71, 23, 33, 48, 73, 81, 75, 18, 19, 67]