4

I have a NSMutableArray called putNumberUsed. It contains the following objects @"blah1,@"blah2",@"blah3",@"blah4". I want to shuffle these objects randomly so for example if I chose:

 [putNumberUsed objectAtIndex:0] 

it would give me anything but "blah1". How would I go about doing this? The following is the code I used thus far:

NSMutableArray *putNumbersUsed = [[NSMutableArray alloc] arrayWithObjects:@"blah1",@"blah2",@"blah3",@"blah4",nil];
Cœur
  • 37,241
  • 25
  • 195
  • 267
Alex G
  • 2,299
  • 5
  • 37
  • 54
  • possible duplicate - http://stackoverflow.com/questions/5659718/shuffling-an-array-in-objective-c – Peter Kelly Jun 27 '12 at 10:23
  • possible duplicate of [What's the Best Way to Shuffle an NSMutableArray?](http://stackoverflow.com/questions/56648/whats-the-best-way-to-shuffle-an-nsmutablearray) – David Rönnqvist Jun 27 '12 at 10:45

6 Answers6

9

I think, You can write a loop for that. Please check the following code,

for (int i = 0; i < putNumberUsed.count; i++) {
    int randomInt1 = arc4random() % [putNumberUsed count];
    int randomInt2 = arc4random() % [putNumberUsed count];
    [putNumberUsed exchangeObjectAtIndex:randomInt1 withObjectAtIndex:randomInt2];
}

I this this may be useful to you.

Rajesh
  • 483
  • 2
  • 8
5

Here is a shuffling solution with all positions forced to change when count > 1.

Add a category like NSMutableArray+Shuffle.m:

@implementation NSMutableArray (Shuffle)
// Fisher-Yates shuffle variation with all positions forced to change
- (void)unstableShuffle
{
    for (NSInteger i = self.count - 1; i > 0; i--)
        // note: we use u_int32_t because `arc4random_uniform` doesn't support int64
        [self exchangeObjectAtIndex:i withObjectAtIndex:arc4random_uniform((u_int32_t)i)];
}
@end

Then you can shuffle like:

[putNumbersUsed unstableShuffle];

This solution:

A Swift 3.2 and Swift 4 equivalent is:

extension Array {
    mutating func unstableShuffle() {
        for i in stride(from: count - 1, to: 0, by: -1) {
            swapAt(i, Int(arc4random_uniform(UInt32(i))))
        }
    }
}

A Swift 3.0 and 3.1 equivalent is:

extension Array {
    mutating func unstableShuffle() {
        for i in stride(from: count - 1, to: 0, by: -1) {
            swap(&self[i], &self[Int(arc4random_uniform(UInt32(i)))])
        }
    }
}

Note: An algorithm for regular shuffling (where a result with same positions being possible) is also available

Cœur
  • 37,241
  • 25
  • 195
  • 267
3

From iOS 10.x++ new concept of shuffle array is given by Apple,

You need to import the framework :

ObjeC

#import <GameplayKit/GameplayKit.h>

NSArray *shuffledArray = [yourArray shuffledArray];

Swift

import GameplayKit

let shuffledArray = yourArray.shuffled()
Mukesh Lokare
  • 2,159
  • 26
  • 38
  • This doesn't answer the question: those methods may return an unmodified array, which is not what is being asked. – Cœur Jul 18 '19 at 16:31
2

You can shuffle the object by using the following line of code,

[putNumbersUsed exchangeObjectAtIndex:3 withObjectAtIndex:0];

I think this may useful to you.

Rajesh
  • 483
  • 2
  • 8
  • 2
    Thank you Rajesh I was looking for something like this but isn't this only exchanging object at 3 with 0? What if I wanted to do this randomly with all. Thanks! – Alex G Jun 27 '12 at 10:32
  • Yes, you're right. But I think Rajesh wanted to guide you to the right direction. I posted a very similiar code in my answer, so have a look. – Fabio Poloni Jun 27 '12 at 10:52
1

generate a random number for index

int randomInt = arc4random() % [putNumberUsed count];
[putNumberUsed objectAtIndex:randomInt];
janusfidel
  • 8,036
  • 4
  • 30
  • 53
0

Use this:

for (int i = 0; i < [putNumberUsed count]; i++) {
    int random = arc4random() % [putNumberUsed count]; 
    [putNumbersUsed exchangeObjectAtIndex:random withObjectAtIndex:i]; 
}
Fabio Poloni
  • 8,219
  • 5
  • 44
  • 74