0

I'm trying to generate a unique number for a bingo app, now its choses at 90 random numbers between 1-90 and adds them to a NSMutableSet. That all works, but I get the number picked from the set to be unique, so the same number is pulled out twice.

Here is what I have so far:

NSMutableSet * numberSet1 = [NSMutableSet setWithCapacity:90];
while ([numberSet1 count] < 90 ) {
    NSNumber * randomNumber1 = [NSNumber numberWithInt:(arc4random() % 90 + 1)];
    [numberSet1 addObject:randomNumber1];
}
//NSLog(@"numberWithSet : %@ \n\n",numberSet1);

NSArray * numbers = [numberSet1 allObjects];
//to display
int r = arc4random() % [numbers count];
if(r<[numbers count]){
    numberLabel.text = [NSString stringWithFormat:@"%@", [numbers objectAtIndex:r]];
}

How can I stop it from giving me duplicates? Thanks in advance

Hassan Mahmood
  • 1,591
  • 2
  • 12
  • 24
  • The code appears to create an array with the numbers 1-90 in random order with no duplicates. What do you want it do and what is it actually doing? – rmaddy Nov 19 '12 at 22:32
  • @rmaddy it gives me duplicate numbers when I try to display the numbers in a label, I'm using the following to display int r = arc4random() % [numbers count]; if(r<[numbers count]){ numberLabel.text = [NSString stringWithFormat:@"%@", [numbers objectAtIndex:r]]; } – Hassan Mahmood Nov 19 '12 at 22:42
  • 1
    Why do you create a random list of numbers and then get a random element from the random array? Create the random list then get them in array order starting at index 0 through to index 89. – rmaddy Nov 19 '12 at 22:46
  • possible duplicate: http://stackoverflow.com/questions/196017/unique-random-numbers-in-o1 – pasawaya Nov 19 '12 at 22:58
  • Yet again, someone who SHOULD NOT start with Objective-C. Begin with Java. You're not going to create that "killer app" any sooner starting with Objective-C, and you'll never learn the basics. – Hot Licks Nov 19 '12 at 23:27

4 Answers4

1

As an alternative to picking random numbers with arc4random() (which samples with replacement, which you probably don't want for a Bingo game):

  1. Take an array of numbers 1 through 90.
  2. Shuffle that array.
  3. Pick the first number from the array, then the second, and so on.

Keep an index of the currently selected element in the array. To get the next number, increment and check if you are dereferencing the 90th element.

Some pseudo-code:

#define SIZE 90

unsigned int index;
unsigned int elements[SIZE];

/* step 1 -- populate the array with elements 1 through 90 */
for (index = 0; index < SIZE; index++)
    elements[index] = index + 1;

/* step 2 -- shuffle the array */
fisher_yates_shuffle(elements);

/* step 3 -- read from the array */
for (index = 0; index < SIZE; index++)
    fprintf(stdout, "element at index %u is %u\n", index, elements[index]);
Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
0

This creates and shuffles an array.

// array to shuffle
NSMutableArray *array = [NSMutableArray array];
for(int i=1; i<91; i++){
    [array addObject:[NSNumber numberWithInt:i]];
}

// shuffle
for (int i = [array count]-1; i>0; i--) {
    [array exchangeObjectAtIndex:i withObjectAtIndex:arc4random()%(i+1)];
}

Not sure if this is what you want since picking 90 numbers at random from 1-90 with no duplicates and adding them to a mutable set is no different from adding everything to a mutable set. But if you want a subset of the 90 numbers just take up to n elements from the array.

Jano
  • 62,815
  • 21
  • 164
  • 192
0

From a lottery app I wrote a while back, also applicable here-

int ball[6], counter, check, similarity;
for ( counter = 1; counter <= 6; counter++ )
{
    for (;;)
    {
        similarity = 0;
        ball[counter] = 1 + arc4random() % 6;
        for (check = counter-1; check >= 1;check--)
        {
            if ( ball[check] == ball[counter] )
            {
                similarity = 1;
                break;
            }
        }
    if(similarity == 0)
        break;
    }
printf("%i\n", ball[counter]);
}

Checks the chosen ball with all previous balls, will never get the same number twice.

PappaSmalls
  • 349
  • 2
  • 13
0

Create a category on NSMutableArray

@implementation NSMutableArray (RandomUtils)
-(void)shuffle
{
    NSUInteger count = [self count];
    for (NSUInteger i = 0; i < count; ++i) {
        NSUInteger nElements = count - i;
        NSUInteger n = (arc4random() % nElements) + i;
        [self exchangeObjectAtIndex:i withObjectAtIndex:n];
    }
}

@end

You can also wrap it for a NSArray version

@implementation NSArray (RandomUtils)

-(NSMutableArray *)mutableArrayShuffled
{
    NSMutableArray *array = [[self mutableCopy] autorelease];
    [array shuffle];
    return array;
}

-(NSArray *)arrayShuffled
{
    return [NSArray arrayWithArray:[self mutableArrayShuffled]];
}

@end

Where needed, import the category, and do:

NSMutableArray *array = [NSMutableArray array];
for(int i=0; i<90; i++){
    [array addObject:[NSNumber numberWithInt:i+1]];
}
[array shuffle];
NSArray *newarray = [array subarrayWithRange:NSMakeRange(0,6)];

Another approach could be to fill a set with 6 random picks.

in the Category:

@implementation NSArray (RandomUtils)
-(id)randomElement
{
    if ([self count] < 1) return nil;
    NSUInteger randomIndex = arc4random() % [self count];
    return [self objectAtIndex:randomIndex];
}
@end

use it like:

NSMutableSet *mset = [NSMutableSet set];

while ([mset count]<6) {
    [mset addObject:[array randomElement]];
} 
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178