Learn Courses My Dashboard

Matching strings exactly in order in Language App

Hello,
I am trying to figure out the correct logic for my language app for this exercise:

https://drive.google.com/file/d/19r1zl88ybZydKNisMFV_CnZmHIRIuPwN/view?usp=sharing

Essentially what happens is the user is forced to type the correct letters in order as the correct answer or the app will not allow the user to type that letter. Each time the user types an incorrect letter, the Hint drop down appears with the correct word.

In the video above the correct phrase is: “Hoy hace calor en Barcelona”

If the user tries to type H-a : then the system will show “H” and then the dropdown will show hint and will not let user continue typing the correct letters until the correct letter is typed - Hoy -

Any hints on how to do this similar logic? I am stumped. I have it now to match correct phrases but it is very demotivating to users that type an entire sentence and get the entire thing wrong because they have one letter wrong!

Please lend your brilliance to a fellow learner :slight_smile:

@toothdoc

Hi Jacob,

I’m not sure if this is what you are getting at but nevertheless the following is offered for your consideration.

Take a look at the following example where the code prevents the user from entering letters that do not match the required string.

struct ContentView: View {
    @State private var yourAnswer = ""
    let correctWord = "Tooth decay"

    var body: some View {
        VStack {
            TextField("Your Answer!", text: $yourAnswer)
                .autocapitalization(.none)
                .disableAutocorrection(true)
                .textFieldStyle(.roundedBorder)
        }
        .padding(.horizontal)
        .onChange(of: yourAnswer) { _ in
            let letterCount = yourAnswer.count
            if yourAnswer.prefix(letterCount) != correctWord.prefix(letterCount) {
                let truncatedString = yourAnswer.prefix(letterCount - 1)
                yourAnswer = String(truncatedString)
            }
        }
    }
}

I’m using the .onChange modifier to react to any change to the answer that the user is typing. It counts the letters entered and uses that value to compare the answer to the correct word by comparing each string up to the length of the characters entered by the user. If they don’t match then the code removes the last entered letter by assigning the correct answer 1 less character than the user entered.

I hope that makes sense.

Hi Chris,

Thanks for the help!!

What is the best way to get that “hint” box to pop down showing a hint when user does type the wrong string?

@toothdoc

I would probably use Boolean which is initially set to false that you set to true when the letter in the string is incorrect and that reveals the hint. I’m guessing that you would want to show the hint for a specific period of time so use a delay to set the boolean back to false so that the hint is hidden.

Something like this maybe.

struct ContentView: View {
    @State private var yourAnswer = ""
    @State private var showingHint = false
    let correctWord = "Tooth decay"


    var body: some View {
        VStack {
            TextField("Your Answer!", text: $yourAnswer)
                .autocapitalization(.none)
                .disableAutocorrection(true)
                .textFieldStyle(.roundedBorder)
            if showingHint {
                Text("Hint - it's bad for you")
            }
        }
        .padding(.horizontal)
        .onChange(of: yourAnswer) { _ in
            let letterCount = yourAnswer.count
            if yourAnswer.prefix(letterCount) != correctWord.prefix(letterCount) {
                let truncatedString = yourAnswer.prefix(letterCount - 1)
                yourAnswer = String(truncatedString)
                //  Show the hint
                withAnimation {
                    showingHint = true
                }
                //  Hide the hint after a delay of 2 seconds.
                DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                    withAnimation {
                        showingHint = false
                    }
                }
            }
        }
    }
}