Skip to content

Commit 292c454

Browse files
authored
Generate unique solution (#2)
* Generate unique solution * Version 1.1.0 * Update ReadMe
1 parent c219d78 commit 292c454

3 files changed

Lines changed: 48 additions & 7 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Sudoku
2-
Sudoku Solver & Generator – create, generate, or solve Sudoku puzzles
2+
Sudoku Solver & Generator
33

44
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
55

@@ -13,11 +13,11 @@ This project is a complete Sudoku tool written in [Xojo](https://www.xojo.com/).
1313
- Enter your own Sudoku puzzle
1414
- Generate a random Sudoku puzzle with a given number of clues
1515
- Solve the Sudoku puzzle
16-
- Interactively edit puzzles in a desktop UI with on the fly validation
16+
- Interactively edit puzzles with on the fly validation
1717
- Let the solver complete the puzzle
1818

1919
### Logic
20-
*The solver uses a classic backtracking algorithm with rule checking to guarantee correct solutions. Random puzzle generation is based on creating a full valid grid, applying digit shuffling, and then removing cells to reach the desired clue count.*
20+
*The solver uses a classic backtracking algorithm with rule checking to guarantee correct solutions. Random puzzle generation is based on creating a full valid grid, applying digit shuffling, and then removing cells to reach the desired clue count while enforcing a unique solution.*
2121

2222

2323
### ScreenShot

Sudoku.xojo_project

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,19 @@ MultiImage=PayPal;Resources/PayPal.xojo_image;&h0000000042A75FFF;&h000000005DC5C
2424
DefaultWindow=Window1
2525
AppMenuBar=MainMenuBar
2626
MajorVersion=1
27-
MinorVersion=0
27+
MinorVersion=1
2828
SubVersion=0
2929
NonRelease=0
3030
Release=0
3131
InfoVersion=Sudoku
3232
LongVersion=jo-tools.ch
33-
ShortVersion=1.0.0
33+
ShortVersion=1.1.0
3434
WinCompanyName=jo-tools.ch
3535
WinInternalName=Sudoku
3636
WinProductName=Sudoku
3737
WinFileDescription=Sudoku
3838
AutoIncrementVersionInformation=False
39-
BuildFlags=&h5990
39+
BuildFlags=&h4900
4040
BuildLanguage=&h0
4141
DebugLanguage=&h0
4242
Region=

Sudoku/Logic/SudokuTool.xojo_code

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Protected Class SudokuTool
33
#tag Method, Flags = &h0
44
Sub ClearGrid()
5+
' Fill entire grid with 0's
56
Redim grid(N-1, N-1)
67
For r As Integer = 0 To N-1
78
For c As Integer = 0 To N-1
@@ -19,6 +20,7 @@ Protected Class SudokuTool
1920

2021
#tag Method, Flags = &h0
2122
Sub Constructor(clone As SudokuTool)
23+
' Init with state of passed-in Sudoku-grid
2224
Redim grid(N-1, N-1)
2325
For r As Integer = 0 To N-1
2426
For c As Integer = 0 To N-1
@@ -28,8 +30,35 @@ Protected Class SudokuTool
2830
End Sub
2931
#tag EndMethod
3032

33+
#tag Method, Flags = &h21
34+
Private Function CountSolutions(limit As Integer = 2) As Integer
35+
Var row, col As Integer
36+
If Not FindEmpty(row, col) Then
37+
Return 1 ' Found one solution
38+
End If
39+
40+
Var total As Integer = 0
41+
' Try every possible digit for that empty cell
42+
For val As Integer = 1 To N
43+
If IsValueValid(row, col, val) Then
44+
' After trying a digit, reset the cell to 0 and try the next digit
45+
grid(row, col) = val
46+
total = total + CountSolutions(limit)
47+
grid(row, col) = 0
48+
49+
If total >= limit Then
50+
Exit ' No need to count more
51+
End If
52+
End If
53+
Next
54+
55+
Return total
56+
End Function
57+
#tag EndMethod
58+
3159
#tag Method, Flags = &h21
3260
Private Function FindEmpty(ByRef outRow As Integer, ByRef outCol As Integer) As Boolean
61+
' Find the first empty cell
3362
For r As Integer = 0 To N-1
3463
For c As Integer = 0 To N-1
3564
If grid(r, c) = 0 Then
@@ -39,6 +68,7 @@ Protected Class SudokuTool
3968
End If
4069
Next
4170
Next
71+
4272
Return False
4373
End Function
4474
#tag EndMethod
@@ -108,13 +138,19 @@ Protected Class SudokuTool
108138
indices(j) = tmpIndex
109139
Next
110140

111-
' Remove cells until only numClues remain
141+
' Remove cells while keeping unique solution
112142
Var removeCount As Integer = N*N - numClues
113143
For i As Integer = 0 To removeCount - 1
114144
Var idx As Integer = indices(i)
115145
Var rr As Integer = idx \ N
116146
Var cc As Integer = idx Mod N
147+
Var backup As Integer = grid(rr, cc)
148+
117149
grid(rr, cc) = 0
150+
If CountSolutions(2) <> 1 Then
151+
' Not unique anymore, restore the number
152+
grid(rr, cc) = backup
153+
End If
118154
Next
119155

120156
' Done — grid now contains the generated puzzle (numClues non-zero cells)
@@ -142,6 +178,8 @@ Protected Class SudokuTool
142178

143179
#tag Method, Flags = &h0
144180
Function IsSolvable() As Boolean
181+
' Try solve on a clone, so that this
182+
' grid is not being modified
145183
Var clone As New SudokuTool(Me)
146184
Return clone.Solve
147185

@@ -150,8 +188,10 @@ Protected Class SudokuTool
150188

151189
#tag Method, Flags = &h0
152190
Function IsSolved() As Boolean
191+
' Ensure current filled-in digits are valid
153192
If (Not IsValid) Then Return False
154193

194+
' And no empty cells left
155195
For r As Integer = 0 To N-1
156196
For c As Integer = 0 To N-1
157197
If (grid(r,c) = 0) Then Return False
@@ -238,6 +278,7 @@ Protected Class SudokuTool
238278

239279
#tag Method, Flags = &h0
240280
Function Solve() As Boolean
281+
' Ensure current filled-in digits are valid
241282
If (Not IsValid()) Then Return False
242283

243284
Return SolveInternal()

0 commit comments

Comments
 (0)