Skip to content

Commit 7c4f67b

Browse files
committedJul 9, 2023
Update Gui
1 parent 0091323 commit 7c4f67b

File tree

10 files changed

+234
-0
lines changed

10 files changed

+234
-0
lines changed
 
File renamed without changes.
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"CurrentProjectSetting": null
3+
}
13.5 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"ExpandedNodes": [
3+
""
4+
],
5+
"PreviewInSolutionExplorer": false
6+
}

‎0x17-Sudoku/SudokuGui/.vs/slnx.sqlite

88 KB
Binary file not shown.

‎0x17-Sudoku/SudokuGui/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# SudokuSolver
2+
Solve any Suduko puzzle using this solver GUI built using Python and Tkinter.
3+
The code uses a backtracking algorithm to solve the puzzle.
4+
5+
<h2>Running the Program</h2>
6+
There are two ways to run the program. The first of which involves using the GUI. Begin by importing gui.py into your IDE of choice. Then run the program and a window will appear.
7+
Input your chosen Sudoku puzzle into the cells of the window. Leave any empty cells blank. Then simply click "solve" to complete the puzzle or "clear" to clear the puzzle.<br>
8+
<br>
9+
10+
Alternatively, you can run the program without a GUI using the solver.py script. Simply import the script into your IDE of choice. Then fill out the 2D board vector at the top of the file.
11+
Fill in empty cells with a zero. After filling in the board vector, you can run the program. The output will be printed to the console.
12+
Binary file not shown.

‎0x17-Sudoku/SudokuGui/gui.py

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
'''
2+
GUI which allows you to solve any Sudoku puzzle.
3+
4+
The GUI has been created using Tkinter and a backtracking algorithm has been used.
5+
'''
6+
7+
from tkinter import *
8+
9+
root = Tk()
10+
root.geometry('330x370')
11+
12+
# Sudoku solver class
13+
class SudokuSolver():
14+
15+
def __init__(self):
16+
self.setZero()
17+
self.solve()
18+
19+
# Set the empty cells to 0 (i.e. the cells you have not filled in)
20+
def setZero(self):
21+
for i in range(9):
22+
for j in range(9):
23+
if filledBoard[i][j].get() not in ['1','2','3','4','5','6','7','8','9']:
24+
filledBoard[i][j].set(0)
25+
26+
# Solve using backtracking
27+
def solve(self):
28+
# Find next empty cell
29+
findEmpty = self.emptyCell()
30+
31+
if not findEmpty:
32+
return True
33+
else:
34+
row, column = findEmpty
35+
36+
for i in range(1,10):
37+
if self.isValid(i, (row, column)):
38+
filledBoard[row][column].set(i)
39+
40+
if self.solve():
41+
return True
42+
43+
filledBoard[row][column].set(0)
44+
45+
return False
46+
47+
# Check row, column and subgrid(3x3 square) to see if number can be placed in cell
48+
def isValid (self, num, pos):
49+
# Check Row
50+
for i in range(9):
51+
if filledBoard[pos[0]][i].get() == str(num):
52+
return False
53+
# Check Column
54+
for i in range(9):
55+
if filledBoard[i][pos[1]].get() == str(num):
56+
return False
57+
58+
# Check Sub Grid
59+
row = pos[0] // 3
60+
column = pos[1] // 3
61+
62+
for i in range(row * 3, (row * 3) + 3):
63+
for j in range(column * 3, (column * 3) + 3):
64+
if filledBoard[i][j].get() == str(num):
65+
return False
66+
return True
67+
68+
# Find empty cells, defined as cells filled with a zero
69+
def emptyCell(self):
70+
for row in range(9):
71+
for column in range(9):
72+
if filledBoard[row][column].get() == '0':
73+
return (row,column)
74+
return None
75+
76+
# GUI class
77+
class Interface():
78+
def __init__(self, window):
79+
self.window = window
80+
window.title("Sudoku Solver")
81+
82+
font = ('Arial', 20)
83+
color = 'white'
84+
85+
# Create solve and clear button and link them to Solve and Clear methods
86+
solve = Button(window, text = 'Solve', command = self.Solve)
87+
solve.grid(column=3,row=20)
88+
clear = Button(window, text = 'Clear', command = self.Clear)
89+
clear.grid(column = 5,row=20)
90+
91+
# Initialise empty 2D list
92+
self.board = []
93+
for row in range(9):
94+
self.board += [["","","","","","","","",""]]
95+
96+
for row in range(9):
97+
for col in range(9):
98+
# Change color of cells depending on position in grid
99+
if (row < 3 or row > 5) and (col < 3 or col > 5):
100+
color = 'white'
101+
elif (row >= 3 and row < 6) and (col >=3 and col < 6):
102+
color = 'white'
103+
else:
104+
color = 'grey'
105+
106+
# Make each cell of grid a entry box and store each user entry into the filledBoard 2D list
107+
self.board[row][col] = Entry(window, width = 2, font = font, bg = color, cursor = 'arrow', borderwidth = 2,
108+
highlightcolor = 'yellow', highlightthickness = 0, highlightbackground = 'black',
109+
textvariable = filledBoard[row][col])
110+
self.board[row][col].bind('<FocusIn>', self.gridChecker) # Link to better understand binding statements: https://www.python-course.eu/tkinter_events_binds.php#:~:text=Tkinter%20provides%20a%20mechanism%20to,and%20methods%20to%20an%20event.&text=If%20the%20defined%20event%20occurs,describing%20the%20event.
111+
self.board[row][col].bind('<Motion>', self.gridChecker)
112+
self.board[row][col].grid(row = row, column = col)
113+
114+
# Function to check if user enters a value which is not an int between 1 and 9 (valid numbers in Sudoku game).
115+
# If entry is not valid, clear value
116+
def gridChecker(self, event):
117+
for row in range(9):
118+
for col in range(9):
119+
if filledBoard[row][col].get() not in ['1','2','3','4','5','6','7','8','9']:
120+
filledBoard[row][col].set('')
121+
122+
# Call Sudoku solver class (called by solve button)
123+
def Solve(self):
124+
SudokuSolver()
125+
126+
# Function to clear board (called by clear button)
127+
def Clear(self):
128+
for row in range(9):
129+
for col in range(9):
130+
filledBoard[row][col].set('')
131+
132+
# Global 2D list which saved in the values the user enters on the GUI
133+
# Each value in the 2D list is set as a StringVar(), a class in Tkinter
134+
# which allows you to save values users enter into the Entry widget
135+
filledBoard = []
136+
for row in range(9):
137+
filledBoard += [["","","","","","","","",""]]
138+
for row in range(9):
139+
for col in range(9):
140+
filledBoard[row][col] = StringVar(root)
141+
142+
# Main Loop
143+
Interface(root)
144+
root.mainloop()
145+
146+
147+

‎0x17-Sudoku/SudokuGui/solver.py

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import numpy as np
2+
board = [
3+
[5,3,0,0,7,0,0,0,0],
4+
[6,0,0,1,9,5,0,0,0],
5+
[0,9,8,0,0,0,0,6,0],
6+
[8,0,0,0,6,0,0,0,3],
7+
[4,0,0,8,0,3,0,0,1],
8+
[7,0,0,0,2,0,0,0,6],
9+
[0,6,0,0,0,0,2,8,0],
10+
[0,0,0,4,1,9,0,0,5],
11+
[0,0,0,0,8,0,0,7,9]
12+
]
13+
14+
def solve(board):
15+
# Find next empty cell
16+
findEmpty = emptyCell(board)
17+
18+
if not findEmpty:
19+
return True # Board is filled
20+
else:
21+
row, column = findEmpty
22+
23+
for i in range(1,10):
24+
if isValid(board, i, (row, column)):
25+
board[row][column] = i
26+
27+
if solve(board):
28+
return True
29+
30+
board[row][column] = 0
31+
32+
return False
33+
34+
35+
def isValid (board, num, pos):
36+
# Check Row
37+
for i in range(9):
38+
if num == board[pos[0]][i]:
39+
return False
40+
# Check Column
41+
for i in range(9):
42+
if num == board[i][pos[1]]:
43+
return False
44+
45+
# Check Sub Grid
46+
row = pos[0] // 3
47+
column = pos[1] // 3
48+
49+
for i in range(row * 3, (row * 3) + 3):
50+
for j in range(column * 3, (column * 3) + 3):
51+
if num == board[i][j]:
52+
return False
53+
return True
54+
55+
def emptyCell(board):
56+
for row in range(9):
57+
for column in range(9):
58+
if board[row][column] == 0:
59+
return (row,column)
60+
return None
61+
62+
def printBoard(board):
63+
print(np.matrix(board))
64+
65+
66+

0 commit comments

Comments
 (0)
Please sign in to comment.