Crash on implementing DFS in SwiftUI

66 Views Asked by At

I am a newbie to SwiftUI and I was trying to make a DFS (Depth First search) visualizer in SwiftUI. I have the following code.

//
//  Maze.swift
//  BookCore
//
//  Created by Subhronil Saha on 14/04/21.
//

import Foundation

class Maze: ObservableObject {
    
    @Published var map = [
        [1, 2, 3, 4, 5, 6, 7, 8],
        [9, 10, 11, 12, 13, 14, 15, 16],
        [17, 18, 19, 20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29, 30, 31, 32],
        [33, 34, 35, 36, 37, 38, 39, 40],
        [41, 42, 43, 44, 45, 46, 47, 48],
        [49, 50, 51, 52, 53, 54, 55, 56],
        [57, 58, 59, 60, 61, 62, 63, 64]
    ]
    
    @Published var visited = [
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0]
    ]
     
    @Published var stack = [1]
    
    var gameTimer: Timer?
    @Published var currentNode = 1
    @Published var row = 0
    @Published var col = 0
    var k = 1
    
    // Constructor
    public init() {

    }
    
    func markVisited(row: Int, col: Int) {
        visited[row][col] = (visited[row][col] == 0) ? 1 : 0
    }
    
    func dfsUtil() -> [Int] {
        
        var myStack: [Int] = [1]
        
        while(myStack.count != 0) {
            let topId = myStack[myStack.count-1]
            myStack.removeLast()
            currentNode = topId
            let currRow = topId / 8
            row = currRow
            let currCol = topId % 8 - 1
            col = currCol
            
            if(visited[currRow][currCol] == 0) {
                visited[currRow][currCol] = 1
            }

            if(topId - 8 > 0) {
                let neighborId = topId - 8
                let row = neighborId / 8
                let col = neighborId % 8 - 1
                if(visited[row][col] == 0) {
                    myStack.append(neighborId)
                }
            }
            if(topId + 1 <= 64) {
                let neighborId = (topId + 1)
                let row = neighborId / 8
                let col = neighborId % 8 - 1
                if(visited[row][col] == 0) {
                    myStack.append(neighborId)
                }
            }
            if(topId + 8 <= 64) {
                let neighborId = (topId + 8)
                let row = neighborId / 8
                let col = neighborId % 8 - 1
                if(visited[row][col] == 0) {
                    myStack.append(neighborId)
                }
            }
            if(topId - 1 > 0) {
                let neighborId = (topId - 1)
                let row = neighborId / 8
                let col = neighborId % 8 - 1
                if(visited[row][col] == 0) {
                    myStack.append(neighborId)
                }
            }

        }
        
        return myStack
        
    }
    
    func dfs(startRow: Int, startCol: Int) {
        // Add Root element
        var myStack = dfsUtil()
        stack = myStack
        //gameTimer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(dfsUtil), userInfo: nil, repeats: true)
    }
    
}

I call the function dfs(0, 0) from MazeView.swift on a Button tap. And I am displaying colored circle buttons based on the visited matrix from the Maze class. The code runs the first iteration and then it crashes. I cannot figure out at all what is going wrong.

Please have a look at the code. Reaally thank you for the help.

//
//  MazeView.swift
//  BookCore
//
//  Created by Subhronil Saha on 13/04/21.
//

import SwiftUI

public struct MazeView: View {
    
    @EnvironmentObject var maze: Maze
    
    public init() {
        
    }
    
    public var body: some View {
        VStack(spacing: 10){
            
            Spacer()
            
            //MARK:- Board
            ForEach(0..<8, id: \.self) { row in
                HStack(spacing: 10){
                    ForEach(0..<8, id: \.self) { col in
                        if maze.visited[row][col] == 0 {
                            
                            Button (action: {
                                withAnimation {
                                    maze.markVisited(row: row, col: col)
                                }
                                
                            }) {
                                
                                ZStack {
                                    Circle()
                                        .foregroundColor(Color.white)
                                        .frame(width: 40, height: 40, alignment: .center)
                                    Text("\(maze.map[row][col])")
                                }
                            }

                        } else {
                            Button (action: {
                                withAnimation {
                                    maze.markVisited(row: row, col: col)
                                }
                            }) {
                                Circle()
                                    .fill(Color.green)
                                    .frame(width: 40, height: 40, alignment: .center)
                            }
                        }
                    }
                }
            }
            
            Spacer()
                .frame(height: 30)
            
            //MARK:- Action Buttons
            Button(action: {
                maze.dfs(startRow: 1, startCol: 1)
            }) {
                ZStack {
                    Capsule()
                        .fill(Color.pink)
                        .frame(width: 50, height: 20, alignment: .center)
                    
                    Text("DFS")
                        .foregroundColor(Color.white)
                }
            }
            
            Text("\(maze.currentNode)")
            Text("\(maze.row)")
            Text("\(maze.col)")
            
            HStack(spacing: 10) {
                ForEach(0..<maze.stack.count, id: \.self) { index in
                    Text("\(maze.stack[index])")
                }
            }
            
            Spacer()
            
        }
    }
}
0

There are 0 best solutions below