问题
I'm currently making an app that plays a song. I wanted to play a random song each a button is clicked. I currently have :
-(IBAction)currentMusic:(id)sender {
NSLog(@"Random Music");
int MusicRandom = arc4random_uniform(2);
switch (MusicRandom) {
case 0:
[audioPlayerN stop];
[audioPlayer play];
break;
case 1:
[audioPlayer stop];
[audioPlayerN play];
break;
but I already tried :
- (IBAction)randomMusic:(id)sender {
NSLog(@"Random Music");
NSMutableArray * numberWithSet = [[NSMutableArray alloc]initWithCapacity:3];
int randomnumber = (arc4random() % 2)+1;
while ([numberWithSet containsObject:[NSNumber numberWithInt:randomnumber]])
{
NSLog(@"Yes, they are the same");
randomnumber = (arc4random() % 2)+1;
}
[numberWithSet addObject:[NSNumber numberWithInt:randomnumber]];
NSLog(@"numberWithSet : %@ \n\n",numberWithSet);
switch (randomnumber) {
case 1:
[audioPlayerN stop];
[audioPlayer play];
NSLog(@"1");
break;
case 2:
[audioPlayer stop];
[audioPlayerN play];
NSLog(@"2");
break;
default:
break;
}
}
And all of them work, the thing is, even though I will add more songs, they repeat. I wanted a random code that would not repeat. Like plays song 1, song 2, song 3, song 4 and song 5 randomly, and when plays all of them restarts. Like a Loop. But my current code is like song 1, song 1, song 2, song 1, song 2, and so on...Is there any way to not repeat the songs except for when all of them have been played? Thank you very much.
回答1:
You want to generate a random permutation.
Option 1
Hat tip @Alexander for this simpler approach...
if(![songsToPlay count])
[songsToPlay addObjectsFromArray:songList];
int index = arc4random_uniform([songsToPlay count]);
playSong(songsToPlay[index]);
[songsToPlay removeObjectAtIndex:index];
Quick explanation:
NSMutableArray *songsToPlay
: Stores the list of songs that haven't been played yet this round. Contents could be of type:NSString
, storing a filenameNSNumber
, storing a song index
NSArray *songList
: Stores the list of all songs you want to play. Contents should be of same type assongsToPlay
. Could also be aNSMutableArray
.playSong(id songToPlay)
: Stops any current songs and playssongToPlay
. You'll need to write this function, since it depends on your implementation.
Option 2
Using Knuth shuffles is another approach:
unsigned permute(unsigned permutation[], unsigned n)
{
unsigned i;
for (i = 0; i < n; i++) {
unsigned j = arc4random_uniform(i);
permutation[i] = permutation[j];
permutation[j] = i;
}
}
Then call the function every time you want to shuffle the songs:
int permutation[NUM_SONGS];
// I'm using a while loop just to demonstrate the idea.
// You'll need to adapt the code to track where you are
// in the permutation between button presses.
while(true) {
for(int i = 0; i < NUM_SONGS; ++i)
permutation[i] = i;
permute(permutation, NUM_SONGS);
for(int i = 0; i < NUM_SONGS; ++i) {
int songNum = permutation[i];
playSong(songNum);
}
waitForButtonPress();
}
回答2:
First of all, you're only hearing 2 songs because your randomnumber
generation is limited to only 2 values.
For the other problem you can create a mutable array with randomly placed tracks and remove each played element. When the count reaches 0 just start playing tracks in random order.
来源:https://stackoverflow.com/questions/19768714/random-integer-loop