Amazing-Python-Scripts
217 строк · 7.5 Кб
1import tkinter as tk2from tkinter import messagebox, simpledialog3import random4
5
6class Sudoku:7def __init__(self, master):8self.master = master9self.board = [[0] * 9 for _ in range(9)]10self.solution = [[num for num in row] for row in self.board]11self.empty_cells = self.get_empty_cells(self.board)12self.create_widgets()13
14def create_widgets(self):15self.master.configure(bg='#ECECEC')16self.canvas = tk.Canvas(self.master, width=680,17height=680, bg='#F8C8DC', highlightthickness=0)18self.canvas.pack(side=tk.TOP, padx=0, pady=0)19
20self.draw_board()21
22self.button_frame = tk.Frame(self.master, bg='#ECECEC')23self.button_frame.pack(side=tk.TOP, pady=20)24
25self.check_button = tk.Button(self.button_frame, text='Check', font=('Inter', 12, 'bold'),26bg='#E75442', fg='#FFFFFF', bd=0, command=self.check_solution)27self.check_button.pack(side=tk.LEFT, padx=10)28
29self.solve_button = tk.Button(self.button_frame, text='Solve', font=('Inter', 12, 'bold'),30bg='#3AC6FF', fg='#FFFFFF', bd=0, command=self.solve_puzzle)31self.solve_button.pack(side=tk.LEFT, padx=10)32
33self.level_frame = tk.Frame(self.master, bg='#ECECEC')34self.level_frame.pack(side=tk.TOP, pady=0)35
36self.level_label = tk.Label(self.level_frame, text='Select Level:', font=(37'Inter', 12, "bold"), bg='#77DD77', fg='#ECECEC')38self.level_label.pack(side=tk.LEFT, padx=10)39
40self.level_var = tk.StringVar()41self.level_var.set('Easy')42self.level_dropdown = tk.OptionMenu(self.level_frame, self.level_var, 'Easy', 'Medium', 'Hard',43command=self.new_game)44self.level_dropdown.config(45font=('Arial', 12, "bold"), bg='#ffb347', fg='#ECECEC', bd=0)46self.level_dropdown.pack(side=tk.LEFT, padx=10)47
48self.new_game_button = tk.Button(self.level_frame, text='New Game', font=('Inter', 12, 'bold'),49bg='#FFD700', fg='#ECECEC', bd=0, command=self.new_game_wrapper)50self.new_game_button.pack(side=tk.LEFT, padx=10)51self.canvas.bind("<Button-1>", self.on_cell_click)52
53def new_game_wrapper(self):54level = self.level_var.get()55self.new_game(level)56
57def new_game(self, level):58if level == 'Easy':59num_cells = 4060elif level == 'Medium':61num_cells = 5062elif level == 'Hard':63num_cells = 6064
65self.board = [[0] * 9 for _ in range(9)]66self.generate_puzzle()67self.remove_cells(num_cells)68self.empty_cells = self.get_empty_cells(self.board)69self.draw_board()70
71def generate_puzzle(self):72self.solve_board(self.board)73for _ in range(81):74row = random.randint(0, 8)75col = random.randint(0, 8)76temp = self.board[row][col]77self.board[row][col] = 078count = 079solution_copy = [row[:] for row in self.board]80self.solve_board(solution_copy)81for i in range(9):82if 0 in solution_copy[i]:83count += 184if count != 1:85self.board[row][col] = temp86
87def solve_board(self, board):88empty_cell = self.get_empty_cell(board)89if not empty_cell:90return True91
92row, col = empty_cell93for num in range(1, 10):94if self.is_valid_move(board, row, col, num):95board[row][col] = num96if self.solve_board(board):97return True98board[row][col] = 099return False100
101def on_cell_click(self, event):102x, y = event.x, event.y103row, col = (y - 80) // 60, (x - 80) // 60104if self.board[row][col] != 0:105messagebox.showinfo(106'Invalid Move', 'Cannot change pre-filled cells!')107return108num = tk.simpledialog.askinteger(109'Input', 'Enter a number (1-9):', minvalue=1, maxvalue=9)110if num:111self.board[row][col] = num112self.draw_board()113
114def get_empty_cell(self, board):115for i in range(9):116for j in range(9):117if board[i][j] == 0:118return i, j119return None120
121def is_valid_move(self, board, row, col, num):122return (123self.is_valid_row(board, row, num)124and self.is_valid_col(board, col, num)125and self.is_valid_box(board, row - row % 3, col - col % 3, num)126)127
128def is_valid_row(self, board, row, num):129for i in range(9):130if board[row][i] == num:131return False132return True133
134def is_valid_col(self, board, col, num):135for i in range(9):136if board[i][col] == num:137return False138return True139
140def is_valid_box(self, board, start_row, start_col, num):141for i in range(3):142for j in range(3):143if board[start_row + i][start_col + j] == num:144return False145return True146
147def draw_board(self):148self.clear_board()149for i in range(9):150for j in range(9):151x = i * 60 + 80152y = j * 60 + 80153cell_value = self.board[j][i]154if cell_value != 0:155# Adjust the coordinates to avoid intersection156text_x = x + 15157text_y = y + 15158self.canvas.create_text(text_x, text_y, text=str(159cell_value), font=('Inter', 20, 'bold'), fill='#333333')160
161self.draw_grid()162
163def draw_grid(self):164for i in range(10):165if i % 3 == 0:166line_width = 2167else:168line_width = 1169self.canvas.create_line(17060 * i + 80, 80, 60 * i + 80, 620, width=line_width, fill='#333333')171self.canvas.create_line(17280, 60 * i + 80, 620, 60 * i + 80, width=line_width, fill='#333333')173
174def clear_board(self):175self.canvas.delete('all')176
177def check_solution(self):178for i in range(9):179for j in range(9):180if self.board[i][j] != self.solution[i][j]:181messagebox.showinfo(182'Incorrect', 'The solution is not correct!')183return184messagebox.showinfo(185'Correct', 'Congratulations! You solved the puzzle!')186
187def remove_cells(self, num_cells):188cells = [(i, j) for i in range(9) for j in range(9)]189random.shuffle(cells)190for i in range(num_cells):191row, col = cells[i]192self.board[row][col] = 0193
194def get_empty_cells(self, board):195empty_cells = []196for i in range(9):197for j in range(9):198if board[i][j] == 0:199empty_cells.append((i, j))200return empty_cells201
202def solve_puzzle(self):203solution_board = [row[:] for row in self.board]204if self.solve_board(solution_board):205self.solution = solution_board206self.board = solution_board207self.draw_board()208else:209messagebox.showinfo(210'Unsolvable', 'The puzzle does not have a solution.')211
212
213if __name__ == '__main__':214root = tk.Tk()215root.title('Sudoku')216gui = Sudoku(root)217root.mainloop()218