NEW: Nominations are now open for the 2019 Swift Community Awards! >>

Shuffling an array with GameplayKit: arrayByShufflingObjects(in:)

Many Swift game projects use this Fisher-Yates array shuffle algorithm implemented in Swift by Nate Cook:

extension Array {
    mutating func shuffle() {
        for i in 0..<(count - 1) {
            let j = Int(arc4random_uniform(UInt32(count - i))) + i
            swapAt(i, j)

With GameplayKit there's a specific method you can call that does a similar thing: arrayByShufflingObjects(in:). I say "similar thing" rather than "identical thing" because the GameplayKit returns a new array rather than modifying the original, whereas Nate's version shuffles in place.

For example, if you wanted to blithely ignore the inevitable legalities and set up a lottery in your neighborhood, you could create an array containing the numbers 1 to 49, randomize its order, then pick the first six balls:

let lotteryBalls = [Int](1...49)
let shuffledBalls = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: lotteryBalls)

Note that I'm using the default system randomization because determinism is exactly what you don't want in a lottery. Actually, forget it: if you're going to ignore the law and set up your own lottery, you might as well fix it so you win, right?

One of the advantages of GameplayKit's randomization is that it is truly deterministic, even across devices. This means as long as you tell it where to start, it will produce the same series of random numbers in the future. This is perfect for our evil lottery plan, and it gives me the chance to show you one last thing: seeding GameplayKit's random sources.

When we created our random seeds earlier, we just used this:

let mersenne = GKMersenneTwisterRandomSource()

That creates a new Mersenne Twister random source with a random starting point. But if you want to force a starting point – either because you want to win your lottery or because you want players in a network game to be synchronized – you can create your random source with a specific seed, which is a fixed starting point.

When you use a seed value, your random number generator becomes predictable – you can always predict exactly what “random” numbers get generated. But that's OK, because you can generate the seeds using a separate random number generator, so you're guaranteed uniqueness.

Here's our lottery example rewritten using a fixed seed value of 1001:

let fixedLotteryBalls = [Int](1...49)
let fixedShuffledBalls = GKMersenneTwisterRandomSource(seed: 1001).arrayByShufflingObjects(in: fixedLotteryBalls)

If you run that code now you'll see that the balls are shuffled identically every time. It's a random order, but predictably random if you know what I mean!

SAVE 20% ON iOS CONF SG The largest iOS conference in Southeast Asia is back in Singapore for the 5th time in January 2020, now with two days of workshops plus two days of talks on SwiftUI, Combine, GraphQL, and more! Save a massive 20% on your tickets by clicking on this link.

Buy Testing Swift Buy Practical iOS 12 Buy Pro Swift Buy Swift Design Patterns Buy Swift Coding Challenges Buy Server-Side Swift (Vapor Edition) Buy Server-Side Swift (Kitura Edition) Buy Hacking with macOS Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with Swift Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!