SwiftUI Slots Game Error

As I was working on making the slots game through the tutorial, everything seemed to be working perfectly fine. Unfortunately, as soon as I finished the challenge and ran the final program, multiple problems began to show up. Firstly, the game seems to just start with the apples and the Max Spin button seems to only randomize the center row. Along with that, since the apples are the only things showing up once I immediately run the program, I immediately get a match and it only further randomizes the center row. Could anyone please analyze the following code for the ContentView.swift (the CardView.swift seems to be fine) and find what the exact problem is? I believe that I must have messed up the format, yet the problem still persists. Here is the code:
import SwiftUI

struct ContentView: View {

@State private var symbols = ["apple", "star", "cherry" ]
@State private var numbers = Array(repeating: 0, count: 9)
@State private var backgrounds = Array(repeating: Color.white, count: 9)
@State private var credits = 1000
private var betAmount = 5

var body: some View {
    
    ZStack {
        //Background
        Rectangle().foregroundColor(Color( red: 200/255, green: 143/255, blue: 32/255))
            .edgesIgnoringSafeArea(.all)
        
        Rectangle().foregroundColor(Color(red: 228/255, green: 195/255, blue: 76/255)).rotationEffect(Angle(degrees: 45)).edgesIgnoringSafeArea(.all)
        
        VStack {
            
            Spacer()
            
            //Title
            HStack {
                Image(systemName: "star.fill")
                    .foregroundColor(.yellow)
                
                Text("SwiftUI Slots")
                    .bold()
                    .foregroundColor(.white)
                
                Image(systemName: "star.fill")
                    .foregroundColor(.yellow)
            }.scaleEffect(2)
            
            Spacer()
            
            //Credits Counter
            Text("Credits: " + String(credits))
                .foregroundColor(.black)
                .padding(.all, 10)
                .background(Color.white.opacity(0.5))
                .cornerRadius(20)
            
            Spacer()
            
            //Cards
            VStack {
                HStack {
                    Spacer()
                    
                    CardView(symbol: $symbols[numbers[0]], background: $backgrounds[0])
                    
                    CardView(symbol: $symbols[numbers[1]], background: $backgrounds[1])
                    
                    CardView(symbol: $symbols[numbers[2]], background: $backgrounds[2])
                    
                    Spacer()
                    
                }
                HStack {
                    Spacer()
                    
                    CardView(symbol: $symbols[numbers[3]], background: $backgrounds[3])
                    
                    CardView(symbol: $symbols[numbers[4]], background: $backgrounds[4])
                    
                    CardView(symbol: $symbols[numbers[5]], background: $backgrounds[5])
                    
                    Spacer()
                    
                }
                HStack {
                    Spacer()
                    
                    CardView(symbol: $symbols[numbers[6]], background: $backgrounds[6])
                    
                    CardView(symbol: $symbols[numbers[7]], background: $backgrounds[7])
                    
                    CardView(symbol: $symbols[numbers[8]], background: $backgrounds[8])
                    
                    Spacer()
                    
                }
            }
            
            Spacer()
            
            //Button
            HStack ( spacing: 20 ) {
                VStack {
                    Button(action: {
                        
                        // Process a single spin
                        self.processResults(false)
                        
                        
                    }) {
                        
                        Text("Spin")
                            .bold()
                            .foregroundColor(.white)
                            .padding(.all, 10)
                            .padding([.leading, .trailing], 30)
                            .background(Color.pink)
                            .cornerRadius(20)
                        
                    }
                    Text("\(betAmount) credits").padding(.top, 10).font(.footnote)
                }
                
                VStack {
                    Button(action: {
                        
                        // Process a single spin
                        self.processResults(true)
                        
                        
                    }) {
                        
                        Text("Max Spin")
                            .bold()
                            .foregroundColor(.white)
                            .padding(.all, 10)
                            .padding([.leading, .trailing], 30)
                            .background(Color.pink)
                            .cornerRadius(20)
                        
                    }
                    Text("\(betAmount * 5) credits").padding(.top, 10).font(.footnote)
                }
                
                
            }
            
            
            
            
            Spacer()
            
        }
        
        
    }
    
}

func processResults(_ isMax : Bool) {
    //Set backgrounds back to white
    
    self.backgrounds = self.backgrounds.map { _ in
        Color.white
    }
    
    if isMax {
        //Spin all the cards
        self.numbers = self.numbers.map({ _ in
            Int.random(in: 0...self.symbols.count - 1)
        })
    }
    else{
        //Spin the middle row
        self.numbers[3] = Int.random(in: 0...self.symbols.count - 1)
        
        self.numbers[4] = Int.random(in: 0...self.symbols.count - 1)
        
        self.numbers[5] = Int.random(in: 0...self.symbols.count - 1)
        
    }
    
    //Check winnings
    processWin(isMax)
}

func processWin(_ isMax:Bool = false) {
    
    var matches = 0
    
    if isMax {
        
        //Processing for single spin
        if self.numbers[3] == self.numbers[4] && self.numbers[4] == self.numbers[5] {
            
            // Won
            matches += 1
            
            //Update backgrounds to green
            self.backgrounds[3] = Color.green
            self.backgrounds[4] = Color.green
            self.backgrounds[5] = Color.green
        }
    }
    else {
        //Processing max spin
        
        //Top row
        if self.numbers[0] == self.numbers[1] && self.numbers[1] == self.numbers[2] {
            
            // Won
            matches += 1
            
            //Update backgrounds to green
            self.backgrounds[0] = Color.green
            self.backgrounds[1] = Color.green
            self.backgrounds[2] = Color.green
        }
        
        //Middle Row
        if self.numbers[3] == self.numbers[4] && self.numbers[4] == self.numbers[5] {
            
            // Won
            matches += 1
            
            //Update backgrounds to green
            self.backgrounds[3] = Color.green
            self.backgrounds[4] = Color.green
            self.backgrounds[5] = Color.green
        }
        
        //Bottom Row
        if self.numbers[6] == self.numbers[7] && self.numbers[7] == self.numbers[8] {
            
            // Won
            matches += 1
            
            //Update backgrounds to green
            self.backgrounds[6] = Color.green
            self.backgrounds[7] = Color.green
            self.backgrounds[8] = Color.green
        }
        // Diagonal top left to bottom
        if self.numbers[0] == self.numbers[4] && self.numbers[4] == self.numbers[8] {
            
            // Won
            matches += 1
            
            //Update backgrounds to green
            self.backgrounds[0] = Color.green
            self.backgrounds[4] = Color.green
            self.backgrounds[8] = Color.green
        }
        
        // Diagonal top right to bottom left
        if self.numbers[2] == self.numbers[4] && self.numbers[4] == self.numbers[6] {
            
            // Won
            matches += 1
            
            //Update backgrounds to green
            self.backgrounds[2] = Color.green
            self.backgrounds[4] = Color.green
            self.backgrounds[6] = Color.green
        }
        
        //Check matches and distribute credits
        if matches > 0 {
            //At least 1 win
            self.credits += matches * betAmount * 2
        }
        else if !isMax {
            //0 wins, single spin
            self.credits -= betAmount
        }
        else {
            //0 wins, max spin
            self.credits -= betAmount * 5
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

}

One thing is that you have your conditional in the processWin function backwards. You check for isMax but when itā€™s true you are processing just the center row.

I tried editing the issues you addressed, but nothing seems to change. Perhaps I interpreted it wrong. Could you please edit my code while also elaborating on my mistake in hope to shed light on the issue because as of now, the issue still persists. Thank you.

Could you please send the edited source code? I think I might be having trouble interpreting what exactly your saying since Iā€™m a beginner.
Thank you!

In your function processWin, change the first if statement so that it looks like this:

if !isMax {

The ! symbol means the inverse of the boolean test. So rather than the test being ā€œif isMax is trueā€ the test is ā€œif NOT isMax is trueā€

Does that make sense?

The other way that this test could have been written is:

if isMax == false {

that is exactly the same as:

if !isMax {

Yes, I changed that in my code but the main issue still hasnā€™t been fixed.

  1. The app starts out with the ā€œappleā€ image in all 9 cells.

2)Both Spin and Max Spin preform the exact same operation (they change and randomize the middle row in order to find a match). The first and last row arenā€™t changing at all.

In summary only the middle row works, while the first and last stay the same for both buttons. The only difference upon clicking these both buttons is that there is a difference in credits, nothing else.

I just placed your code in my Temporary project and it works fine with the change to the line I mentioned. ā€œSpinā€ spins the middle row only and ā€œMax Spinā€ spins all rows.

Maybe you need to Clean your build folder. Shift + Option + Command + K

Ah wait. I see that the credits are not being updated on the centre row ā€œSpinā€ but get updated on a ā€œMax Spinā€.

I believe thereā€™s a problem in the Max Spin as only Row 1 works for it. Both Row 0 and Row 2 remain unchanged. The diagonal matching along with the other formats for getting a match donā€™t seem to work. While running this project, did you check the Max Spin? It doesnā€™t work.

Iā€™m just going to rebuild that processWin function.
BRB

OK fixed it. So many damn if statements itā€™s easy to lose track of where you are. Here is the repaired function:

func processWin(_ isMax:Bool = false) {
        var matches = 0
        
        if !isMax {
            //Processing for single spin
            if self.numbers[3] == self.numbers[4] && self.numbers[4] == self.numbers[5] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[3] = Color.green
                self.backgrounds[4] = Color.green
                self.backgrounds[5] = Color.green
                
            }
        } else {
            if self.numbers[0] == self.numbers[1] && self.numbers[1] == self.numbers[2] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[0] = Color.green
                self.backgrounds[1] = Color.green
                self.backgrounds[2] = Color.green
            }
            
            //Middle Row
            if self.numbers[3] == self.numbers[4] && self.numbers[4] == self.numbers[5] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[3] = Color.green
                self.backgrounds[4] = Color.green
                self.backgrounds[5] = Color.green
            }
            
            //Bottom Row
            if self.numbers[6] == self.numbers[7] && self.numbers[7] == self.numbers[8] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[6] = Color.green
                self.backgrounds[7] = Color.green
                self.backgrounds[8] = Color.green
            }
            // Diagonal top left to bottom
            if self.numbers[0] == self.numbers[4] && self.numbers[4] == self.numbers[8] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[0] = Color.green
                self.backgrounds[4] = Color.green
                self.backgrounds[8] = Color.green
            }
            
            // Diagonal top right to bottom left
            if self.numbers[2] == self.numbers[4] && self.numbers[4] == self.numbers[6] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[2] = Color.green
                self.backgrounds[4] = Color.green
                self.backgrounds[6] = Color.green
            }
        }
        //Check matches and distribute credits
        if matches > 0 {
            //At least 1 win
            self.credits += matches * betAmount * 2
        }
        else if !isMax {
            //0 wins, single spin
            self.credits -= betAmount
        }
        else {
            //0 wins, max spin
            self.credits -= betAmount * 5
        }
    }
1 Like

Thank you so much! I truly appreciate you putting in the time to help me! I have one more question though, as soon as I replaced the previous function with yours, I immediately got 2 errors saying the same thing, ā€œValue of type ā€˜ContentViewā€™ has no member ā€˜processResultsā€™ā€. This was located on line 104 and 125, where it states:

// Process a single spin
self.processResults(false)

So, if it works for you, the source code of my edited whole program would be completely fine so I can see the difference between what you and I had done.

Oh jeepers I think you accidentally overwrote the processResults function. Here it is:

func processResults(_ isMax : Bool = false) {
        //Set backgrounds back to white
        
        self.backgrounds = self.backgrounds.map { _ in
            Color.white
        }
        
        if isMax {
            //Spin all the cards
            self.numbers = self.numbers.map({ _ in
                Int.random(in: 0...self.symbols.count - 1)
            })
        }
        else{
            //Spin the middle row
            self.numbers[3] = Int.random(in: 0...self.symbols.count - 1)
            self.numbers[4] = Int.random(in: 0...self.symbols.count - 1)
            self.numbers[5] = Int.random(in: 0...self.symbols.count - 1)
        }
        
        //Check winnings
        processWin(isMax)
    }

The function processResults() calls processWin()

Do you want me to send you back the entire code from ContentView ?

Yes, if that is fine with you. I think comparing my entire code with your edited one would help me gain a better understanding of the exact flaws and how they were fixed. Thank you!

OK, the only change I made was to the processWin() function so all the rest is the same.

struct ContentView: View {
    
    @State private var symbols = ["apple", "star", "cherry" ]
    @State private var numbers = Array(repeating: 0, count: 9)
    @State private var backgrounds = Array(repeating: Color.white, count: 9)
    @State private var credits = 1000
    private var betAmount = 5

    var body: some View {
        
        ZStack {
            //Background
            Rectangle().foregroundColor(Color( red: 200/255, green: 143/255, blue: 32/255))
                .edgesIgnoringSafeArea(.all)
            
            Rectangle().foregroundColor(Color(red: 228/255, green: 195/255, blue: 76/255)).rotationEffect(Angle(degrees: 45)).edgesIgnoringSafeArea(.all)
            
            VStack {
                
                Spacer()
                
                //Title
                HStack {
                    Image(systemName: "star.fill")
                        .foregroundColor(.yellow)
                    
                    Text("SwiftUI Slots")
                        .bold()
                        .foregroundColor(.white)
                    
                    Image(systemName: "star.fill")
                        .foregroundColor(.yellow)
                }.scaleEffect(2)
                
                Spacer()
                
                //Credits Counter
                Text("Credits: " + String(credits))
                    .foregroundColor(.black)
                    .padding(.all, 10)
                    .background(Color.white.opacity(0.5))
                    .cornerRadius(20)
                
                Spacer()
                
                //Cards
                VStack {
                    HStack {
                        Spacer()
                        
                        CardView(symbol: $symbols[numbers[0]], background: $backgrounds[0])
                        
                        CardView(symbol: $symbols[numbers[1]], background: $backgrounds[1])
                        
                        CardView(symbol: $symbols[numbers[2]], background: $backgrounds[2])
                        
                        Spacer()
                        
                    }
                    HStack {
                        Spacer()
                        
                        CardView(symbol: $symbols[numbers[3]], background: $backgrounds[3])
                        
                        CardView(symbol: $symbols[numbers[4]], background: $backgrounds[4])
                        
                        CardView(symbol: $symbols[numbers[5]], background: $backgrounds[5])
                        
                        Spacer()
                        
                    }
                    HStack {
                        Spacer()
                        
                        CardView(symbol: $symbols[numbers[6]], background: $backgrounds[6])
                        
                        CardView(symbol: $symbols[numbers[7]], background: $backgrounds[7])
                        
                        CardView(symbol: $symbols[numbers[8]], background: $backgrounds[8])
                        
                        Spacer()
                        
                    }
                }
                
                Spacer()
                
                //Button
                HStack ( spacing: 20 ) {
                    VStack {
                        Button(action: {
                            
                            // Process a single spin
                            self.processResults(false)
                            
                        }) {
                            
                            Text("Spin")
                                .bold()
                                .foregroundColor(.white)
                                .padding(.all, 10)
                                .padding([.leading, .trailing], 30)
                                .background(Color.pink)
                                .cornerRadius(20)
                            
                        }
                        Text("\(betAmount) credits").padding(.top, 10).font(.footnote)
                    }
                    
                    VStack {
                        Button(action: {
                            
                            // Process a single spin
                            self.processResults(true)
                        }) {
                            
                            Text("Max Spin")
                                .bold()
                                .foregroundColor(.white)
                                .padding(.all, 10)
                                .padding([.leading, .trailing], 30)
                                .background(Color.pink)
                                .cornerRadius(20)
                        }
                        Text("\(betAmount * 5) credits").padding(.top, 10).font(.footnote)
                    }
                }
                
                Spacer()
            }
        }
    }

    func processResults(_ isMax : Bool = false) {
        //Set backgrounds back to white
        
        self.backgrounds = self.backgrounds.map { _ in
            Color.white
        }
        
        if isMax {
            //Spin all the cards
            self.numbers = self.numbers.map({ _ in
                Int.random(in: 0...self.symbols.count - 1)
            })
        }
        else{
            //Spin the middle row
            self.numbers[3] = Int.random(in: 0...self.symbols.count - 1)
            self.numbers[4] = Int.random(in: 0...self.symbols.count - 1)
            self.numbers[5] = Int.random(in: 0...self.symbols.count - 1)
        }
        
        //Check winnings
        processWin(isMax)
    }
    
    func processWin(_ isMax:Bool = false) {
        var matches = 0
        
        if !isMax {
            //Processing for single spin
            if self.numbers[3] == self.numbers[4] && self.numbers[4] == self.numbers[5] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[3] = Color.green
                self.backgrounds[4] = Color.green
                self.backgrounds[5] = Color.green
                
            }
        } else {
            if self.numbers[0] == self.numbers[1] && self.numbers[1] == self.numbers[2] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[0] = Color.green
                self.backgrounds[1] = Color.green
                self.backgrounds[2] = Color.green
            }
            
            //Middle Row
            if self.numbers[3] == self.numbers[4] && self.numbers[4] == self.numbers[5] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[3] = Color.green
                self.backgrounds[4] = Color.green
                self.backgrounds[5] = Color.green
            }
            
            //Bottom Row
            if self.numbers[6] == self.numbers[7] && self.numbers[7] == self.numbers[8] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[6] = Color.green
                self.backgrounds[7] = Color.green
                self.backgrounds[8] = Color.green
            }
            // Diagonal top left to bottom
            if self.numbers[0] == self.numbers[4] && self.numbers[4] == self.numbers[8] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[0] = Color.green
                self.backgrounds[4] = Color.green
                self.backgrounds[8] = Color.green
            }
            
            // Diagonal top right to bottom left
            if self.numbers[2] == self.numbers[4] && self.numbers[4] == self.numbers[6] {
                
                // Won
                matches += 1
                
                //Update backgrounds to green
                self.backgrounds[2] = Color.green
                self.backgrounds[4] = Color.green
                self.backgrounds[6] = Color.green
            }
        }
        //Check matches and distribute credits
        if matches > 0 {
            //At least 1 win
            self.credits += matches * betAmount * 5
        }
        else if !isMax {
            //0 wins, single spin
            self.credits -= betAmount
        }
        else {
            //0 wins, max spin
            self.credits -= betAmount * 5
        }
    }    
}
1 Like

Wow, it worked! I canā€™t wait to start analyzing this code and learn more on SwiftUI! Thank you!

No worries. Happy to be of assistance.