NEW! Master Swift design patterns with my latest book! >>

< Previous: Making the basic game work: UIButton and CALayer   Next: From outlets to actions: IBAction and string interpolation >

Guess which flag: random numbers

Our current code chooses the first three items in the countries array, and places them into the three buttons on our view controller. This is fine to begin with, but really we need to choose random countries each time. There are two ways of doing this:

  1. Pick three random numbers, and use those to read the flags from the array.
  2. Shuffle up the order of the array, then pick the first three items.

Both approaches are valid, but the former takes a little more work because we need to ensure that all three numbers are different – this game would be even less fun if all three flags were the French flag!

The second approach is easy to do, but there's a catch: we're going to use an iOS framework called GameplayKit. You see, randomness is a complicated thing, and it's easy to write some code that you think randomizes an array perfectly when actually it generates a predictable sequence. As a result, we're going to use an Apple framework called GameplayKit that does all this hard work for us.

Now, you might think, "why would I want to use something called GameplayKit for apps?" But the simple answer is: because it's there, because all devices have it built right in, and because it's available in all your projects, whether games or apps. GameplayKit can do a lot more than just shuffling an array, but we'll get on to that much later.

For now, look at the top of your ViewController.swift file and you'll find a line of code that says import UIKit. Just before that, add this new line:

import GameplayKit

With that done, we can start using the functionality given to us by GameplayKit. At the start of the askQuestion() method, just before you call the first setImage() method, add this line of code:

countries = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: countries) as! [String]

That will automatically randomize the order of the countries in the array, meaning that countries[0], countries[1] and countries[2] will refer to different flags each time the askQuestion() method is called. To try it out, press Cmd+R to run your program a few times to see different flags each time.

The next step is to track which answer should be the correct one, and to do that we're going to create a new property for our view controller called correctAnswer. Put this near the top, just above var score = 0:

var correctAnswer = 0

This gives us a new integer property that will store whether it's flag 0, 1 or 2 that holds the correct answer.

To choose which should be the right answer requires using GameplayKit again, because we need to choose a random number for the correct answer. GameplayKit has a special method for this called nextInt(upperBound:), which lets you specify a number as your "upper bound" – i.e., the cap for the numbers to generate. GameplayKit will then return a number between 0 and one less than your upper bound, so if you want a number that could be 0, 1 or 2 you specify an upper bound of 3.

Putting all this together, to generate a random number between 0 and 2 inclusive you need to put this line just below the three setImage() calls in askQuestion():

correctAnswer = GKRandomSource.sharedRandom().nextInt(upperBound: 3)

Now that we have the correct answer, we just need to put its text into the navigation bar. This can be done by using the title property of our view controller, but we need to add one more thing: we don't want to write "france" or "uk" in the navigation bar, because it looks ugly. We could capitalize the first letter, and that would work great for France, Germany, and so on, but it would look poor for “Us” and “Uk”, which should be “US” and “UK”.

The solution here is simple: uppercase the entire string. This is done using the uppercased() method of any string, so all we need to do is read the string out from the countries array at the position of correctAnswer, then uppercase it. Add this to the end of the askQuestion() method, just after correctAnswer is set:

title = countries[correctAnswer].uppercased()

With that done, you can run the game and it's now almost playable: you'll get three different flags each time, and the flag the player needs to tap on will have its name shown at the top.

Your game so far: three different flags, with one correct answer shown at the top.

Of course, there's one piece missing: the user can tap on the flag buttons, but they don't actually do anything. Let's fix that…

Get my latest video for free

Learn about value types, functional programming, and protocol-oriented programming in this new video – it's free!

< Previous: Making the basic game work: UIButton and CALayer   Next: From outlets to actions: IBAction and string interpolation >
Buy Practical iOS 12 Buy Pro Swift Buy Swift Design Patterns Buy Practical iOS 11 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 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 me know!

Average rating: 5.0/5

Click here to visit the Hacking with Swift store >>