forked from zhoulisha/Sudoku-Project
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboard.py
195 lines (166 loc) · 7.81 KB
/
board.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
import pygame
from constants import *
from cell import Cell
from sudoku_generator import SudokuGenerator
class Board:
def __init__(self, width, height, screen, difficulty):
self.board = [[0 for _ in range(9)] for _ in range(9)]
self.width = 750
self.height = 900
self.screen = pygame.display.set_mode((width, height))
self.difficulty = difficulty
self.board_rows = 9
self.board_cols = 9
self.board_line_width = 5
self.cell_size = 82
# difficulty_levels = {"easy": 30, "medium": 40, "hard": 50}
# if self.difficulty in difficulty_levels:
# self.empty_cells = difficulty_levels[self.difficulty]
# else:
# raise ValueError("Invalid difficulty level")
self.original = [row[:] for row in self.board]
self.cells = [[Cell(self.board[row][col], row, col, self.screen)
for col in range(self.board_cols)]
for row in range(self.board_rows)]
self.selected = (0, 0)
def draw(self):
# Calculate the width and height of the board
BOARD_WIDTH = 9 * CELL_SIZE
BOARD_HEIGHT = 9 * CELL_SIZE
# Calculate the starting position
board_start_x = (WIDTH - BOARD_WIDTH) // 2
board_start_y = (HEIGHT - BOARD_HEIGHT) // 2 - 70 # move board up ~ 70 px
# Draw the cells
for row in self.cells:
for cell in row:
cell_rect = pygame.Rect(board_start_x + cell.col * CELL_SIZE, board_start_y + cell.row * CELL_SIZE,
CELL_SIZE, CELL_SIZE)
pygame.draw.rect(self.screen, SCREEN_COLOR, cell_rect)
cell.draw(self.screen)
# Draw the squares for the board
for i in range(0, 4):
pygame.draw.line(self.screen, BLACK,
(board_start_x, board_start_y + (3 * i) * CELL_SIZE),
(board_start_x + BOARD_WIDTH, board_start_y + (3 * i) * CELL_SIZE),
BOARD_LINE_WIDTH)
for i in range(0, 4):
pygame.draw.line(self.screen, BLACK,
(board_start_x + (3 * i) * CELL_SIZE, board_start_y),
(board_start_x + (3 * i) * CELL_SIZE, board_start_y + BOARD_HEIGHT),
BOARD_LINE_WIDTH)
# Marks the cell at (row, col) in the board as the current selected cell
def select(self, row, col):
for i in range(self.board_rows):
for j in range(self.board_cols):
if i == row and j == col:
self.cells[i][j].selected = True
else:
self.cells[i][j].selected = False
# returns a tuple of the (row, col) of the cell which was clicked
def click(self, x, y):
# Calculate the width and height of the board
BOARD_WIDTH = 9 * CELL_SIZE
BOARD_HEIGHT = 9 * CELL_SIZE
# Calculate the starting position
board_start_x = (WIDTH - BOARD_WIDTH) // 2
board_start_y = (HEIGHT - BOARD_HEIGHT) // 2 - 70 # move board up ~ 70 px
# if coordinates inside the board (which calculated by adding board's width and height to the starting points)
if board_start_x <= x < board_start_x + BOARD_WIDTH and board_start_y <= y < board_start_y + BOARD_HEIGHT:
clicked_row = (y - board_start_y) // CELL_SIZE
clicked_col = (x - board_start_x) // CELL_SIZE
return clicked_row, clicked_col
return None
# allows user to remove the cell values and sketched value that are filled by themselves
def clear(self):
for i in range(self.board_rows):
for j in range(self.board_cols):
if self.cells[i][j].selected:
# check if it's an empty cell in the original board
if self.board[i][j] == 0:
self.cells[i][j].sketched_value = 0
self.cells[i][j].value = 0
def sketch(self, value):
for row in range(self.board_rows):
for col in range(self.board_cols):
if self.cells[col][row].selected:
if self.board[col][row] == 0:
self.cells[col][row].set_sketched_value(value)
# sketched_val = str(value)
# font = pygame.font.SysFont('Times New Roman', 100)
# number_print = font.render(sketched_val, True, 'Grey')
# self.screen.blit(number_print, (selected_cell[0], selected_cell[1]))
# pygame.display.update()
def place_number(self, value):
#self.value = value
#sketched_val = str(self.value)
for row in range(self.board_rows):
for col in range(self.board_cols):
if self.cells[col][row].selected:
if self.board[col][row] == 0:
self.cells[col][row].set_cell_value(value)
self.cells[col][row].set_sketched_value(0)
self.board[col][row] = value # Update the board
self.draw() # Refresh the board display
# x = selected_cell[0] * 82
# y = selected_cell[1] * 82
# font = pygame.font.SysFont('Times New Roman', 50)
# number_print = font.render(sketched_val, True, 'Black')
# for event in pygame.event.get():
# if event.type == pygame.KEYDOWN:
# if event.key == pygame.K_RETURN:
# self.screen.blit(number_print, (x, y))
def reset_to_original(self):
for row in range(self.board_rows):
for col in range(self.board_cols):
if self.original[row][col] == 0: # If the cell was empty originally
self.board[row][col] = 0
# Recreate the cells to reflect the reset
self.cells = [[Cell(self.board[row][col], row, col, self.screen)
for col in range(self.board_cols)]
for row in range(self.board_rows)]
return self.cells
def is_full(self):
# self.board = [[0 for _ in range(9)] for _ in range(9)]
for row in self.board:
for cell in row:
if cell == 0:
return False
return True
def update_board(self):
# for row in self.board:
# for col in self.board:
# font = pygame.font.SysFont('Times New Roman', 50)
# number_print = font.render(str(self.value), True, 'Black')
# x = col * 82
# y = row * 82
# self.screen.blit(number_print, (x, y))
# pygame.display.update()
for row in range(self.board_rows):
for col in range(self.board_cols):
if self.cells[col][row].sketched_value != 0:
self.cells[col][row].value = self.cells[col][row].sketched_value
def find_empty(self):
# loop through cells and find empty, then return row and col as tuple
for row in self.board:
for col in self.board:
if self.board[row][col] == '0':
tup = (row, col)
return tup
def check_board(self):
def valid(values):
values = [v for v in values if v != 0]
return sorted(values) == list(range(1, 10))
for row in range(self.board_rows):
if not valid(self.board[row]):
return False
for col in range(self.board_cols):
if not valid(self.board[col]):
return False
for box_row in range(0, 9, 3):
for box_col in range(0, 9, 3):
box = [self.board[row][col]
for row in range(box_row, box_row + 3)
for col in range(box_col, box_col + 3)]
if not valid(box):
return False
return True