WWDC24 SALE: Save 50% on all my Swift books and bundles! >>

Day 25 Milestone Challenge: Thread 1: breakpoint 1.1 (1)

Forums > 100 Days of SwiftUI

Hi!

I have tried to finish the milestone Challenge.

I am sure there are a lot of ways of improving it. I am totally new with programming (and also english is not my first language) but I am trying hard doing it everyday... I always spend much time than what it is says in 100 days of swiftui, but it doesnt matter. i will finish the course!!! 💪

Anyway, speaking about the challenge...

If i try my result with the canvas it works fine, but if i try it with the simulator, the screen stays white. and in xcode it says "Thread 1: breakpoint 1.1 (1)"

I have searched that problem using google, but i can't find anything...

Could someone please help me?

Also, if I tried to use "func ✌️Tapped" for a Buttomn as I have done with the other two bottons, it shows a lot of errors... if i write it (scissorsTapped) it shows no errors... it happens just with this one, because with 🤚Tapped and 👊Tapped it says nothing...

Also... how can I do to not get a -1 or -2 score ???? just from 0 to 10

Also, if there are things that could be done much better or in a better way, could you please say it to me to try to simplify or improve it?

Really happy that I have been able of doing something... but not sure if it is ok...

thanks...

import SwiftUI

struct ButtonsStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.system(size: 120))
            .background(.blue)
            .clipShape(.capsule)
    }
}

extension View {
    func allButtonsStyle() -> some View {
        modifier(ButtonsStyle())
    }
}

struct WinLoseStyle: View {

    var text: String

    var body: some View {
     Text (text)
            .foregroundStyle(.blue)
            .font(.custom("Chalkboard SE", size: 65) .bold())
    }
}

struct ContentView: View {

    @State private var rockPaperScissors = ["👊", "🤚", "✌️"]
    @State private var shouldWin = ["Win", "Lose"]

    @State private var randomRockPaperScissor = Int.random(in: 0...2)
    @State private var randomShouldWin = Bool.random()
    @State private var showButtonsMessage = true
    @State private var numberOfQuestions = 0
    @State private var round = 1
    @State private var score = 0
    @State private var finalScoreAlert = false

    func 👊Tapped () {

        if randomShouldWin && rockPaperScissors[randomRockPaperScissor] == "🤚"
        { score += 1 } else if randomShouldWin == false && rockPaperScissors[randomRockPaperScissor] == "✌️" {
            score += 1 } else { score -= 1 }

    }

    func 🤚Tapped () {
        if randomShouldWin && rockPaperScissors[randomRockPaperScissor] == "✌️"
        { score += 1 } else if randomShouldWin == false && rockPaperScissors[randomRockPaperScissor] == "👊" {
            score += 1 } else { score -= 1 }
    }

    func scissorsTapped () {
        if randomShouldWin && rockPaperScissors[randomRockPaperScissor] == "👊"
        { score += 1 } else if randomShouldWin == false && rockPaperScissors[randomRockPaperScissor] == "🤚" {
            score += 1 } else { score -= 1 }
    }

    func newRoundAndTotalScore () {
        randomShouldWin.toggle()
        randomRockPaperScissor = Int.random(in: 0...2)
        round += 1

        if round > 10 {
            round = 10
            finalScoreAlert = true
        }
    }

    func newGame () {
        round = 1
        score = 0
        randomShouldWin.toggle()
        randomRockPaperScissor = Int.random(in: 0...2)

    }

        var body: some View {

            ZStack {

                LinearGradient(colors: [.blue, .black], startPoint: .top, endPoint: .bottom)
                    .ignoresSafeArea()

                    VStack {

                        VStack (spacing: 5) {

                            Text ("ROUND: \(round)")
                                .font(.custom("Chalkboard SE", size: 45))

                            Text ("\(rockPaperScissors[randomRockPaperScissor])")
                                .font(.system(size: 95))
                                .background(.pink)
                                .clipShape(.rect(cornerRadius: 30))

                            if randomShouldWin { WinLoseStyle(text: "WIN")

                            } else { WinLoseStyle(text: "LOSE")
                            }
                        }

                        VStack (spacing: 25) {

                            Button ("👊") {
                                👊Tapped()
                                newRoundAndTotalScore()
                            }
                            .allButtonsStyle()

                            Button ("🤚") {
                                🤚Tapped()
                                newRoundAndTotalScore()
                            }
                            .allButtonsStyle()

                            Button ("✌️") {
                                scissorsTapped()
                                newRoundAndTotalScore()
                            }
                            .allButtonsStyle()
                        }

                        .alert("GAME OVER!!!!", isPresented: $finalScoreAlert) {
                            Button ("Try again") {
                              newGame()
                            }
                        } message: {
                            Text ("FINAL SCORE: \(score)")
                        }
                }
            }
    }

}

#Preview {
    ContentView()
}

   

Nice start!

When I review code, I try to find patterns where code is duplicated. Then I ask myself, "Can I make this easier to maintain?"

    Button ("👊") {
        👊Tapped()
        newRoundAndTotalScore()  // 👈🏼 duplicated code
   } 
   .allButtonsStyle()            // 👈🏼 duplicated code

    Button ("🤚") {
       🤚Tapped()
       newRoundAndTotalScore()   // 👈🏼 duplicated code
    }
   .allButtonsStyle()            // 👈🏼 duplicated code

   Button ("✌️") {
        scissorsTapped()
        newRoundAndTotalScore()  // 👈🏼 duplicated code
    }
    .allButtonsStyle()           // 👈🏼 duplicated code

Indeed! The newRoundAndTotalScore()function is duplicated in your view code! Where could you put that code so it's not repeated? How about putting it inside your 🤲🏼Tapped()function?

Next, take a look at these three functions:

 👊Tapped()
 🤚Tapped()
 scissorsTapped()

They all do the same thing!? So can you combine them into ONE function? The only thing different is the input to the function: rock, paper, or scissors. Do you know of a way to pass a changing parameter into a function?

//                   👇🏼Pass in a parameter 
func buttonTapped(_ theButton: String) {
    if     theButton == "👊" { print ("you tapped rock")     }
    elseif theButton == "🤚" { print ("you tapped paper")    }
    else                     { print ("you tapped scissors") }
    // add your scoring code here...
}

Keep Coding

Nice start! Try to simplify your code a bit and return here with your results.

What about the button style? Where could you add that code to affect all your buttons, but not duplicate code?

1      

Kitty writes:

Also, if I tried to use "func ✌️Tapped" for a button as I have done with the other two buttons, it shows a lot of errors...

The error I see that points to the problem is this:

✌️' is not a prefix unary operator

Function names must start with strings. For example the following function name is not allowed:

//       👇🏼 Must start with character, not an integer.
    func 000Tapped() {
        print("you tapped 000")
    }

Both your rock and paper functions start with emoji characters.

    //   👇  Starts with emoji character
    func 👊Tapped () {
        // ....snip.....
    }

    func 🤚Tapped () {
        // ....snip.....
    }

So WHY then is this not allowed ??

    //   👇  Not allowed......what the grep SwiftUI?!?
    func ✌️Tapped () {
        // ....snip.....
    }

Is this a character? ✌️

Emojis are complex characters. For example, you can add skin tone colors to hand and finger emojis. In short an emoji character can be a combination of several characters which are rendered as one character on the screen.

Without diving into the guts of the ✌️emoji, it seems that the compiler sees this emoji differently from rock and paper. You tried to add this to the start of a function name, and the compiler doesn't see the finished emoji peace sign. Instead it's interpreted as a prefix operator to a function named Tapped().

Then it tells you that prefix operators are not allowed in Swift.

Keep Coding

It's not the best error message.

1      

First of all, thanks for your words and sorry for my english...

Sometimes I have the thinking of giving it up, because it is really new for me and I spend quite a few hours doing something that maybe can be done in minutes... ☺️

But I continue here...

and when I do something that seems to work "properly" , it's a great happiness!

I have some more question...

1.- how can the app work using the canvas but not using the simulator? i thought that if it works in one place, it must work in the other one... i thought that the simulator was just to see the app better... what are the differences between using the simulator and using the canvas? why the error doesn't appear with the canvas and it appears with the simulator?

2.- The problem with that breakpoint is solved! thanks a lot... About this, it just said "Breakpoint". Is there a way of knowing what the exact problem is? (in this case that the prefix operators are not allowed...). Can I see it somewhere?

3.- Is it possible to make the font size of the alert bigger ? or bold?

4.- Maybe a silly queastion but... what is the "print" for? in my app, the things that I put with "print" can be seen for the person who tries it? when I use "print" I can see what I have written at the botton of the xcode, but if i try the app, nothing that I have put in "print" appears... I don´t understand what "print" is for...

For example, if in the scissorsTapped function I write print ("Hello world") at the end of the funcion and I try the app, "Hello word" doesnt appear...

5.- When should I use a closure instead of a function?

6.- And when should I use custom modifiers instead of another view ?

I am going to try to change the code to make it easier as you suggested. Thanks or the ideas. If you have more, let me know them please!!!

Thanks a lot for your help and for your words! It may seem silly, but it just have encouraged me to continue with this... 💪😌

   

Kitty continues:

2.- The problem with that breakpoint is solved! thanks a lot... About this, it just said "Breakpoint".

how can the app work using the canvas but not using the simulator?
i thought that if it works in one place, it must work in the other one..

By the way, your English is quite good. But I appreciate that it might be hard for you to express the problem you have.

You used the word "breakpoint" which may lend a clue. Plus you gave this other clue:

Thread 1: breakpoint 1.1 (1)

What this tells me is that you may have accidentially triggered a breakpoint in your code using the debugger!

A breakpoint is a way for you to tell SwiftUI to run your code in a simulator, but when you cross a certain line in your code, you want the program to STOP completely so that you can examine the variables, or look at the screen before continuing.

In fact, when you run in the simulator, the program will STOP on the line that you have selected.

The message (Thread 1: breakpoint 1.1(1)) will be in a GREEN box, yes?

At the start of the line you might see the LINE NUMBER and it will be inside an ARROW box? If this is true, then you have told SwiftUI to STOP running when it gets to this line number.

To clear the breakpoint, select the DEBUG menu in Xcode.
In the Debug menu, find the Breakpoints sub-menu.
In the Breakpoints sub-menu, select Delete All Breakpoints.

Then try to run your application in the simulator again.

More about Breakpoints

@twoStraws has an exceptional video about breakpoints, even if it's five years old!

See -> All about breakpoints

Keep Coding

Please return here and let us know if you cleared your breakpoints!!

   

Kitty ponders the value of print statements:

4.- Maybe a silly question but... what is the "print" for?
in my app, the things that I put with "print" can be seen for the person who tries it?

Debugging

print statements are only for your benefit. Your user should never see them.

At some point in developing an application, you may think your list should be in date order, but for some reason the list is in alphabetical order. This makes you MAD!

Simple Example

So, to help you figure out the problem, you might add print(sortOrder) to your button, and add it to your Update() function, and also add it to your PressOK() button. Add a few print statements into your program.

Then when your run your program in the simulator, try pressing the Update() button. Press the OK button. Each time you press, or tap, or drag, your program will print the value of sortOrder in the debug screen. This is ONLY to help you see where your variable changes. Your user should never see this message.

This will help you find the error in your logic. Somewhere you forgot to change the value of sortOrder!

Keep Coding!

Please remember, the only silly questions are the ones your boss and bus drivers ask you!

   

I have changed several things...

What about it now? Would you find somehting I could change to improve it?

I would like to get a diferent emoji when clicking a button, depending on the answer. If the answer is right, I would like to show 🤩 instead of the image that the button has. If it is wrong , 😱

I have tried several things, but nothing works...

Some help to get it ?

import SwiftUI

struct ButtonsStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.system(size: 120))
            .background(.blue)
            .clipShape(.capsule)
            .shadow(color: .yellow, radius: 15)
    }
}

extension View {
    func allButtonsStyle() -> some View {
        modifier(ButtonsStyle())
    }
}

struct WinLoseStyle: View {

    var text: String

    var body: some View {
     Text (text)
            .foregroundStyle(.blue)
            .font(.custom("Chalkboard SE", size: 65) .bold())
    }
}

struct ContentView: View {

    @State private var rockPaperScissors = ["👊", "🤚", "✌️"]
    @State private var shouldWin = ["Win", "Lose"]

    @State private var randomRockPaperScissor = Int.random(in: 0...2)
    @State private var randomShouldWin = Bool.random()
    @State private var showButtonsMessage = true
    @State private var round = 1
    @State private var score = 0
    @State private var finalScoreAlert = false
    @State private var changeButtonImage = ["🤩", "😱"]

    func buttonTapped(_ theButton: String) {
       if theButton == "👊" {
           if randomShouldWin && rockPaperScissors[randomRockPaperScissor] == "🤚"
           {
               score += 1

           } else if randomShouldWin == false && rockPaperScissors[randomRockPaperScissor] == "✌️" {
               score += 1
           } else { score -= 1
           }
         }

        else if theButton == "🤚" { 
            if randomShouldWin && rockPaperScissors[randomRockPaperScissor] == "✌️"
            { score += 1 } else if randomShouldWin == false && rockPaperScissors[randomRockPaperScissor] == "👊" {
                score += 1 } else { score -= 1 }    }
       else  {
           if randomShouldWin && rockPaperScissors[randomRockPaperScissor] == "👊"
           { score += 1 } else if randomShouldWin == false && rockPaperScissors[randomRockPaperScissor] == "🤚" {
               score += 1 } else { score -= 1 } }

        if score < 0 { score = 0}

        newRoundAndTotalScore()
    }

    func newRoundAndTotalScore () {
        randomShouldWin.toggle()
        randomRockPaperScissor = Int.random(in: 0...2)
        round += 1

        if round > 10 {
            round = 10
            finalScoreAlert = true
        }
    }

    func newGame () {
        round = 1
        score = 0
        randomShouldWin.toggle()
        randomRockPaperScissor = Int.random(in: 0...2)

    }

        var body: some View {

            ZStack {

                LinearGradient(colors: [.blue, .black], startPoint: .top, endPoint: .bottom)
                    .ignoresSafeArea()

                    VStack (spacing: 20)  {

                        VStack {

                            Text ("ROUND: \(round)")
                                .font(.custom("Chalkboard SE", size: 45))
                                .foregroundStyle(.black)

                            Text ("\(rockPaperScissors[randomRockPaperScissor])")
                                .font(.system(size: 95))
                                .background(.pink)
                                .clipShape(.rect(cornerRadius: 30))
                                .shadow(color: .black, radius: 20)

                            if randomShouldWin { WinLoseStyle(text: "WIN")

                            } else { WinLoseStyle(text: "LOSE")
                            }
                        }

                        VStack (spacing: 25) {

                            Button ("👊") {
                                buttonTapped("👊")
                            }
                            .allButtonsStyle()

                            Button ("🤚") {
                                buttonTapped("🤚")
                            }
                            .allButtonsStyle()

                            Button ("✌️") {
                                buttonTapped("✌️")
                            }
                            .allButtonsStyle()
                        }

                        .alert("GAME OVER!!!!", isPresented: $finalScoreAlert) {
                            Button ("Try again"){
                              newGame()
                            }
                        } message: {
                            Text ("FINAL SCORE: \(score)")
                        }
                }
            }
    }

}

#Preview {
    ContentView()
}

   

any suggestion of how to get another emoji when pressing a bottons depending on the answer (if it is right or not), please?

   

Hello Kitty2018,

Since your app doesn't pause after the user has pressed the button, it would be impossible for the user to see your changed emoji in time with the current approach. I would recommend that you find a way for the app to pause until the user is ready for the next round. Tip: You can do this using alerts.

   

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Reply to this topic…

You need to create an account or log in to reply.

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.