When we last left off with this project, we printed out each row on the screen, but we want to process each emoji that composes the array.
First, remove the player from the maze and replace it with an orange square. You can just copy and paste from another square. Keep the carrot as is. We will treat it as a special space. Now we just have the maze data.
Next, we need a function to generate the actual row. First we define the function. We must place this inside the ContentView. Add the following:
func generateRow(rowData: [String], drawPlayer: Bool) -> Text {
}
This defines a function called generateRow and it passes in the actual row that is an array of emoji. Next, you signify whether to draw the player in the row. Finally, the function returns a Text view.
Next we define a string to hold the generated row.
var textString = ""
Now we loop through each element in the rowData.
for colIndex in 0...rowData.count - 1 {
}
At this point, we can add each element to the text string.
textString += rowData[colIndex]
Finally, we return the text.
return Text(textString)
Okay, this doesn’t do things much differently from calling the joined() method on the array. So why put it in a method? This is so you can add the player. Update the following:
if colIndex == playerCol && drawPlayer {
textString += "🐰"
} else {
textString += col[colIndex]
}
In this case, if the player matches the current column and you set the drawPlayer to true, then the player is drawn instead of the maze emoji. This causes the player to move.
Finally, call this function in your SwiftUI code.
generateRow(rowData: data[rowIndex], drawPlayer: playerRow == rowIndex)
This looks great. Now with your app running, tap the buttons. You’ll see player move across the play area. Unfortunately, the player does not obey the limits of the maze. You can fix. Add the following method:
func isValidMove(row: Int, col: Int) -> Bool {
if data[row][col] == "🟧" {
return true
}
return false
}
This checks to see if a space is yellow square. Otherwise, if it is, the player can move into it. You actually simplify this:
func isValidMove(row: Int, col: Int) -> Bool {
return data[row][col] == "🟧"
}
If the emoji is a yellow square, the function returns true otherwise, it returns false. Now update the button tapping code to the following:
Button {
if playerRow > 0 {
if (isValidMove(row: playerRow - 1, col: playerCol)) {
playerRow -= 1
}
}
} label: {
Text("⬆️").font(.system(size: 50))
}
Button {
if playerRow < data.count - 1 {
if (isValidMove(row: playerRow + 1, col: playerCol)) {
playerRow += 1
}
}
} label: {
Text("⬇️").font(.system(size: 50))
}
Button {
if playerCol > 0 {
if (isValidMove(row: playerRow, col: playerCol - 1)) {
playerCol -= 1
}
}
} label: {
Text("⬅️").font(.system(size: 50))
}
Button {
if playerCol < data[0].count - 1 {
if (isValidMove(row: playerRow, col: playerCol + 1)) {
playerCol += 1
}
}
} label: {
Text("➡️").font(.system(size: 50))
}
Now when you tap your buttons, you’ll be able to move around on the yellow path. The code prevents you from crossing over a hedge. Let’s just add some final touches. Add the following variables:
@State var wonGame = false
var carrotRow = 10
var carrotCol = 3
The state variable lets SwiftUI know when the player wins the game. We’ll present an alert to the user. The carrotRow and and carrotCol let’s us know when the user lands on the carrot space.
Let’s update the isValidMove() method so the player can step on it.
if (data[row][col] == "🟧" || data[row][col] == "🥕") {
Now add this code to each button tap. This lets us know when the user has reached the carrot.
wonGame = playerRow == carrotRow && playerCol == carrotCol
Finally, we’ll present an alert to the user should the player win the game. The alert is just another modifier. It will use the wonGame variable to trigger it. Add the following:
.alert("Congrats! You won!", isPresented: $wonGame) {
Button("OK") { }
}
First you provide a message to the user and the isPresented property displays the alert. The dollar sign means we are accessing the projected value. This allows the alert to change the value once the alert is closed. This means, once the alert goes away, the value of wonGame is false.
The Button triggers the close. It doesn’t do anything, but you can add additional code as well.
Now start the game and get to the end. You’ll get a message. You won! Congratulations!