How can I never repeat a already generated random number?
本问题已经有最佳答案,请猛点这里访问。
如何使arc4random()集中的随机生成的数字永不重复?例如,在arc4random(100)中,选择1,它将不再被提起。
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 | 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) |
您所做的不是生成随机数,而是以随机顺序显示一组数字。
有一种非常简单的算法(也很快)叫做fisher-yates shuffle。它随机移动一个数组。唯一的缺点是它意味着数组中的任何数字都不能位于它开始的位置。(在你的情况下,这可能是也可能不是一个不利因素)。
无论如何,您应该创建数字数组。1-300然后洗牌。
然后,当您迭代数组时,您将得到一组完整的300个数字,而不需要任何重复,每次都是以随机顺序进行的。
这是我用的密码。(记住现在是凌晨3点,我很累,但我不得不这么做)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
也许有一个更整洁的方法来写它。
编辑了功能,因为我的不工作。根据这个答案改编。
在nsmutablerray上添加以下类别(这是修改后的fisher-yates shuffle):
1 2 3 4 5 6 7 | - (void) shuffle { for (NSInteger i = [self count] - 1; i > 0; --i) { [self exchangeObjectAtIndex:arc4random() % (i+1) withObjectAtIndex: i]; } } |
。
按顺序生成数字范围(例如1-300),并将其放入NSmutableArray(作为NSnumber)。然后,使用上面的随机播放方法。
然后,从NSmutableArray中按顺序提取结果(索引0-299)。你将随机抽取数字而不替换,我想这就是你想要的。
你要生成这些数字中的一些,还是很多?
如果您只生成了一些,那么您可能需要保留一个已经收到的列表,并在再次收到它们时重试。有点像…
1 2 3 4 5 6 7 8 9 10 | 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个数字上,你将反复循环,直到随机的机会,你最终得到的两个数字之一还没有在你的列表中。如果您想要生成大量的数字,那么创建一个集合(数组、堆栈等)以及其中所有的数字(1-100)并对其进行无序处理可能会更有效。然后你可以一次把它们从上面弹下来。
1 2 3 4 5 6 7 8 9 10 11 12 | 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]; } |
号
xcode 8?斯威夫特3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 } } |
使用
1 2 3 4 5 | 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] |
。