Non-repeating arc4random_uniform

谁都会走 提交于 2019-11-28 10:30:39
Josh Caswell

There's no guarantee whatsoever that ar4random_uniform() won't repeat. Think about it for a second -- you're asking it to produce a number between 0 and 103. If you do that one hundred and five times, it has no choice but to repeat one of its earlier selections. How could the function know how many times you're going to request a number?

You will either have to check the list of numbers that you've already gotten and request a new one if it's a repeat, or shuffle the array. There should be any number of questions on SO for that. Here's one of the oldest: What's the Best Way to Shuffle an NSMutableArray?.

There's also quite a few questions about non-repeating random numbers: https://stackoverflow.com/search?q=%5Bobjc%5D+non-repeating+random+numbers

HeWhoShallNotBeNamed

You can create an NSMutableSet and implement it like this:

NSMutableArray* numbers = [[NSMutableArray alloc] initWithCapacity: 13];
NSMutableSet* usedValues = [[NSMutableSet alloc] initWithCapacity: 13];

for (int i = 0; i < 13; i++) {
  int randomNum = arc4random_uniform(104);
  while ([usedValues containsObject: [NSNumber numberWithInt: randomNum]) {     
    randomNum = arc4random_uniform(104)
  }
  [[usedValues addObject: [NSNumber numberWithInt: randomNum];
  [numbers addObject: [[NSNumber numberWithInt: randomNum];
}

Alternatively you can also create a mutable array of 105 integers each a unique one, and arc4random_uniform([arrayname count]) and then delete that same one from the array, then you'll get a random int each time without repeating (though the smaller the array gets the easier it is to predict what the next number will be, just simple probability)

Kostub Deshmukh

The best algorithm that I have found for this exact question is described here:

Algorithm to select a single, random combination of values?

Instead of shuffling an array of 104 elements, you just need to loop through 13 times. Here is my implementation of the algorithm in Objective C:

// Implementation of the Floyd algorithm from Programming Pearls.
// Returns a NSSet of num_values from 0 to max_value - 1.
static NSSet* getUniqueRandomNumbers(int num_values, int max_value) {
    assert(max_value >= num_values);
    NSMutableSet* set = [NSMutableSet setWithCapacity:num_values];
    for (int i = max_value - num_values; i < max_value; ++i) {
        NSNumber* rand = [NSNumber numberWithInt:arc4random_uniform(i)];
        if ([set containsObject:rand]) {
            [set addObject:[NSNumber numberWithInt:i]];
        } else {
            [set addObject:rand];
        }
    }
    return set;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!