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

WordScramble app

Forums > 100 Days of SwiftUI

I've just completed the Word Scramble game, everything seemed to run smoothly however the rootWord (if you don't remember, the word users spell from) does not change from aardvark, which is the first word in the start.tx. I've had a look over the code a number of times, first looking at it logically then repeating the exercise. The code seems right and the start.tx file hasn't been corrupted, but I don't appear to have found a solution. Is anyone able to spot any errors in the code that are causing this issue?

struct ContentView: View {
    @State private var usedWords = [String]()
    @State private var rootWord = ""
    @State private var newWord = ""
    @State private var errorTitle = ""
    @State private var errorMessage = ""
    @State private var showingError = false

    var body: some View {
        NavigationView {
            VStack {
                TextField("Enter your word", text: $newWord, onCommit: addNewWord)

                List(usedWords, id: \.self) {
                    Image(systemName: "\($0.count).circle")

            .onAppear(perform: startGame)
            .alert(isPresented: $showingError) {
                Alert(title: Text(errorTitle), message: Text(errorMessage), dismissButton: .default(Text("OK")))

    func addNewWord() {
        //lower cas and trim the word, to make sure we don't add duplicate words with case diffrences
        let answer = newWord.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)

        // exit if the remaining string is empty
        guard answer.count > 0 else {

        guard isOriginal(word: answer) else {
            wordError(title: "Word used already", message: "Be more original!")

        guard isPossible(word: answer) else {
            wordError(title: "Word not recognized", message: "You can't just make them up, you know!")

        guard isReal(word: answer) else {
            wordError(title: "Word not possible", message: "That isn't a real world")

        usedWords.insert(answer, at: 0)
        newWord = ""


    func startGame() {
        // 1. Find the URL for start.txt in our app bundle
        if let startWordsURL = Bundle.main.url(forResource: "start", withExtension: "txt") {
            // 2. Load start.txt into a string
            if let startWords = try? String(contentsOf: startWordsURL) {
                // 3. Split the string up into an array of strings, splitting on line breaks
                let allWords = startWords.components(separatedBy: "\n)")

                // 4. Pick one random word, or use "silkworm" as a sensible default
                rootWord = allWords.randomElement() ?? "silkworm"

                // If we are here everything has worked, so we can exit

        //If we're here then there was a problem -  trigger a crash and report the error
        fatalError("Could not load start.txt from bundle.")

    func isOriginal(word: String) -> Bool {

    func isPossible(word: String) -> Bool {
        var tempWord = rootWord

        for letter in word {
            if let pos = tempWord.firstIndex(of: letter) {
                tempWord.remove(at: pos)
        } else {
            return false
    return true

    func isReal(word: String) -> Bool {
        let checker = UITextChecker()
        let range = NSRange(location: 0, length: word.utf16.count)
        let misspelledRange = checker.rangeOfMisspelledWord(in: word, range: range, startingAt: 0, wrap: false, language: "en")

        return misspelledRange.location == NSNotFound

    func wordError(title: String, message: String) {
        errorTitle = title
        errorMessage = message
        showingError = true



Hi There,

So it's always showing 'aardvark', the first word in start.txt. First thought I had, was that your randomElement statement wasn't working correctly. That looked ok to me. Your line to separate the word list into an array looks correct to me, too. I'd add a print statement after that line, to print out the length of allWords. My guess is allWords just contains the one word, aardvark! If that's the case, and start.txt does indeed contain all the words, does the file actually not contain newlines but contains special characters instead? You can tell by opening up the file in vi, going to escape mode, and typing :set list.


You have a parenthesis in this line just after the n:

let allWords = startWords.components(separatedBy: "\n)")

Notice after the n there should be nothing:

let allWords = startWords.components(separatedBy: "\n")


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.