Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 11-06-2010, 10:00 AM   #1 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default Generating random, non-repeating text

This question comes up on this board at least once a week. A while back I wrote some code to select random words or phrases from an array, and only select any given word/phrase once. Here is the code you need:



Code:
	NSArray* words;
	NSMutableArray* randomArray;
	NSMutableArray* array;
}
@property (nonatomic, retain)			NSArray* words;
@property (nonatomic, retain)			NSMutableArray* array;
@property (nonatomic, retain)			NSMutableArray* randomArray;
And put these methods (and one C function) into the .m file of the same class:


Code:
//This is the "sort" function that puts the items in random order.
//It uses a random number generator to decide the ordering of items in the array

NSInteger randomize(id num1, id num2, void *context)
{
	int rand = arc4random() %2;
	if (rand)
		return NSOrderedAscending;
    else 
        return NSOrderedDescending;
}

//This function populates "randomArray" with an array of indexes in random order.
//Once the getRandomWord method returns nil, call resetRandomArray to 
//repopulate the randomArray with the same list of words in a different random order.
- (void) resetRandomArray;
{
        //Copy over our starting "array" containing all our indexes in order.
	[randomArray setArray: array ];

        //Use a trick to "sort" the array into random order.
        //this trick involves using a sort function "randomize" that puts
        //the items in random order.
	[randomArray sortUsingFunction: randomize context:NULL];

}

-(NSString*) getRandomWord;
{
	if ([randomArray count] ==0)
		return nil;
	NSString* result;
	NSInteger randomIndex = [[randomArray lastObject] intValue];;
	[randomArray removeLastObject];
	result = [words objectAtIndex: randomIndex];
	return result;
}

-(void) buildRandomWordArray;
{	
	NSInteger index;
	
	NSError* theError;
	NSString *path = [[NSBundle mainBundle] pathForResource:@"words" ofType:@"txt"];
	NSString* text = [NSString stringWithContentsOfFile: path 
											   encoding: NSUTF8StringEncoding 
												  error: &theError];
	self.words = [text componentsSeparatedByString: @"\n"];
	
	int arraySize = [words count];
	self.array = [NSMutableArray arrayWithCapacity:arraySize];
	self.randomArray = [NSMutableArray arrayWithCapacity:arraySize];

        //This code fills "array" with index values from 0 to the number of elements in the "words" array.
	for (index = 0; index<arraySize; index++)
		[array addObject: [NSNumber numberWithInt: index]];
	[self resetRandomArray];
	
//	for (index = 0; index<=arraySize; index++)
//		NSLog(@"Random word: %@", [self getRandomWord]);
}
To use it:
-Create a file called words.txt containing a list of words or phrases separated by carriage returns.
-Drag that file into the resources portion of your project, so it will be included in the bundle.
-Call [self buildRandomWordArray] to do the initial setup. That reads the file and populates an array of random indexes.
-Call [self getRandomWord] to get a new random word or phrase. That word/phrase will be deleted from the list and not used again. Once the list is exhausted, the getRandomWord will return nil;
-To start over and get the same list of words in a different order, call [self resetRandomArray];
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Old 11-06-2010, 11:03 AM   #2 (permalink)
Fly-by-night Innovator
 
Join Date: Jun 2010
Posts: 364
musicwind95 is on a distinguished road
Default

Thanks!

Just a sidenote of sorts:
If you don't need to reuse this code too much, a (possibly) easier way is to populate an NSMutableArray, shuffle it, extract an element, and remove it. For instance:

Code:
- (id)randomObject {     // You could also pass in an array as an argument     
     self.randomArray = [[self.randomArray shuffledArray] mutableCopy];
     NSInteger index = arc4random() % [self.randomArray count] - 1;
     return [self.randomArray objectAtIndex:index];
     [self.randomArray removeObjectAtIndex:index];
}
Obviously, if you were to reuse this code, you would have to repopulate the array—it's a tradeoff between performance or less code.
__________________
If I have helped you, please consider donating. I use PayPal. It would mean a lot to me!


For more iOS Development, check out my blog—Cups of Cocoa. All visitors welcome, but especially beginners!

Hope I have helped!

Please check out IceFall, a new action game available in the App Store!
musicwind95 is offline   Reply With Quote
Old 03-09-2011, 09:38 AM   #3 (permalink)
J-E
Registered Member
 
Join Date: Feb 2011
Posts: 6
J-E is on a distinguished road
Default

Hi Duncan !
"Generating random, non-repeating text" is exactly what I would like to do within an app I'm trying to write. I'm an absolute beginner regarding this, so I hope you have some patience with my questions ;-) I have tried to apply your solution in my app, but I don get it to work. I'm using a plist instead of a txt-file, UIPicker and Button. I don't get how to apply your random stuff, so I get it to read my plist randomly and send it to the UIPicker when I press the button via IBAcation ? How do trigger this ?
//J-E
J-E is offline   Reply With Quote
Old 09-25-2011, 04:57 PM   #4 (permalink)
Registered Member
 
Join Date: Sep 2011
Posts: 3
laslov is on a distinguished road
Default How to make this work for UIViews?

Duncan,
I have 20 UIViews that I want to show randomly via a "next" button. I have it working but it does repeat:-( Can you pls. help me to make it non-repeat?
Also, after doing all 20 views, can it be made to go to a new page or xib?
Thanks in advance,
laslov
(Here's the code)
-(IBAction)next {
int UIView = random() % 20;
switch (UIView) {
laslov is offline   Reply With Quote
Old 09-25-2011, 05:03 PM   #5 (permalink)
Fly-by-night Innovator
 
Join Date: Jun 2010
Posts: 364
musicwind95 is on a distinguished road
Default

Quote:
Originally Posted by laslov View Post
-(IBAction)next {
int UIView = random() % 20;
switch (UIView) {
You can't just make a UIView an integer and then hope to switch through it. Wonder that it doesn't crash at all.

You'll need to give each view an identifier—either an index, if you're storing them in an NSArray (you don't need to actually create the index…), or a tag (which you do have to assign) if they're all in a XIB. You get the random index with the following code:

Code:
int index = arc4random() % 20;
If you're using tags, you should start numbering from 1 (because the default is zero and you want to avoid conflicts in the tag), so add one to that result. Then grab the view you want:

Code:
UIView *nextView = [self.viewsArray objectAtIndex:index];
or
Code:
UIView *nextView = [self.view viewWithTag:index];
Then display the view however you want.
__________________
If I have helped you, please consider donating. I use PayPal. It would mean a lot to me!


For more iOS Development, check out my blog—Cups of Cocoa. All visitors welcome, but especially beginners!

Hope I have helped!

Please check out IceFall, a new action game available in the App Store!
musicwind95 is offline   Reply With Quote
Old 09-26-2011, 08:22 AM   #6 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default

Quote:
Originally Posted by musicwind95 View Post
Thanks!

Just a sidenote of sorts:
If you don't need to reuse this code too much, a (possibly) easier way is to populate an NSMutableArray, shuffle it, extract an element, and remove it. For instance:

Code:
- (id)randomObject {     // You could also pass in an array as an argument     
     self.randomArray = [[self.randomArray shuffledArray] mutableCopy];
     NSInteger index = arc4random() % [self.randomArray count] - 1;
     return [self.randomArray objectAtIndex:index];
     [self.randomArray removeObjectAtIndex:index];
}
Obviously, if you were to reuse this code, you would have to repopulate the array—it's a tradeoff between performance or less code.
In fact, you could make the case that your approach is cleaner and simpler in all cases. Just do the following:

Create a "master" array of objects that you want to shuffle. (one-time setup)

Use mutableCopy to save a mutable copy of the array. Call it randomItems. You could use a retained property to keep track of it:

Code:
- (void) createRandomArray;
{
  self.randomItems  = [[masterArray mutableCopy] autorelease];
}
When you want a random item, use code like this:

Code:
-(id) getRandomItem
{
  if (![randomItems count])
    return nil;
  int index;
  index = arc4random() % [randomItems count];
  id item = [randomItems objectAtIndex: index];
  [randomItems removeItemAtIndex: index];
  return item;
}
When getRandomItem returns nil, just call createRandomArray again to repopulate the random array.

The above code assumes that the masterArray is kept for life of the program. That way, masterArray retains the objects so they don't get deallocated when you remove them from the randomItems array.
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Old 01-03-2012, 11:23 AM   #7 (permalink)
Registered Member
 
Join Date: Nov 2011
Posts: 7
Jimmyl is on a distinguished road
Default

Quote:
Originally Posted by Duncan C View Post
This question comes up on this board at least once a week. A while back I wrote some code to select random words or phrases from an array, and only select any given word/phrase once. Here is the code you need:



Code:
	NSArray* words;
	NSMutableArray* randomArray;
	NSMutableArray* array;
}
@property (nonatomic, retain)			NSArray* words;
@property (nonatomic, retain)			NSMutableArray* array;
@property (nonatomic, retain)			NSMutableArray* randomArray;
And put these methods (and one C function) into the .m file of the same class:


Code:
//This is the "sort" function that puts the items in random order.
//It uses a random number generator to decide the ordering of items in the array

NSInteger randomize(id num1, id num2, void *context)
{
	int rand = arc4random() %2;
	if (rand)
		return NSOrderedAscending;
    else 
        return NSOrderedDescending;
}

//This function populates "randomArray" with an array of indexes in random order.
//Once the getRandomWord method returns nil, call resetRandomArray to 
//repopulate the randomArray with the same list of words in a different random order.
- (void) resetRandomArray;
{
        //Copy over our starting "array" containing all our indexes in order.
	[randomArray setArray: array ];

        //Use a trick to "sort" the array into random order.
        //this trick involves using a sort function "randomize" that puts
        //the items in random order.
	[randomArray sortUsingFunction: randomize context:NULL];

}

-(NSString*) getRandomWord;
{
	if ([randomArray count] ==0)
		return nil;
	NSString* result;
	NSInteger randomIndex = [[randomArray lastObject] intValue];;
	[randomArray removeLastObject];
	result = [words objectAtIndex: randomIndex];
	return result;
}

-(void) buildRandomWordArray;
{	
	NSInteger index;
	
	NSError* theError;
	NSString *path = [[NSBundle mainBundle] pathForResource:@"words" ofType:@"txt"];
	NSString* text = [NSString stringWithContentsOfFile: path 
											   encoding: NSUTF8StringEncoding 
												  error: &theError];
	self.words = [text componentsSeparatedByString: @"\n"];
	
	int arraySize = [words count];
	self.array = [NSMutableArray arrayWithCapacity:arraySize];
	self.randomArray = [NSMutableArray arrayWithCapacity:arraySize];

        //This code fills "array" with index values from 0 to the number of elements in the "words" array.
	for (index = 0; index<arraySize; index++)
		[array addObject: [NSNumber numberWithInt: index]];
	[self resetRandomArray];
	
//	for (index = 0; index<=arraySize; index++)
//		NSLog(@"Random word: %@", [self getRandomWord]);
}
To use it:
-Create a file called words.txt containing a list of words or phrases separated by carriage returns.
-Drag that file into the resources portion of your project, so it will be included in the bundle.
-Call [self buildRandomWordArray] to do the initial setup. That reads the file and populates an array of random indexes.
-Call [self getRandomWord] to get a new random word or phrase. That word/phrase will be deleted from the list and not used again. Once the list is exhausted, the getRandomWord will return nil;
-To start over and get the same list of words in a different order, call [self resetRandomArray];

Im alittle confused, how do I connect the code to a label so it changes the label into random generated text from a list which won't be repeated? I believe I'll have to connect it by a Outlet or?

Last edited by Jimmyl; 01-03-2012 at 11:28 AM.
Jimmyl is offline   Reply With Quote
Old 01-03-2012, 11:47 AM   #8 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default

Quote:
Originally Posted by Jimmyl View Post
Im alittle confused, how do I connect the code to a label so it changes the label into random generated text from a list which won't be repeated? I believe I'll have to connect it by a Outlet or?
It depends on what you want to do and how your app is set up.

When do you want the label to change? On a button click?

If so, you should create an IBAction method that's invoked on the button click and an outlet for your label.

In your action, get the next random string and assign it to the label.
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Old 01-03-2012, 11:52 AM   #9 (permalink)
Registered Member
 
Join Date: Nov 2011
Posts: 7
Jimmyl is on a distinguished road
Default

For the instance I'm using this code in the .m file
Code:
-(IBAction)generateNumbers {
    int getRandomWord = arc4random() % 100;
    switch (getRandomWord) {
        case 0:
            relationlabel.text = @"XXX";
            
       break;

        default:
            break;
    }
}
And this in the .h File

Code:
    IBOutlet UILabel *relationlabel;
Notice that I shorted this code.

Last edited by Jimmyl; 01-03-2012 at 12:00 PM.
Jimmyl is offline   Reply With Quote
Old 02-07-2012, 05:53 AM   #10 (permalink)
Registered Member
 
Join Date: Feb 2012
Posts: 1
denied is on a distinguished road
Default

Hi guys! I need some help with this. I'm not a programmer I'm more of a designer. I'm making a quote app. This seems perfect for what I'm trying to do. I designed the app in Photoshop and I placed the elements in Xcode using Interface Builder.
As I said I designed a simple quote app. Basically is one page, one button. When I push the button the app takes a quote from my .txt file and shows it.
How do I use this code in my app? Can you show me some examples? Where do I start?
Maybe it's a lot to ask. If someone has a few minutes to explain this for me it would be awesome.

Thank You!

*Edit

I got half of it. I did the IBOutlet and the IBAction thing in my .h file. Now I need to figure out the .m file. I inserted the code you gave in there and I have no errors. Any help?

Last edited by denied; 02-07-2012 at 04:55 PM.
denied is offline   Reply With Quote
Old 03-11-2012, 10:11 PM   #11 (permalink)
Registered Member
 
Join Date: Feb 2012
Posts: 45
arkeiquatro is on a distinguished road
Default

can this be applied in an image?
arkeiquatro is offline   Reply With Quote
Old 03-12-2012, 12:39 AM   #12 (permalink)
Registered Member
 
2WeeksToGo's Avatar
 
Join Date: Nov 2011
Posts: 227
2WeeksToGo is on a distinguished road
Default

Genious, thank you duncan.
2WeeksToGo is offline   Reply With Quote
Old 03-12-2012, 02:25 PM   #13 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default

Quote:
Originally Posted by arkeiquatro View Post
can this be applied in an image?
Yes. Adapting it to an array of images is "left as an exercise for the reader."
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Reply

Bookmarks

Tags
generating random text, random text

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 350
10 members and 340 guests
7twenty7, chiataytuday, condor304, Creativ, Domele, dreamdash3, laureix68, LEARN2MAKE, mistergreen2011, Paul Slocum
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,660
Threads: 94,119
Posts: 402,896
Top Poster: BrianSlick (7,990)
Welcome to our newest member, laureix68
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 01:26 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0