我正在为 iOS 制作数独,这对于我的课程来说将是一个简单的项目。问题在于数独的检查。检查的数独可能会出现三个结果:
根据这些值的枚举,将会有一个工作表显示已检查的数独的结果。
列举如下:
// MARK: Statuses
/// Statuses that can result from checking the sudoku.
enum Statuses {
case correct
case incorrect
case notFilled
}
这是保存枚举值和用于显示工作表的布尔变量的结构。
// MARK: SudokuStatus
/// Struct that is used to combine the status and if the sudoku is checked.
struct SudokuStatus {
public var status: Statuses
public var isChecked: Bool
/// Initialiser of the struct making the status not checked and empty.
init () {
self.status = .notFilled
self.isChecked = false
}
/// Function that will update the status.
/// - Parameter status: The status form the sudoku.
/// - Returns: There is no return.
mutating func setStatus(status: Statuses) -> Void {
self.status = status
self.isChecked = true
}
}
这是内容视图。
// MARK: ContentView
/// The main view of the app.
struct ContentView: View {
/// Variable that will create a sudoku object.
let sudoku: Sudoku = Sudoku()
/// Array that will hold the numbers in the sudoku.
/// If the numbers is equals to 0 it means its empty.
@State var numbers: [[Number]] = Array(repeating: Array(repeating: Number(), count: 9), count: 9)
/// Variable that will keep the selected number.
/// The value at begging will be 0 representing that no number is selected.
@State var selectedNumber: Int = 0
/// Variable used to selected the difficulty of the game.
@State var selectedDifficulty: Difficulties = .easy
/// Variable that will keep the status form the sudoku.
@State var sudokuStatus: SudokuStatus = SudokuStatus()
/// The main body of the struct.
var body: some View {
GeometryReader { geo in
VStack(spacing: geo.size.height / 20) {
Title (
width: geo.size.width / 1.2,
height: geo.size.height / 10
)
Board (
size: geo.size.width / 1.2,
selectedNumber: $selectedNumber,
numbers: $numbers
)
NumberSelection (
width: geo.size.width,
height: geo.size.height / 10,
selectedNumber: $selectedNumber
)
BottomBar (
width: geo.size.width,
height: geo.size.height / 10,
onStartGameClicked: onStartGameClicked,
onCheckGameClicked: onCheckGameClicked,
selectedDifficulty: $selectedDifficulty
)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.sheet(isPresented: $sudokuStatus.isChecked, content: {
SudokuStatusSheet(status: sudokuStatus.status)
})
}
}
/// Function called when the start button is clicked.
/// - Returns: There is no return. The function fills the array with the numbers.
func onStartGameClicked() -> Void {
let grid: [[Int]] = sudoku.generateSudoku(difficulty: selectedDifficulty)
for i in 0..<9 {
for j in 0..<9 {
if grid[i][j] == 0 {
numbers[i][j].value = 0
numbers[i][j].isGenerated = false
}
else {
numbers[i][j].value = grid[i][j]
numbers[i][j].isGenerated = true
}
}
}
}
/// Function called when the check button is clicked.
/// - Returns: There is no return. The function updates the sudoku status variable.
func onCheckGameClicked() -> Void {
var grid: [[Int]] = Array(repeating: Array(repeating: 0, count: 9), count: 9)
for i in 0..<9 {
for j in 0..<9 {
if numbers[i][j].value == 0 {
sudokuStatus.setStatus(status: .notFilled)
return
}
grid[i][j] = numbers[i][j].value
}
}
if Sudoku.checkSudoku(grid: grid) {
sudokuStatus.setStatus(status: .correct)
} else {
sudokuStatus.setStatus(status: .incorrect)
}
}
}
如您所见,检查数独的功能非常简单。它通过保存数字值的结构体和 bool 变量来检查输入的数字,以检查该数字是否由用户生成或输入。如果数字等于0,则表示为空,会将值更新为未填充并返回。然后它将由班级进行检查 数独可以正确工作,如果结果为真,它将使其从正确变为错误。问题是,每次应用程序启动或预览重新启动时,您第一次检查数独时,它总是会显示未填充。之后代码就可以正常工作,但第一次检查时就不行了。
我更改了结构数独状态的默认初始化程序的值,并了解到将显示的第一个值将是设置的默认值。我真的不知道如何解决这个问题,所以我没有尝试更多,除了在互联网上搜索同样的问题,或者使用我们最喜欢的人工智能,但它没有帮助。
最好的方法是创建一个符合
ObservableObject
并具有 @Published
值的类,如下所示:
class SudokuStatus: ObservableObject {
@Published var status: Statuses = .notFilled
@Published var isChecked: Bool = false
func setStatus(status: Statuses) {
self.status = status
self.isChecked = true
}
}
然后,您必须将此对象声明为
@StateObject
,并像您一样使用它,如下所示:
@StateObject var sudokuStatus: SudokuStatus = .init()
//...
.sheet(isPresented: $sudokuStatus.isChecked) {
SudokuStatusSheet(status: sudokuStatus.status)
}
//...