I need to generate 8 random integers, but they need to be unique, aka not repeated.
For example, I want 8 numbers within the range 1 to 8.
I've seen arc4random but I'm not sure how to make them unique ?
Solution
-(NSMutableArray *)getRandomInts:(int)amount from:(int)fromInt to:(int)toInt {
if ((toInt - fromInt) +1 < amount) {
return nil;
}
NSMutableArray *uniqueNumbers = [[[NSMut开发者_StackOverflowableArray alloc] init] autorelease];
int r;
while ([uniqueNumbers count] < amount) {
r = (arc4random() % toInt) + fromInt;
if (![uniqueNumbers containsObject:[NSNumber numberWithInt:r]]) {
[uniqueNumbers addObject:[NSNumber numberWithInt:r]];
}
}
return uniqueNumbers;
}
-(NSMutableArray *)getEightRandom {
NSMutableArray *uniqueNumbers = [[[NSMutableArray alloc] init] autorelease];
int r;
while ([uniqueNumbers count] < 8) {
r = arc4random();
if (![uniqueNumbers containsObject:[NSNumber numberWithInt:r]]) {
[uniqueNumbers addObject:[NSNumber numberWithInt:r]];
}
}
return uniqueNumbers;
}
If you want to restrict to numbers less than some threshold M, then you can do this by:
-(NSMutableArray *)getEightRandomLessThan:(int)M {
NSMutableArray *uniqueNumbers = [[[NSMutableArray alloc] init] autorelease];
int r;
while ([uniqueNumbers count] < 8) {
r = arc4random() % M; // ADD 1 TO GET NUMBERS BETWEEN 1 AND M RATHER THAN 0 and M-1
if (![uniqueNumbers containsObject:[NSNumber numberWithInt:r]]) {
[uniqueNumbers addObject:[NSNumber numberWithInt:r]];
}
}
return uniqueNumbers;
}
If M=8, or even if M is close to 8 (e.g. 9 or 10), then this takes a while and you can be more clever.
-(NSMutableArray *)getEightRandomLessThan:(int)M {
NSMutableArray *listOfNumbers = [[NSMutableArray alloc] init];
for (int i=0 ; i<M ; ++i) {
[listOfNumbers addObject:[NSNumber numberWithInt:i]]; // ADD 1 TO GET NUMBERS BETWEEN 1 AND M RATHER THAN 0 and M-1
}
NSMutableArray *uniqueNumbers = [[[NSMutableArray alloc] init] autorelease];
int r;
while ([uniqueNumbers count] < 8) {
r = arc4random() % [listOfNumbers count];
if (![uniqueNumbers containsObject:[listOfNumbers objectAtIndex:r]]) {
[uniqueNumbers addObject:[listOfNumbers objectAtIndex:r]];
}
}
[listOfNumbers release];
return uniqueNumbers;
}
Uniqueness is something that you need to provide-- randomness APIs won't do this for you.
As has been suggested, you can generate a number and then check to see whether it collides with something you've already generated, and if so, try agin. Please note however, that depending on the quantity of numbers and the size of the range, this becomes an algorithm that doesn't have a guaranteed end point.
If you're really just trying to get a contiguous set of numbers in random order, this is a not the way to do it, since it could take an unpredictably long time to complete. In this case, building an array of all desired values first, and then "shuffling" the array is a better choice. The best shuffle is the Fisher-Yates, but if you don't need it to be perfectly unbiased, you could also do what's described here.
Checking for already generated numbers is potentially expensive (theoretically, it could take forever.) However, this is a solved problem. You want a shuffling algorithm, like the Fisher-Yates_shuffle
On iOS probably something like:
NSMutableArray *randSequence = [[NSMutableArray alloc] initWithCapacity:8];
for (int ii = 1; ii < 9; ++ii)
[randSequence addObject:[NSNumber numberWithInt:ii]];
for (int ii = 8; ii > 0; --ii) {
int r = arc4random() % (ii + 1);
[randSequence exchangeObjectAtIndex:ii withObjectAtIndex:r];
// you can now iterate over the numbers in `randSequence` to get
// your sequence in random order
Store the numbers in an array, and each time you generate the next - check if it already exists in the array. If not, then add it and continue.
Here's some psuedo code
- For each number 1-8 generate a random number.
- Add the random number and the integer to a dictionary as a key value pair
- get all the keys of the dictionary as an array (hint: have a look at the
allKeys
method) - Sort this array (ascending or descending isn't important)
- Now for each of these numbers as the key, get the corresponding integer from the dictionary
Try this code...this will give you all the possible unique number set in Mutable array...
-(NSInteger) randomNumber {
NSInteger newRandomNumber = (NSInteger) arc4random() % 10;
NSInteger uniqueNumber;
if ([self.arrayContainingNumbers containsObject: [NSNumber numberWithInteger:newRandomNumber]]) {
[self randomNumber];
} else {
[self.arrayContainingNumbers addObject: [NSNumber numberWithInteger:newRandomNumber]];
}
uniqueNumber = [[self.mutableArrayContainingNumbers lastObject]integerValue];
NSLog(@"new Unique Number is %ld",(long)uniqueNumber);
return uniqueNumber;
}
Don't forget to add this method :)
-(NSMutableArray *) arrayContainingNumbers {
if (!_mutableArrayContainingNumbers) {
_mutableArrayContainingNumbers = [[NSMutableArray alloc] init];
}
return _mutableArrayContainingNumbers;
}
精彩评论