How To Make a Letter / Word Game with UIKit and Swift: Part 1/3

This 3-part tutorial series will guide you through the process of building a board game for the iPad in Swift, where you create words with letters. You’ll also learn about best practices for creating solid, modular iOS apps. And as a bonus, you’ll get a crash course in audio-visual effects with UIKit! By Caroline Begbie.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 4 of this article. Click here to view the first page.

5) Dealing the Tiles on the Screen

Switch back to GameController.swift – your dealRandomAnagram() method already loads the data you need, but it still does not do much. Time to fix that!

Add the following property to the GameController class:

private var tiles = [TileView]()

This is an array to hold the TileView objects that will display the tiles at the bottom of the screen. These tiles contain the initial phrase of the anagram.

Later you will also create an array to hold the target views that will display the spaces at the top of the screen where the player has to drag the tiles to form the second phrase of the anagram.

Before you continue, you also need a constant for the space between the tiles. Jump over to Config.swift and add the following:

let TileMargin: CGFloat = 20.0

Some of you might already be protesting, “Can’t I just use 20 where I need it and be done?” It’s a good point, but there is a reason for predefining in the config file.

My experience shows that you will have to tweak any numbers you have in your code when it comes time to fine-tune the gameplay. So best practice is to externalize all numbers to a config file and give those variables meaningful names. This will pay off especially well if you are working in a team and you need to hand the game to a game designer for fine-tuning. :]

OK, back in GameController.swift, get ready to add some code to the end of dealRandomAnagram(). You have the number of characters in both phrases, so it’s easy to calculate what size tiles you need. Add this code at the end of the method:

//calculate the tile size
let tileSide = ceil(ScreenWidth * 0.9 / CGFloat(max(anagram1length, anagram2length))) - TileMargin

You take 90% of the width of the screen and divide it by the number of characters. You use the length of the longer phrase – remember, the number of characters can vary! You decrease the result by TileMargin to account for spacing between tiles.

Next find the initial x position of the first tile. It will depend on the length of the word and the tile size you just calculated. Once again, add the following at the end of dealRandomAnagram():

//get the left margin for first tile
var xOffset = (ScreenWidth - CGFloat(max(anagram1length, anagram2length)) * (tileSide + TileMargin)) / 2.0
    
//adjust for tile center (instead of the tile's origin)
xOffset += tileSide / 2.0

You take the screen width, subtract the calculated width of the word tiles and find where the first tile should be positioned on the screen. Wouldn’t it be nice if there were a simpler way to “center” the tiles!

LeSighHisLeg

Continuing in the same method, add the following code to display the tiles:

//1 initialize tile list
tiles = []
    
//2 create tiles
for (index, letter) in enumerate(anagram1) {
  //3
  if letter != " " {
    let tile = TileView(letter: letter, sideLength: tileSide)
    tile.center = CGPointMake(xOffset + CGFloat(index)*(tileSide + TileMargin), ScreenHeight/4*3)
        
    //4
    gameView.addSubview(tile)
    tiles.append(tile)
  }
}

Here’s what’s happening above:

  1. First you initialize a fresh copy of your tiles array. It’s important to start with an empty array here because this function will be called multiple times during a run of your app. Since spaces are skipped, if you didn’t clear out the array then there might be old tiles left over from a previous phrase where there should be spaces.
  2. You then loop through the phrase. You will need both the letter from the phrase and the position of the letter, so use enumerate which returns a tuple of the index + the value.
  3. You check each letter and if it is not a space, it’s a go! You create a new tile and position it using xOffset, tileSide and TileMargin. Here you are calculating the position based on that letter’s position in the phrase, which is represented by index. So if index is 5, this math will figure out how much space five tiles take up and add the new tile to the right of that space.
    You position the tiles vertically at 3/4ths of the screen height.
  4. Finally, you add the tile to the gameView and to the tiles array. The first actually shows the tile on the screen, while the latter helps you loop faster over the tiles later on.

Alrighty! Time for the final touch – you need to load the level data and call dealRandomAnagram(). Switch to ViewController.swift and add these two lines at the end of viewDidLoad():

controller.level = level1
controller.dealRandomAnagram()

Remember that you already have a Level object, so you just pass it on to your GameController and call dealRandomAnagram().

It’s been a long time coming, but build and run to check out the result! Your app should look something like this:

Empty Tiles

Awesome, it works! It’s alive!!!

Note: Your view probably won’t look exactly like this because the app is choosing a random anagram each time it runs. Run it a few times to see how the app sizes the tiles differently for different phrases. The console output will show you the phrases used.

You are closing in on the finish line for the first part of this tutorial series!

6) Add the Letters

Switch to TileView.swift. This is where you’re going to add letters to those tiles. Find init(letter:sideLength:) and add the following code to the end:

//add a letter on top
let letterLabel = UILabel(frame: self.bounds)
letterLabel.textAlignment = NSTextAlignment.Center
letterLabel.textColor = UIColor.whiteColor()
letterLabel.backgroundColor = UIColor.clearColor()
letterLabel.text = String(letter).uppercaseString
letterLabel.font = UIFont(name: "Verdana-Bold", size: 78.0*scale)
self.addSubview(letterLabel)

The above code creates a new UILabel and adds it to the tile view. Because you want the letter to be as easy to read as possible, you create the label to be as large as the tile itself. You then align the letter to show up in the center of the tile.

You ensure the letter is uppercase by setting the label text with String(letter).uppercaseString. Using capital letters will ease the game play, as they are easier to recognize, specifically by children. Always think about your game’s target audience!

Finally you reuse the scale factor you calculated earlier. For the full-size tile a Verdana font with a size of 78 pts fits well, but for other sizes you need to scale the font size accordingly.

Build and run the project. As I said, you’re now moving fast towards your goal. Good job! :]

Tiles with Letters

Once again, your screen probably won’t look just like this one. But that just means your game controller is doing what’s it’s supposed to do and dealing a random anagram. Nice!

Have another look at the image above. Right now the tiles look like they were put on the board by a pedantic robot: they are perfectly aligned. Now comes the time to add a pinch of randomization!

Contributors

Over 300 content creators. Join our team.