Skip to content

Commit 5e7389a

Browse files
Added sudoku
1 parent 6bbe3c4 commit 5e7389a

File tree

1 file changed

+289
-0
lines changed

1 file changed

+289
-0
lines changed

Diff for: python/sudoku_gui.py

+289
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
import time
2+
import pygame
3+
from sudoku import solve, valid, find_empty
4+
5+
pygame.font.init()
6+
7+
8+
class Grid:
9+
board = [
10+
[7, 8, 0, 4, 0, 0, 1, 2, 0],
11+
[6, 0, 0, 0, 7, 5, 0, 0, 9],
12+
[0, 0, 0, 6, 0, 1, 0, 7, 8],
13+
[0, 0, 7, 0, 4, 0, 2, 6, 0],
14+
[0, 0, 1, 0, 5, 0, 9, 3, 0],
15+
[9, 0, 4, 0, 6, 0, 0, 0, 5],
16+
[0, 7, 0, 3, 0, 0, 0, 1, 2],
17+
[1, 2, 0, 0, 0, 7, 4, 0, 0],
18+
[0, 4, 9, 2, 0, 6, 0, 0, 7]
19+
]
20+
21+
def __init__(self, rows, cols, width, height, win):
22+
self.rows = rows
23+
self.cols = cols
24+
self.cubes = [[Cube(self.board[i][j], i, j, width, height) for j in range(cols)] for i in range(rows)]
25+
self.width = width
26+
self.height = height
27+
self.model = None
28+
self.update_model()
29+
self.selected = None
30+
self.win = win
31+
32+
def update_model(self):
33+
self.model = [[self.cubes[i][j].value for j in range(self.cols)] for i in range(self.rows)]
34+
35+
def place(self, val):
36+
row, col = self.selected
37+
if self.cubes[row][col].value == 0:
38+
self.cubes[row][col].set(val)
39+
self.update_model()
40+
41+
if valid(self.model, val, (row, col)) and solve(self.model):
42+
return True
43+
else:
44+
self.cubes[row][col].set(0)
45+
self.cubes[row][col].set_temp(0)
46+
self.update_model()
47+
return False
48+
49+
def sketch(self, val):
50+
row, col = self.selected
51+
self.cubes[row][col].set_temp(val)
52+
53+
def draw(self):
54+
# Draw Grid Lines
55+
gap = self.width / 9
56+
for i in range(self.rows + 1):
57+
if i % 3 == 0 and i != 0:
58+
thick = 4
59+
else:
60+
thick = 1
61+
pygame.draw.line(self.win, (0, 0, 0), (0, i * gap), (self.width, i * gap), thick)
62+
pygame.draw.line(self.win, (0, 0, 0), (i * gap, 0), (i * gap, self.height), thick)
63+
64+
# Draw Cubes
65+
for i in range(self.rows):
66+
for j in range(self.cols):
67+
self.cubes[i][j].draw(self.win)
68+
69+
def select(self, row, col):
70+
# Reset all other
71+
for i in range(self.rows):
72+
for j in range(self.cols):
73+
self.cubes[i][j].selected = False
74+
75+
self.cubes[row][col].selected = True
76+
self.selected = (row, col)
77+
78+
def clear(self):
79+
row, col = self.selected
80+
if self.cubes[row][col].value == 0:
81+
self.cubes[row][col].set_temp(0)
82+
83+
def click(self, pos):
84+
"""
85+
:param: pos
86+
:return: (row, col)
87+
"""
88+
if pos[0] < self.width and pos[1] < self.height:
89+
gap = self.width / 9
90+
x = pos[0] // gap
91+
y = pos[1] // gap
92+
return int(y), int(x)
93+
else:
94+
return None
95+
96+
def is_finished(self):
97+
for i in range(self.rows):
98+
for j in range(self.cols):
99+
if self.cubes[i][j].value == 0:
100+
return False
101+
return True
102+
103+
def solve_gui(self):
104+
self.update_model()
105+
find = find_empty(self.model)
106+
if not find:
107+
return True
108+
else:
109+
row, col = find
110+
for i in range(1, 10):
111+
if valid(self.model, i, (row, col)):
112+
self.model[row][col] = i
113+
self.cubes[row][col].set(i)
114+
self.cubes[row][col].draw_change(self.win, True)
115+
self.update_model()
116+
pygame.display.update()
117+
pygame.time.delay(100)
118+
if self.solve_gui():
119+
return True
120+
self.model[row][col] = 0
121+
self.cubes[row][col].set(0)
122+
self.update_model()
123+
self.cubes[row][col].draw_change(self.win, False)
124+
pygame.display.update()
125+
pygame.time.delay(100)
126+
return False
127+
128+
129+
class Cube:
130+
rows = 9
131+
cols = 9
132+
133+
def __init__(self, value, row, col, width, height):
134+
self.value = value
135+
self.temp = 0
136+
self.row = row
137+
self.col = col
138+
self.width = width
139+
self.height = height
140+
self.selected = False
141+
142+
def draw(self, win):
143+
fnt = pygame.font.SysFont("comicsans", 40)
144+
145+
gap = self.width / 9
146+
x = self.col * gap
147+
y = self.row * gap
148+
149+
if self.temp != 0 and self.value == 0:
150+
text = fnt.render(str(self.temp), 1, (128, 128, 128))
151+
win.blit(text, (x + 5, y + 5))
152+
elif not (self.value == 0):
153+
text = fnt.render(str(self.value), 1, (0, 0, 0))
154+
win.blit(text, (x + (gap / 2 - text.get_width() / 2), y + (gap / 2 - text.get_height() / 2)))
155+
156+
if self.selected:
157+
pygame.draw.rect(win, (255, 0, 0), (x, y, gap, gap), 3)
158+
159+
def draw_change(self, win, g=True):
160+
fnt = pygame.font.SysFont("comicsans", 40)
161+
gap = self.width / 9
162+
x = self.col * gap
163+
y = self.row * gap
164+
pygame.draw.rect(win, (255, 255, 255), (x, y, gap, gap), 0)
165+
text = fnt.render(str(self.value), 1, (0, 0, 0))
166+
win.blit(text, (x + (gap/2 - text.get_width()/2), y + (gap/2 - text.get_height()/2)))
167+
if g:
168+
pygame.draw.rect(win, (0, 255, 0), (x, y, gap, gap), 3)
169+
else:
170+
pygame.draw.rect(win, (255, 0, 0), (x, y, gap, gap), 3)
171+
172+
def set(self, val):
173+
self.value = val
174+
175+
def set_temp(self, val):
176+
self.temp = val
177+
178+
179+
def redraw_window(win, board, time, strikes):
180+
win.fill((255, 255, 255))
181+
# Draw time
182+
fnt = pygame.font.SysFont("comicsans", 40)
183+
text = fnt.render("Time: " + format_time(time), 1, (0, 0, 0))
184+
win.blit(text, (540 - 160, 560))
185+
# Draw Strikes
186+
text = fnt.render("X " * strikes, 1, (255, 0, 0))
187+
win.blit(text, (20, 560))
188+
# Draw grid and board
189+
board.draw()
190+
191+
192+
def format_time(secs):
193+
sec = secs % 60
194+
minute = secs // 60
195+
hour = minute // 60
196+
197+
mat = str(hour) + ":" + str(minute) + ":" + str(sec)
198+
return mat
199+
200+
201+
def main():
202+
win = pygame.display.set_mode((540, 600))
203+
pygame.display.set_caption("Sudoku")
204+
board = Grid(9, 9, 540, 540, win)
205+
key = None
206+
run = True
207+
start = time.time()
208+
strikes = 0
209+
while run:
210+
211+
play_time = round(time.time() - start)
212+
213+
for event in pygame.event.get():
214+
if event.type == pygame.QUIT:
215+
run = False
216+
if event.type == pygame.KEYDOWN:
217+
if event.key == pygame.K_1:
218+
key = 1
219+
if event.key == pygame.K_2:
220+
key = 2
221+
if event.key == pygame.K_3:
222+
key = 3
223+
if event.key == pygame.K_4:
224+
key = 4
225+
if event.key == pygame.K_5:
226+
key = 5
227+
if event.key == pygame.K_6:
228+
key = 6
229+
if event.key == pygame.K_7:
230+
key = 7
231+
if event.key == pygame.K_8:
232+
key = 8
233+
if event.key == pygame.K_9:
234+
key = 9
235+
if event.key == pygame.K_KP1:
236+
key = 1
237+
if event.key == pygame.K_KP2:
238+
key = 2
239+
if event.key == pygame.K_KP3:
240+
key = 3
241+
if event.key == pygame.K_KP4:
242+
key = 4
243+
if event.key == pygame.K_KP5:
244+
key = 5
245+
if event.key == pygame.K_KP6:
246+
key = 6
247+
if event.key == pygame.K_KP7:
248+
key = 7
249+
if event.key == pygame.K_KP8:
250+
key = 8
251+
if event.key == pygame.K_KP9:
252+
key = 9
253+
if event.key == pygame.K_DELETE:
254+
board.clear()
255+
key = None
256+
257+
if event.key == pygame.K_SPACE:
258+
board.solve_gui()
259+
260+
if event.key == pygame.K_RETURN:
261+
i, j = board.selected
262+
if board.cubes[i][j].temp != 0:
263+
if board.place(board.cubes[i][j].temp):
264+
print("Success")
265+
else:
266+
print("Wrong")
267+
strikes += 1
268+
key = None
269+
270+
if board.is_finished():
271+
print("Game over")
272+
run = False
273+
274+
if event.type == pygame.MOUSEBUTTONDOWN:
275+
pos = pygame.mouse.get_pos()
276+
clicked = board.click(pos)
277+
if clicked:
278+
board.select(clicked[0], clicked[1])
279+
key = None
280+
281+
if board.selected and key is not None:
282+
board.sketch(key)
283+
284+
redraw_window(win, board, play_time, strikes)
285+
pygame.display.update()
286+
287+
288+
main()
289+
pygame.quit()

0 commit comments

Comments
 (0)