Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3f8af1e

Browse files
committed
sudoku game
1 parent 6abdcdc commit 3f8af1e

File tree

1 file changed

+208
-0
lines changed

1 file changed

+208
-0
lines changed

‎Sudoku_Game/sudoku.py‎

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import tkinter as tk
2+
from tkinter import messagebox,simpledialog
3+
import random
4+
5+
6+
class Sudoku:
7+
def __init__(self, master):
8+
self.master = master
9+
self.board = [[0] * 9 for _ in range(9)]
10+
self.solution = [[num for num in row] for row in self.board]
11+
self.empty_cells = self.get_empty_cells(self.board)
12+
self.create_widgets()
13+
14+
def create_widgets(self):
15+
self.master.configure(bg='#ECECEC')
16+
self.canvas = tk.Canvas(self.master, width=680, height=680, bg='#F8C8DC', highlightthickness=0)
17+
self.canvas.pack(side=tk.TOP, padx=0, pady=0)
18+
19+
self.draw_board()
20+
21+
self.button_frame = tk.Frame(self.master, bg='#ECECEC')
22+
self.button_frame.pack(side=tk.TOP, pady=20)
23+
24+
self.check_button = tk.Button(self.button_frame, text='Check', font=('Inter', 12, 'bold'),
25+
bg='#E75442', fg='#FFFFFF', bd=0, command=self.check_solution)
26+
self.check_button.pack(side=tk.LEFT, padx=10)
27+
28+
self.solve_button = tk.Button(self.button_frame, text='Solve', font=('Inter', 12, 'bold'),
29+
bg='#3AC6FF', fg='#FFFFFF', bd=0, command=self.solve_puzzle)
30+
self.solve_button.pack(side=tk.LEFT, padx=10)
31+
32+
self.level_frame = tk.Frame(self.master, bg='#ECECEC')
33+
self.level_frame.pack(side=tk.TOP, pady=0)
34+
35+
self.level_label = tk.Label(self.level_frame, text='Select Level:', font=('Inter', 12,"bold"), bg='#77DD77', fg='#ECECEC')
36+
self.level_label.pack(side=tk.LEFT, padx=10)
37+
38+
self.level_var = tk.StringVar()
39+
self.level_var.set('Easy')
40+
self.level_dropdown = tk.OptionMenu(self.level_frame, self.level_var, 'Easy', 'Medium', 'Hard',
41+
command=self.new_game)
42+
self.level_dropdown.config(font=('Arial', 12,"bold"), bg='#ffb347', fg='#ECECEC', bd=0)
43+
self.level_dropdown.pack(side=tk.LEFT, padx=10)
44+
45+
self.new_game_button = tk.Button(self.level_frame, text='New Game', font=('Inter', 12, 'bold'),
46+
bg='#FFD700', fg='#ECECEC', bd=0, command=self.new_game_wrapper)
47+
self.new_game_button.pack(side=tk.LEFT, padx=10)
48+
self.canvas.bind("<Button-1>", self.on_cell_click)
49+
50+
51+
def new_game_wrapper(self):
52+
level = self.level_var.get()
53+
self.new_game(level)
54+
55+
def new_game(self, level):
56+
if level == 'Easy':
57+
num_cells = 40
58+
elif level == 'Medium':
59+
num_cells = 50
60+
elif level == 'Hard':
61+
num_cells = 60
62+
63+
self.board = [[0] * 9 for _ in range(9)]
64+
self.generate_puzzle()
65+
self.remove_cells(num_cells)
66+
self.empty_cells = self.get_empty_cells(self.board)
67+
self.draw_board()
68+
69+
def generate_puzzle(self):
70+
self.solve_board(self.board)
71+
for _ in range(81):
72+
row = random.randint(0, 8)
73+
col = random.randint(0, 8)
74+
temp = self.board[row][col]
75+
self.board[row][col] = 0
76+
count = 0
77+
solution_copy = [row[:] for row in self.board]
78+
self.solve_board(solution_copy)
79+
for i in range(9):
80+
if 0 in solution_copy[i]:
81+
count += 1
82+
if count != 1:
83+
self.board[row][col] = temp
84+
85+
def solve_board(self, board):
86+
empty_cell = self.get_empty_cell(board)
87+
if not empty_cell:
88+
return True
89+
90+
row, col = empty_cell
91+
for num in range(1, 10):
92+
if self.is_valid_move(board, row, col, num):
93+
board[row][col] = num
94+
if self.solve_board(board):
95+
return True
96+
board[row][col] = 0
97+
return False
98+
99+
def on_cell_click(self, event):
100+
x, y = event.x, event.y
101+
row, col = (y - 80) // 60, (x - 80) // 60
102+
if self.board[row][col] != 0:
103+
messagebox.showinfo('Invalid Move', 'Cannot change pre-filled cells!')
104+
return
105+
num = tk.simpledialog.askinteger('Input', 'Enter a number (1-9):', minvalue=1, maxvalue=9)
106+
if num:
107+
self.board[row][col] = num
108+
self.draw_board()
109+
110+
111+
def get_empty_cell(self, board):
112+
for i in range(9):
113+
for j in range(9):
114+
if board[i][j] == 0:
115+
return i, j
116+
return None
117+
118+
def is_valid_move(self, board, row, col, num):
119+
return (
120+
self.is_valid_row(board, row, num)
121+
and self.is_valid_col(board, col, num)
122+
and self.is_valid_box(board, row - row % 3, col - col % 3, num)
123+
)
124+
125+
def is_valid_row(self, board, row, num):
126+
for i in range(9):
127+
if board[row][i] == num:
128+
return False
129+
return True
130+
131+
def is_valid_col(self, board, col, num):
132+
for i in range(9):
133+
if board[i][col] == num:
134+
return False
135+
return True
136+
137+
def is_valid_box(self, board, start_row, start_col, num):
138+
for i in range(3):
139+
for j in range(3):
140+
if board[start_row + i][start_col + j] == num:
141+
return False
142+
return True
143+
144+
def draw_board(self):
145+
self.clear_board()
146+
for i in range(9):
147+
for j in range(9):
148+
x = i * 60 + 80
149+
y = j * 60 + 80
150+
cell_value = self.board[j][i]
151+
if cell_value != 0:
152+
# Adjust the coordinates to avoid intersection
153+
text_x = x + 15
154+
text_y = y + 15
155+
self.canvas.create_text(text_x, text_y, text=str(cell_value), font=('Inter', 20, 'bold'), fill='#333333')
156+
157+
self.draw_grid()
158+
159+
def draw_grid(self):
160+
for i in range(10):
161+
if i % 3 == 0:
162+
line_width = 2
163+
else:
164+
line_width = 1
165+
self.canvas.create_line(60 * i + 80, 80, 60 * i + 80, 620, width=line_width, fill='#333333')
166+
self.canvas.create_line(80, 60 * i + 80, 620, 60 * i + 80, width=line_width, fill='#333333')
167+
168+
def clear_board(self):
169+
self.canvas.delete('all')
170+
171+
def check_solution(self):
172+
for i in range(9):
173+
for j in range(9):
174+
if self.board[i][j] != self.solution[i][j]:
175+
messagebox.showinfo('Incorrect', 'The solution is not correct!')
176+
return
177+
messagebox.showinfo('Correct', 'Congratulations! You solved the puzzle!')
178+
179+
def remove_cells(self, num_cells):
180+
cells = [(i, j) for i in range(9) for j in range(9)]
181+
random.shuffle(cells)
182+
for i in range(num_cells):
183+
row, col = cells[i]
184+
self.board[row][col] = 0
185+
186+
def get_empty_cells(self, board):
187+
empty_cells = []
188+
for i in range(9):
189+
for j in range(9):
190+
if board[i][j] == 0:
191+
empty_cells.append((i, j))
192+
return empty_cells
193+
194+
def solve_puzzle(self):
195+
solution_board = [row[:] for row in self.board]
196+
if self.solve_board(solution_board):
197+
self.solution = solution_board
198+
self.board = solution_board
199+
self.draw_board()
200+
else:
201+
messagebox.showinfo('Unsolvable', 'The puzzle does not have a solution.')
202+
203+
204+
if __name__ == '__main__':
205+
root = tk.Tk()
206+
root.title('Sudoku')
207+
gui = Sudoku(root)
208+
root.mainloop()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /