3

I need a method to generate 4 numbers positioned randonly in an array. This method must be able to be called several times. The code that I tried below seems to be working.. except that everytime I call it, it generates the very same numbers sequence.

At my header file:

NSMutableSet * numberSet;
NSArray * numbers;

Code file:

    numberSet = [NSMutableSet setWithCapacity:4];
    [self placeRandomLine];
    numbers = [numberSet allObjects];

... using the generated array

    [self placeRandomLine];
    numbers = [numberSet allObjects];

... using the generated array

    [self placeRandomLine];
    numbers = [numberSet allObjects];

... using the generated array

Random Method:

-(void)placeRandomLine
{
    [numberSet removeAllObjects];
    while ([numberSet count] < 4 ) {
        NSNumber * randomNumber = [NSNumber numberWithInt:(arc4random() % 4)];
        [numberSet addObject:randomNumber];
    }
}

I am sure I am missing something here..

Thanks for your help!

RickON
  • 395
  • 7
  • 18
  • Nice bug ;-) You might want to try something like this: http://stackoverflow.com/questions/791232/canonical-way-to-randomize-an-nsarray-in-objective-c – Matthias Bauch Jan 04 '14 at 11:31

2 Answers2

3

Use an ordered set:

NSMutableOrderedSet *numberSet = [NSMutableOrderedSet new];
int setSize = 4;
while ([numberSet count] < setSize ) {
    NSNumber * randomNumber = [NSNumber numberWithInt:arc4random_uniform(setSize)];
    [numberSet addObject:randomNumber];
}

NSLog output:

numberSet: {(
    2,
    0,
    1,
    3
)}

Alternatively using an array or arbitrary numbers
Create an NSMutableArray with the four integers.
Create an empty NSMutableArray.
Use arc4random_uniform() to pick one of the numbers in the first array, remove it and place it in the second array.
Repeat for all four numbers.
The second array will have the four numbers in a random order.

Example:

NSMutableArray *a0 = [@[@3, @5, @4, @8] mutableCopy];
NSMutableArray *a1 = [NSMutableArray new];
while (a0.count) {
    int randomIndex = arc4random_uniform(a0.count);
    NSNumber *randomValue = a0[randomIndex];
    [a1 addObject:randomValue];
    [a0 removeObject:randomValue];
}   
NSLog(@"a1: %@", a1);

NSLog output:

a1: (
    8,
    5,
    3,
    4
)

Alternatively using an ordered set

zaph
  • 111,848
  • 21
  • 189
  • 228
  • Great! I only added "[numberSet removeAllObjects];"before adding more objects! Thank you Zaph! – RickON Jan 04 '14 at 13:31
2

while ([numberSet count] < 4 ) will cause the loop to run until its elements are 0,1,2,3, because the set doesn't contain repeated elements.

Jano
  • 62,815
  • 21
  • 164
  • 192
  • That is it. I need the elements "0,1,2,3". In my case I am getting an array with the following sequence: "0,3,1,2"... but always like this... – RickON Jan 04 '14 at 11:36
  • 2
    that happens because `allObjects` returns the objects of a set in a undefined order, not in a random order, or an order that is imposed by the order you used to add objects to the set. In your case undefined means "always 0,3,1,2". – Matthias Bauch Jan 04 '14 at 11:38
  • But the imposed order used to add objects is random, according to the "placeRandomLine" method, right? – RickON Jan 04 '14 at 12:06