Reading random values ​​from an array

I have an array with 14 rows. I want to display each of these 14 lines to the user without duplicates. The closest I got was creating integers and shuffling their values, and then reading from an array of strings using one of the numbers from an int array as an index:

//appDelegate.randomRiddles is an array of integers that has integer values randomly appDelegate.randomRiddlesCounter++; NSNumber *index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter]; int i = [index intValue]; while(i>[appDelegate.currentRiddlesContent count]){ appDelegate.randomRiddlesCounter++; index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter]; i = [index intValue]; } hintText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:@"hint"]; questionText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:@"question"]; 

But my path causes a crash and duplicates. Oh, and every time I read a value from an array of strings, that row is removed from the array, decreasing its number by 1. Thus, this complicates this a bit.

+7
source share
5 answers

Get the elements in your array as follows:

 int position = arc4random() % ([myArray count]); 

This method, even if the count is reduced by one, is normal, since you will still get the actual value of the next position until there are more possible values.

+7
source

Under β€œno duplicates,” I assume that you want you to use each row in the array once before using the same row again, but do not want you to filter the array so that it does not contain duplicate rows.

Here's a feature using Shuffle Fisher-Yates:

 /** @brief Takes an array and produces a shuffled array. * * The new array will contain retained references to * the objects in the original array * * @param original The array containing the objects to shuffle. * @return A new, autoreleased array with all of the objects of * the original array but in a random order. */ NSArray *shuffledArrayFromArray(NSArray *original) { NSMutableArray *shuffled = [NSMutableArray array]; NSUInteger count = [original count]; if (count > 0) { [shuffled addObject:[original objectAtIndex:0]]; NSUInteger j; for (NSUInteger i = 1; i < count; ++i) { j = arc4random() % i; // simple but may have a modulo bias [shuffled addObject:[shuffled objectAtIndex:j]]; [shuffled replaceObjectAtIndex:j withObject:[original objectAtIndex:i]]; } } return shuffled; // still autoreleased } 

If you want to keep the connection between riddles, hints and questions, I would recommend using NSDictionary to store each set of related strings, rather than storing them in separate arrays.

+4
source

This task is very simple using NSMutableArray . To do this, simply remove the random element from the array, show it to the user.

Declare a mutable array as an instance variable

 NSMutableArray * questions; 

When the application starts, fill in the values ​​from myArray

 questions = [[NSMutableArray alloc] initWithArray:myArray]]; 

Then, to get a random element from the array and remove it, do the following:

 int randomIndex = (arc4random() % [questions count]); NSDictionary * anObj = [[[questions objectAtIndex:randomIndex] retain] autorelease]; [questions removeObjectAtIndex:randomIndex]; // do something with element hintText.text = [anObj objectForKey:@"hint"]; questionText.text = [anObj objectForKey:@"question"]; 
+2
source

No need to print so much. To shuffle an array, you simply sort it with a random comparator:

 #include <stdlib.h> NSInteger shuffleCmp(id a, id b, void* c) { return (arc4random() & 1) ? NSOrderedAscending : NSOrderedDescending; } NSArray* shuffled = [original sortedArrayUsingFunction:shuffleCmp context:0]; 
+2
source

You can copy the array into NSMutableArray and shuffle it. A simple demonstration of how to mix an array:

 #import <Foundation/Foundation.h> int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // Original array, here initialised with 1..9 NSArray *arr = [NSArray arrayWithObjects: [NSNumber numberWithInt: 1], [NSNumber numberWithInt: 2], [NSNumber numberWithInt: 3], [NSNumber numberWithInt: 4], [NSNumber numberWithInt: 5], [NSNumber numberWithInt: 6], [NSNumber numberWithInt: 7], [NSNumber numberWithInt: 8], [NSNumber numberWithInt: 9], nil]; // Array that will be shuffled NSMutableArray *shuffled = [NSMutableArray arrayWithArray: arr]; // Shuffle array for (NSUInteger i = shuffled.count - 1; i > 0; i--) { NSUInteger index = rand() % i; NSNumber *temp = [shuffled objectAtIndex: index]; [shuffled removeObjectAtIndex: index]; NSNumber *top = [shuffled lastObject]; [shuffled removeLastObject]; [shuffled insertObject: top atIndex: index]; [shuffled addObject: temp]; } // Display shuffled array for (NSNumber *num in shuffled) { NSLog(@"%@", num); } [pool drain]; return 0; } 

Note that all arrays and numbers here are auto-implemented, but in your code you may need memory management.

If you don't need to store elements in an array, you can simplify this (see also Oscar Gomez answer):

  NSUInteger index = rand() % shuffled.count; NSLog(@"%@", [shuffled objectAtIndex: index]); [shuffled removeObjectAtIndex: index]; 

In the end, the shuffled will be empty. You will also have to change the conditions of the loop:

  for (NSUInteger i = 0; i < shuffled.count; i++) 
+1
source

All Articles