You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中点击NavigationLink重复生成相同Board的问题求助

解决数独游戏重复生成相同棋盘的问题

问题根源

你遇到的问题本质是:从WelcomeView进入GameView时,复用了提前创建好的旧Board实例,而GameView内的新游戏是实时生成新实例,导致两次进入同难度得到重复棋盘。

具体解决步骤

1. 重构Board的初始化逻辑

给Board添加按难度生成棋盘的初始化方法,确保每次初始化都生成全新的棋盘:

// 先定义难度枚举
enum Difficulty {
    case easy, medium, hard
}

struct Board {
    let id = UUID() // 加UUID用于标识不同实例,辅助视图刷新判断
    var grid: [[Int]]
    
    // 按难度初始化,直接生成对应棋盘
    init(difficulty: Difficulty) {
        self.grid = Self.generateGrid(for: difficulty)
    }
    
    // 静态方法:根据难度生成棋盘逻辑
    static func generateGrid(for difficulty: Difficulty) -> [[Int]] {
        // 这里替换成你的数独棋盘生成代码,根据难度调整空位数量/位置等
        switch difficulty {
        case .easy:
            return generateEasyGrid()
        case .medium:
            return generateMediumGrid()
        case .hard:
            return generateHardGrid()
        }
    }
    
    // 你的具体生成函数
    private static func generateEasyGrid() -> [[Int]] { /* ... */ }
    private static func generateMediumGrid() -> [[Int]] { /* ... */ }
    private static func generateHardGrid() -> [[Int]] { /* ... */ }
}

2. 修改GameView:接收难度参数,实时生成Board

让GameView不再直接接收Board实例,而是接收难度,初始化时创建新的Board:

struct GameView: View {
    let difficulty: Difficulty
    @State private var currentBoard: Board
    
    // 初始化时根据难度生成新棋盘
    init(difficulty: Difficulty) {
        self.difficulty = difficulty
        self._currentBoard = State(initialValue: Board(difficulty: difficulty))
    }
    
    // 游戏内切换同难度新游戏的逻辑
    private func startNewGame() {
        currentBoard = Board(difficulty: difficulty)
    }
    
    var body: some View {
        VStack {
            // 渲染81个CellView,使用currentBoard.grid
            ForEach(0..<9) { row in
                HStack {
                    ForEach(0..<9) { col in
                        CellView(value: currentBoard.grid[row][col])
                    }
                }
            }
            
            Button("同难度新游戏") {
                startNewGame()
            }
        }
    }
}

3. 调整WelcomeView的NavigationLink

不要提前生成Board实例,而是直接给GameView传难度参数:

struct WelcomeView: View {
    var body: some View {
        NavigationStack {
            VStack(spacing: 20) {
                NavigationLink("开始Easy难度", destination: GameView(difficulty: .easy))
                NavigationLink("开始Medium难度", destination: GameView(difficulty: .medium))
                NavigationLink("开始Hard难度", destination: GameView(difficulty: .hard))
            }
            .padding()
        }
    }
}

为什么之前加UUID没用?

你给Board加UUID是对的,但问题出在没有创建新实例——如果WelcomeView里提前生成了一个Easy难度的Board并缓存,每次点击NavigationLink都传这个旧实例,UUID虽然存在,但还是同一个对象,棋盘自然不会变。现在的逻辑是每次进入GameView都创建全新的Board实例,UUID也会是新的,视图会自动刷新显示新棋盘。

内容的提问来源于stack exchange,提问作者b3rber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 22:01:12