UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Project 2 Guess The Flag: Challenge 3

Forums > 100 Days of SwiftUI

How do I add a "cancel" option to my "Restart" button?

Hi all, tackling Challenge 3 of Project 2.

Right now I have this:

import SwiftUI

struct ContentView: View {
    @State private var showingScore = false //whether the alert is showing
    @State private var scoreTitle = "" //title to be shown in the alert
    @State private var userScore = 0 //the user's score playing the game
    @State private var gameFinished = false //whether the game is finished at 8 questions
    @State private var totalPlayed = 0 //tracking the number of questions answered

    @State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled()
    @State private var correctAnswer = Int.random(in: 0...2) //decide which country flag should be tapped.

    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: 400).ignoresSafeArea()
            VStack {
                Spacer()
                Text("Guess The Flag").font(.largeTitle.weight(.bold))
                    .foregroundColor(.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]).renderingMode(.original).clipShape(Capsule()).shadow(radius: 5)}
                        }.alert(scoreTitle, isPresented: $showingScore) {
                            Button("Continue", action: askQuestion)
                        } message: {
                            Text("Your socre is \(userScore)")
                        }

                    Button("Restart") {
                        gameFinished = true
                        }
                        .alert("Restarting", isPresented: $gameFinished) {
                            Button("Restart", role: .cancel, action: reset)
                        } message: {
                            Text("Your final score is \(userScore)")
                        }
                    }
                    .frame(maxWidth: .infinity)
                    .padding(.vertical, 20)
                    .background(.regularMaterial)
                    .clipShape(RoundedRectangle(cornerRadius: 20))

                    Spacer()
                    Spacer()
                    Text("Score: \(userScore)")
                        .foregroundColor(.white)
                        .font(.title.bold())
                    Text("Total Guessed: \(totalPlayed)")
                        .foregroundColor(.white)
                        .font(.title.bold())
                    Spacer()
                }
                .padding()
        }

    }

    func flagTapped(_ number: Int) {
        if totalPlayed == (8-1) {
            gameFinished = true
        }

        else {
            if number == correctAnswer {
                scoreTitle = "Correct"
                userScore += 1
            } else {
                scoreTitle = "Wrong! That is the flag of \(countries[number])"
            }
        }

        totalPlayed += 1
        showingScore = true
    }

    //resets the game by shuffling up the countries and picking a new correct answer
    func askQuestion() {
        countries.shuffle()
        correctAnswer = Int.random(in: 0...2)
    }

    func reset() {
        scoreTitle = "You have finished all 8 guesses"
        userScore = 0
        totalPlayed = 0
        countries.shuffle()
    }
}

How do I add a "cancel" click to my "Restart" button?

Besides that, anything I can improve here? Thanks a lot.

Thank you very much.

1      

First get rid of the role: .cancel on your restart button. Then add a cancel button below it.

.alert("Restarting", isPresented: $gameFinished) {
  Button("Restart", action: reset)
  Button("Cancel", role: .cancel) {}
} message: {
  Text("Your final score is \(userScore)")
}

You also might want to consider moving your alerts to the outer ZStack to group them together.

2      

@vtabmow, thanks a lot for your comment. The cancel button worked.

I tried to put both alerts on the ZStack before, but only 1 worked. It seems that one of the alerts will be override if I put them both on the ZStack ?

1      

Did you try this?

import SwiftUI

struct ContentView: View {
    @State private var showingScore = false //whether the alert is showing
    @State private var scoreTitle = "" //title to be shown in the alert
    @State private var userScore = 0 //the user's score playing the game
    @State private var gameFinished = false //whether the game is finished at 8 questions
    @State private var totalPlayed = 0 //tracking the number of questions answered

    @State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled()
    @State private var correctAnswer = Int.random(in: 0...2) //decide which country flag should be tapped.

    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: 400).ignoresSafeArea()
            VStack {
                Spacer()
                Text("Guess The Flag").font(.largeTitle.weight(.bold))
                    .foregroundColor(.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]).renderingMode(.original).clipShape(Capsule()).shadow(radius: 5)}
                    }

                    Button("Restart") {
                        gameFinished = true
                    }

                }
                .frame(maxWidth: .infinity)
                .padding(.vertical, 20)
                .background(.regularMaterial)
                .clipShape(RoundedRectangle(cornerRadius: 20))

                Spacer()
                Spacer()
                Text("Score: \(userScore)")
                    .foregroundColor(.white)
                    .font(.title.bold())
                Text("Total Guessed: \(totalPlayed)")
                    .foregroundColor(.white)
                    .font(.title.bold())
                Spacer()
            }
            .padding()
        }
        .alert(scoreTitle, isPresented: $showingScore) {
            Button("Continue", action: askQuestion)
        } message: {
            Text("Your socre is \(userScore)")
        }
        .alert("Restarting", isPresented: $gameFinished) {
            Button("Restart", action: reset)
            Button("Cancel", role: .cancel) {}
        } message: {
            Text("Your final score is \(userScore)")
        }
    }

    func flagTapped(_ number: Int) {
        if totalPlayed == (8-1) {
            gameFinished = true
        }

        else {
            if number == correctAnswer {
                scoreTitle = "Correct"
                userScore += 1
            } else {
                scoreTitle = "Wrong! That is the flag of \(countries[number])"
            }
        }

        totalPlayed += 1
        showingScore = true
    }

    //resets the game by shuffling up the countries and picking a new correct answer
    func askQuestion() {
        countries.shuffle()
        correctAnswer = Int.random(in: 0...2)
    }

    func reset() {
        scoreTitle = "You have finished all 8 guesses"
        userScore = 0
        totalPlayed = 0
        countries.shuffle()
    }
}

2      

I don't remember if I've tried this, but it helps ! Thank you.

1      

What do you think about my solution?

import SwiftUI

struct ContentView: View { @State private var showingScore = false @State private var showFinalScore = false

@State private var scoreTitle = ""
@State private var scoreTitleFinished = ""

@State private var score = 0

@State private var countries = [ "Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US", "Monaco" ].shuffled()
@State private var correctAnswer = Int.random(in: 0...2)

@State private var selectedFlag = ""
@State private var numberOfQ = 0
var body: some View {
    ZStack{
        // radial gradient
        RadialGradient(stops: [
            .init(color: Color(red: 0.1, green: 0.8, blue: 0.95), location: 0.3),
            .init(color: Color(red: 0.06, green: 0.9, blue: 0.6), location: 0.3)
        ], center: .top, startRadius: 200, endRadius: 700)
        .ignoresSafeArea()

        VStack{
            Spacer()
            Text("Guess the flag?")
                .font(.largeTitle.weight(.bold))
                .foregroundColor(.yellow.opacity(0.9))

            VStack(spacing: 15){
                VStack{
                    Text("Tap the flag off")
                        .foregroundStyle(.secondary)
                        .font(.subheadline.weight(.heavy))
                    Text(countries[correctAnswer])
                        .font(.largeTitle.weight(.semibold))
                }
                ForEach(0..<3){ number in
                    Button {
                    // flag was tapped
                    flagTapped(number)
                    } label: {
                        Image(countries[number])
                            .renderingMode(.original)
                            .clipShape(Capsule())
                            .shadow(radius: 5)
                    }
                    }
            }.frame(maxWidth: .infinity)
                    .padding(.vertical, 20)
                    .background(.thinMaterial)
                    .clipShape(RoundedRectangle(cornerRadius: 20))
                    Spacer()
            Spacer()
                    Text("Score: \(score)")
                        .foregroundColor(.white)
                        .font(.title.bold())
            Spacer()

        }.padding()
    }

    .alert(scoreTitle, isPresented: $showingScore){
        Button("Continue", action: askQuestion)
    } message: {
        if scoreTitle == "Correct" {
            Text("Your score is \(score)")
        }else {
            Text("You are wrong, this is the flag of \(selectedFlag)")
        }
        }

    .alert(scoreTitleFinished, isPresented: $showFinalScore){
        Button("Reset Game", action: resetScore)
    } message:{
        if scoreTitleFinished == "Finished"{
            Text("Your final score is \(score)")
        }}

    }

func flagTapped(_ number: Int){
    selectedFlag = countries[number]
    numberOfQ += 1
    if number == correctAnswer && numberOfQ < 4{
        scoreTitle = "Correct"
        score += 1
        showingScore = true
    } else if number == correctAnswer && numberOfQ == 4{
        scoreTitleFinished = "Finished"
        score += 1
        showFinalScore = true

    } else if numberOfQ == 4{
        scoreTitleFinished = "Finished"
        showFinalScore = true
    } else if numberOfQ < 4{
        scoreTitle = "Wrong"
        showingScore = true
    }
   //

}
// Question
func askQuestion(){
    countries.shuffle()
    correctAnswer = Int.random(in: 0...2)
}

func resetScore(){
    score = 0
    numberOfQ = 0
    countries.shuffle()
    correctAnswer = Int.random(in: 0...2)
}

1      

I'm new in this gathering. I have a few inquiries regarding this gathering. These inquiries are displayed underneath:

My inquiry is about this string. Assuming that you have any data about this string. Kindly statement me and tackle my concern.

1      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.