Hello,
I'm completely new to programming and have never done this before.
After doing project 2 of 100 days of SwiftUI, I thought I would try to add some of my own code before moving on to the next project. I managed to add a player name, but the app crashes after question 9 of the game when I play it again & I am not sure why.
I see a "Thread 1: fatal error: index out of range" error on line 53: Image(countries[number]).
Why does this error occur during a new game?
Here is my code:
static let allCountries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Monaco", "Nigeria", "Poland", "Spain", "UK", "Ukraine", "US"]
@State private var countries = allCountries.shuffled()
@State private var correctAnswer = Int.random(in: 0...2)
@State private var nameGiven = true
@State private var playerName = ""
@State private var showingResults = false
@State private var showingScore = false
@State private var scoreTitle = ""
@State private var score = 0
@State private var QuestionCounter = 1
var body: some View {
ZStack {
RadialGradient(stops: [
.init(color: Color(red: 0.1, green: 0.2, blue: 0.45), location: 0.3),
.init(color: Color(red: 0.76, green: 0.15, blue: 0.26), location: 0.3)
], center: .top, startRadius: 200, endRadius: 700)
.ignoresSafeArea()
VStack {
Spacer()
Text("Guess the flag")
.font(.largeTitle.weight(.bold))
.foregroundStyle(.white)
VStack (spacing: 15) {
VStack {
Text("Tap the flag of")
.foregroundStyle(.secondary)
.font(.subheadline.weight(.heavy))
Text(countries[correctAnswer])
.font(.largeTitle.weight(.semibold))
}
ForEach(0..<3){ number in
Button {
flagTapped(number)
} label: {
Image(countries[number])
.clipShape(.capsule)
.shadow(radius: 5)
}
}
}
.frame(maxWidth: .infinity)
.padding(.vertical, 20)
.background(.regularMaterial)
.clipShape(.rect(cornerRadius: 20))
Spacer()
Spacer()
Text ("\(playerName)'s Score: \(score) / 10")
.foregroundStyle(.white)
.font(.title.bold())
}
}
.alert(scoreTitle, isPresented: $showingScore) {
Button("Continue", action: askQuestion)
} message: {
Text("Your score is \(score) / 10")
}
.alert("Game over!", isPresented: $showingResults) {
Button("Finish", action: restartGame)
} message: {
Text("Your final score was \(score) / 10")
}
.alert("Enter your name", isPresented: $nameGiven) {
TextField("Name", text: $playerName)
Text("Play")
}
}
func flagTapped(_ number: Int) {
if number == correctAnswer {
scoreTitle = "Correct, \(playerName)!"
score += 1
} else {
let needsThe = ["UK", "US"]
let theirAnswer = countries[number]
if needsThe.contains(theirAnswer) {
scoreTitle = "Wrong, \(playerName)! that's the flag of the \(theirAnswer)"
} else {
scoreTitle = "Wrong, \(playerName)! That's the flag of \(theirAnswer)"
}
}
if QuestionCounter == 10 {
showingResults = true
} else {
showingScore = true
}
}
func askQuestion() {
countries.remove(at: correctAnswer)
countries.shuffle()
correctAnswer = Int.random(in: 0...2)
QuestionCounter += 1
}
func restartGame() {
QuestionCounter = 0
score = 0
countries = Self.allCountries
askQuestion()
askForPlayerName()
}
func askForPlayerName() {
if score == 0 {
nameGiven = true
playerName = ""
} else {
nameGiven = false
}
}
}
Thank you