From b0fc2ef080405f31309eb4bd5fc46ba0547e4970 Mon Sep 17 00:00:00 2001 From: psparkyg Date: Fri, 19 Apr 2024 07:29:19 -0400 Subject: [PATCH 01/12] Added sudoku.py and updated sudoku_generator.py --- sudoku.py | 4 ++ sudoku_generator.py | 89 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 sudoku.py diff --git a/sudoku.py b/sudoku.py new file mode 100644 index 00000000..c68e8bf4 --- /dev/null +++ b/sudoku.py @@ -0,0 +1,4 @@ + +# This file will contain code to create the different screens of the project +# (game start, game over, and game in progress), and will form a cohesive project together +# with the rest of the code. \ No newline at end of file diff --git a/sudoku_generator.py b/sudoku_generator.py index 7ec18a59..3e3da08c 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -23,7 +23,10 @@ class SudokuGenerator: None ''' def __init__(self, row_length, removed_cells): - pass + self.row_length = row_length + self.removed_cells = removed_cells + self.board = [] + self.box_length = math.sqrt(self.row_length) ''' Returns a 2D python list of numbers which represents the board @@ -32,7 +35,7 @@ def __init__(self, row_length, removed_cells): Return: list[list] ''' def get_board(self): - pass + return list[self.board] ''' Displays the board to the console @@ -42,7 +45,7 @@ def get_board(self): Return: None ''' def print_board(self): - pass + print(self.board) ''' Determines if num is contained in the specified row (horizontal) of the board @@ -187,6 +190,84 @@ def fill_values(self): def remove_cells(self): pass +class Cell: + # Constructor for this class + def __int__(self, value, row, col, screen): + pass + + # Setter for this cell's value + def set_cell_value(self, value): + pass + + # Setter for this cell's sketched value + def set_sketched_value(self, value): + pass + + # Draws this cell, along with the value inside it. + # If this cell has a nonzero value, that value is displayed. + # Otherwise, no value is displayed in the cell. + # The cell is outlined red if it is currently selected + def draw(self): + pass + +class Board: + # Constructor for the Board class. + # screen is a window from PyGame. + # difficulty is a variable to indicate if the user chose easy, medium, or hard. + + def __init__(self, width, height, screen, difficulty): + pass + + # Draws an outline of the Sudoku grid, with bold lines to delineate the 3x3 boxes + # Draws every cell on this board. + def draw(self): + pass + + # Marks the cell at (row, col) in the board as the current selected cell. + # Once a cell has been selected, the user can edit its value or sketched value. + def select(self, row, col): + pass + + # If a tuple of (x, y) coordinates is within the displayed board, this function returns a tuple of the (row, col) + # of the cell which was clicked. Otherwise, this function returns None. + def click(self, x, y): + pass + + # Clears the value cell. Note that the user can only remove the cell values and sketched value that are + # filled by themselves. + def clear(self): + pass + + # Sets the sketched value of the current selected cell equal to user entered value. + # It will be displayed at the top left corner of the cell using the draw() function. + def sketch(self, value): + pass + + # Sets the value of the current selected cell equal to user entered value. + # Called when the user presses the Enter key. + def place_number(self, value): + pass + + # Reset all cells in the board to their original values (0 if cleared, otherwise the corresponding digit). + def reset_to_original(self): + pass + + # Returns a Boolean value indicating whether the board is full or not. + def is_full(self): + pass + + # Updates the underlying 2D board with the values in all cells. + def update_board(self): + pass + + # Finds an empty cell and returns its row and col as a tuple (x, y). + def find_empty(self): + pass + + # Check whether the Sudoku board is solved correctly. + def check_board(self): + pass + ''' DO NOT CHANGE Provided for students @@ -209,3 +290,5 @@ def generate_sudoku(size, removed): sudoku.remove_cells() board = sudoku.get_board() return board + +generate_sudoku(size=9,removed=0) From b37608a3570fc562a4ad1695384975e8485ef811 Mon Sep 17 00:00:00 2001 From: psparkyg Date: Fri, 19 Apr 2024 09:13:23 -0400 Subject: [PATCH 02/12] Updated sudoku_generator.py --- sudoku_generator.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index 3e3da08c..ebc3b0da 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -35,7 +35,7 @@ def __init__(self, row_length, removed_cells): Return: list[list] ''' def get_board(self): - return list[self.board] + pass ''' Displays the board to the console @@ -45,7 +45,7 @@ def get_board(self): Return: None ''' def print_board(self): - print(self.board) + pass ''' Determines if num is contained in the specified row (horizontal) of the board @@ -113,7 +113,7 @@ def is_valid(self, row, col, num): ''' def fill_box(self, row_start, col_start): pass - + ''' Fills the three boxes along the main diagonal of the board These are the boxes which start at (0,0), (3,3), and (6,6) @@ -154,7 +154,7 @@ def fill_remaining(self, row, col): col = 0 if row >= self.row_length: return True - + for num in range(1, self.row_length + 1): if self.is_valid(row, col, num): self.board[row][col] = num @@ -291,4 +291,4 @@ def generate_sudoku(size, removed): board = sudoku.get_board() return board -generate_sudoku(size=9,removed=0) +print(generate_sudoku(9,0)) From 3afbeb95ef65196039d04226e8746e82000be49a Mon Sep 17 00:00:00 2001 From: ADomonkos04 Date: Fri, 19 Apr 2024 19:54:00 -0400 Subject: [PATCH 03/12] This is the completed sudoku generator class, along with with constants modfiied from the tictactoe example --- sudoku.py | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/sudoku.py b/sudoku.py index c68e8bf4..d96a537d 100644 --- a/sudoku.py +++ b/sudoku.py @@ -1,4 +1,119 @@ +import random, pygame, sys +WIDTH = 540 +HEIGHT = 600 +LINE_WIDTH = 2 +BOARD_ROWS = 10 +BOARD_COLS = 9 +SQUARE_SIZE = 60 +RED = (255, 0, 0) +GRAY = (168, 168, 168) +BG_COLOR = (255, 255, 245) +LINE_COLOR = (0, 0, 0) +CHIP_COLOR = (171, 176, 172) +FIXED_CHIP_COLOR = (0, 0, 0) + + +class SudokuGenerator: + + def __init__(self, removed_cells, row_length=9): + self.row_length = row_length + self.removed_cells = removed_cells + self.box_length = 3 + self.board = [[" " for _ in range(self.row_length)] for _ in range(self.row_length)] + + def get_board(self): + return self.board + + def print_board(self): + print(self.board) + + def valid_in_row(self, row, num): + return num not in self.board[row] + + def valid_in_col(self, col, num): + for row in range(self.row_length): + if self.board[row][col] == num: + return False + return True + + def valid_in_box(self, row_start, col_start, num): + for row in range(3): + for col in range(3): + if self.board[row_start + row][col_start + col] == num: + return False + return True + + def is_valid(self, row, col, num): + return self.valid_in_row(row, num) and self.valid_in_col(col, num) and self.valid_in_box(row - row % 3, + col - col % 3, num) + + def unused_in_box(self, row_start, col_start, num): + for row in range(row_start, row_start + 3): + for col in range(col_start, col_start + 3): + if self.board[row][col] == num: + return False + return True + + def fill_box(self, row_start, col_start): + nums = list(range(1, self.row_length + 1)) + random.shuffle(nums) + for i in range(self.box_length): + for j in range(self.box_length): + self.board[row_start + i][col_start + j] = nums.pop() + + def fill_diagonal(self): + for i in range(0, self.row_length, 3): + self.fill_box(i, i) + + def fill_remaining(self, row, col): + if (col >= self.row_length and row < self.row_length - 1): + row += 1 + col = 0 + if row >= self.row_length and col >= self.row_length: + return True + if row < self.box_length: + if col < self.box_length: + col = self.box_length + elif row < self.row_length - self.box_length: + if col == int(row // self.box_length * self.box_length): + col += self.box_length + else: + if col == self.row_length - self.box_length: + row += 1 + col = 0 + if row >= self.row_length: + return True + + for num in range(1, self.row_length + 1): + if self.is_valid(row, col, num): + self.board[row][col] = num + if self.fill_remaining(row, col + 1): + return True + self.board[row][col] = 0 + return False + + def fill_values(self): + self.fill_diagonal() + self.fill_remaining(0, 3) + + def remove_cells(self): + for i in range(self.removed_cells): + row = random.randint(0, self.row_length - 1) + col = random.randint(0, self.row_length - 1) + while self.board[row][col] == 0: + row = random.randint(0, self.row_length - 1) + col = random.randint(0, self.row_length - 1) + self.board[row][col] = 0 + + +def generate_sudoku(size, removed): + sudoku = SudokuGenerator(size, removed) + sudoku.fill_values() + board = sudoku.get_board() + sudoku.remove_cells() + board = sudoku.get_board() + return board # This file will contain code to create the different screens of the project # (game start, game over, and game in progress), and will form a cohesive project together # with the rest of the code. \ No newline at end of file From 041b083c521831c53a8dd891c751e4ec26ad3b8d Mon Sep 17 00:00:00 2001 From: ADomonkos04 Date: Sun, 21 Apr 2024 19:52:33 -0400 Subject: [PATCH 04/12] Made functions for game won and game over screens to be implemented later in the main code --- sudoku.py | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/sudoku.py b/sudoku.py index d96a537d..150270aa 100644 --- a/sudoku.py +++ b/sudoku.py @@ -114,6 +114,87 @@ def generate_sudoku(size, removed): sudoku.remove_cells() board = sudoku.get_board() return board -# This file will contain code to create the different screens of the project -# (game start, game over, and game in progress), and will form a cohesive project together -# with the rest of the code. \ No newline at end of file + +def draw_menu(screen): + start_title_font = pygame.font.Font(None, 70) + select_title_font = pygame.font.Font(None, 55) + button_font = pygame.font.Font(None, 40) + + screen.fill(BG_COLOR) + + title_surf = start_title_font.render("Welcome to Sudoku", 1, LINE_COLOR) + title_rect = title_surf.get_rect(center=(WIDTH//2, HEIGHT//2-150)) + screen.blit(title_surf, title_rect) + + select_title_surf = select_title_font.render("Select Game Mode:", 1, LINE_COLOR) + select_title_rect = select_title_surf.get_rect(center=(WIDTH//2, HEIGHT//2)) + screen.blit(select_title_surf, select_title_rect) + + + easy=button_font.render("Easy",0,(255,255,255)) + med=button_font.render("Medium",0,(255,255,255)) + hard=button_font.render("Hard",0,(255,255,255)) + + easy_surf=pygame.Surface((easy.get_size()[0]+20,easy.get_size()[1]+20)) + easy_surf.fill(LINE_COLOR) + easy_surf.blit(easy,(10,10)) + med_surf = pygame.Surface((med.get_size()[0] + 20, med.get_size()[1] + 20)) + med_surf.fill(LINE_COLOR) + med_surf.blit(med, (10, 10)) + hard_surf = pygame.Surface((hard.get_size()[0] + 20, hard.get_size()[1] + 20)) + hard_surf.fill(LINE_COLOR) + hard_surf.blit(hard, (10, 10)) + + + easy_rect=easy.get_rect(center=(WIDTH//2-120,HEIGHT//2+100)) + med_rect=med.get_rect(center=(WIDTH//2,HEIGHT//2+100)) + hard_rect=hard.get_rect(center=(WIDTH//2+120,HEIGHT//2+100)) + + screen.blit(easy_surf,easy_rect) + screen.blit(med_surf, med_rect) + screen.blit(hard_surf, hard_rect) + + + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + elif event.type == pygame.MOUSEBUTTONDOWN: + if easy_rect.collidepoint(event.pos): + return 'easy' + elif med_rect.collidepoint(event.pos): + return 'medium' + elif hard_rect.collidepoint(event.pos): + return 'hard' + pygame.display.update() + +def draw_game_over(screen): + game_over_font = pygame.font.Font(None, 100) + button_font = pygame.font.Font(None, 40) + screen.fill(BG_COLOR) + if win: + text="Game Won!" + else: + text = "Game Over :(" + game_over_surf = game_over_font.render(text, 0, LINE_COLOR) + game_over_rect = game_over_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) + screen.blit(game_over_surf, game_over_rect) + + if win: + exit_text=button_font.render("EXIT",0,(255,255,255)) + exit_surf=pygame.Surface((exit_text.get_size()[0]+20,exit_text.get_size()[1]+20)) + exit_surf.fill(LINE_COLOR) + exit_surf.blit(exit_text,(10,10)) + exit_rect=exit_surf.get_rect(center=(WIDTH//2+135,570)) + screen.blit(exit_surf,exit_rect) + + else: + restart_text = button_font.render("RESTART", 0, (255, 255, 255)) + restart_surf = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) + restart_surf.fill(LINE_COLOR) + restart_surf.blit(restart_text, (10, 10)) + restart_rect = restart_surf.get_rect(center=(WIDTH//2, 570)) + screen.blit(restart_surf, restart_rect) + From 32c07ecd821e13b94750ae47095ca080ce269610 Mon Sep 17 00:00:00 2001 From: psparkyg Date: Mon, 22 Apr 2024 15:51:52 -0400 Subject: [PATCH 05/12] Overhauled every script and created game board --- sudoku.py | 272 +++++++++++++---------------------------- sudoku_generator.py | 287 ++++++++++++++++---------------------------- 2 files changed, 189 insertions(+), 370 deletions(-) diff --git a/sudoku.py b/sudoku.py index 150270aa..10038d2b 100644 --- a/sudoku.py +++ b/sudoku.py @@ -1,200 +1,96 @@ -import random, pygame, sys +import pygame +import sudoku_generator -WIDTH = 540 +pygame.init() + +# Screen constants +WIDTH = 500 HEIGHT = 600 -LINE_WIDTH = 2 -BOARD_ROWS = 10 -BOARD_COLS = 9 -SQUARE_SIZE = 60 -RED = (255, 0, 0) -GRAY = (168, 168, 168) -BG_COLOR = (255, 255, 245) -LINE_COLOR = (0, 0, 0) -CHIP_COLOR = (171, 176, 172) -FIXED_CHIP_COLOR = (0, 0, 0) - - -class SudokuGenerator: - - def __init__(self, removed_cells, row_length=9): - self.row_length = row_length - self.removed_cells = removed_cells - self.box_length = 3 - self.board = [[" " for _ in range(self.row_length)] for _ in range(self.row_length)] - - def get_board(self): - return self.board - - def print_board(self): - print(self.board) - - def valid_in_row(self, row, num): - return num not in self.board[row] - - def valid_in_col(self, col, num): - for row in range(self.row_length): - if self.board[row][col] == num: - return False - return True - - def valid_in_box(self, row_start, col_start, num): - for row in range(3): - for col in range(3): - if self.board[row_start + row][col_start + col] == num: - return False - return True - - def is_valid(self, row, col, num): - return self.valid_in_row(row, num) and self.valid_in_col(col, num) and self.valid_in_box(row - row % 3, - col - col % 3, num) - - def unused_in_box(self, row_start, col_start, num): - for row in range(row_start, row_start + 3): - for col in range(col_start, col_start + 3): - if self.board[row][col] == num: - return False - return True - - def fill_box(self, row_start, col_start): - nums = list(range(1, self.row_length + 1)) - random.shuffle(nums) - for i in range(self.box_length): - for j in range(self.box_length): - self.board[row_start + i][col_start + j] = nums.pop() - - def fill_diagonal(self): - for i in range(0, self.row_length, 3): - self.fill_box(i, i) - - def fill_remaining(self, row, col): - if (col >= self.row_length and row < self.row_length - 1): - row += 1 - col = 0 - if row >= self.row_length and col >= self.row_length: - return True - if row < self.box_length: - if col < self.box_length: - col = self.box_length - elif row < self.row_length - self.box_length: - if col == int(row // self.box_length * self.box_length): - col += self.box_length - else: - if col == self.row_length - self.box_length: - row += 1 - col = 0 - if row >= self.row_length: - return True - - for num in range(1, self.row_length + 1): - if self.is_valid(row, col, num): - self.board[row][col] = num - if self.fill_remaining(row, col + 1): - return True - self.board[row][col] = 0 - return False - - def fill_values(self): - self.fill_diagonal() - self.fill_remaining(0, 3) - - def remove_cells(self): - for i in range(self.removed_cells): - row = random.randint(0, self.row_length - 1) - col = random.randint(0, self.row_length - 1) - while self.board[row][col] == 0: - row = random.randint(0, self.row_length - 1) - col = random.randint(0, self.row_length - 1) - self.board[row][col] = 0 - - -def generate_sudoku(size, removed): - sudoku = SudokuGenerator(size, removed) - sudoku.fill_values() - board = sudoku.get_board() - sudoku.remove_cells() - board = sudoku.get_board() - return board - -def draw_menu(screen): - start_title_font = pygame.font.Font(None, 70) - select_title_font = pygame.font.Font(None, 55) - button_font = pygame.font.Font(None, 40) - - screen.fill(BG_COLOR) - - title_surf = start_title_font.render("Welcome to Sudoku", 1, LINE_COLOR) - title_rect = title_surf.get_rect(center=(WIDTH//2, HEIGHT//2-150)) - screen.blit(title_surf, title_rect) - - select_title_surf = select_title_font.render("Select Game Mode:", 1, LINE_COLOR) - select_title_rect = select_title_surf.get_rect(center=(WIDTH//2, HEIGHT//2)) - screen.blit(select_title_surf, select_title_rect) - - - easy=button_font.render("Easy",0,(255,255,255)) - med=button_font.render("Medium",0,(255,255,255)) - hard=button_font.render("Hard",0,(255,255,255)) - - easy_surf=pygame.Surface((easy.get_size()[0]+20,easy.get_size()[1]+20)) - easy_surf.fill(LINE_COLOR) - easy_surf.blit(easy,(10,10)) - med_surf = pygame.Surface((med.get_size()[0] + 20, med.get_size()[1] + 20)) - med_surf.fill(LINE_COLOR) - med_surf.blit(med, (10, 10)) +SCREEN = pygame.display.set_mode([HEIGHT,WIDTH]) + +# Colors +WHITE = (255,255,255) +BLACK = (0,0,0) +GREY = (192,192,192) + +DIFFICULTY = None + +# Game initializer +DB = False +clock = pygame.time.Clock() + +# Window caption +pygame.display.set_caption("Sudoku") + +# Fonts +start_title_font = pygame.font.Font(None, 70) +select_title_font = pygame.font.Font(None, 55) +button_font = pygame.font.Font(None, 40) + +difficulty_chart = { + "Easy" : 30, + "Medium" : 40, + "Hard" : 50 +} + +if __name__ == "__main__": + SCREEN.fill(GREY) + + title_surf = start_title_font.render("Welcome to Sudoku", 1, BLACK) + title_rect = title_surf.get_rect(center=(WIDTH // 2 + 35, HEIGHT // 2 - 150)) + SCREEN.blit(title_surf, title_rect) + + select_title_surf = select_title_font.render("Select Game Mode:", 1, BLACK) + select_title_rect = select_title_surf.get_rect(center=(WIDTH // 2 + 35, HEIGHT // 2 - 50)) + SCREEN.blit(select_title_surf, select_title_rect) + + easy = button_font.render("Easy", 0, (255, 255, 255)) + medium = button_font.render("Medium", 0, (255, 255, 255)) + hard = button_font.render("Hard", 0, (255, 255, 255)) + + easy_surf = pygame.Surface((easy.get_size()[0] + 20, easy.get_size()[1] + 20)) + easy_surf.fill(BLACK) + easy_surf.blit(easy, (10, 10)) + med_surf = pygame.Surface((medium.get_size()[0] + 20, medium.get_size()[1] + 20)) + med_surf.fill(BLACK) + med_surf.blit(medium, (10, 10)) hard_surf = pygame.Surface((hard.get_size()[0] + 20, hard.get_size()[1] + 20)) - hard_surf.fill(LINE_COLOR) + hard_surf.fill(BLACK) hard_surf.blit(hard, (10, 10)) + easy_rect = easy.get_rect(center=(WIDTH // 2 - 100, HEIGHT // 2 + 25)) + med_rect = medium.get_rect(center=(WIDTH // 2 + 25, HEIGHT // 2 + 25)) + hard_rect = hard.get_rect(center=(WIDTH // 2 + 150, HEIGHT // 2 + 25)) - easy_rect=easy.get_rect(center=(WIDTH//2-120,HEIGHT//2+100)) - med_rect=med.get_rect(center=(WIDTH//2,HEIGHT//2+100)) - hard_rect=hard.get_rect(center=(WIDTH//2+120,HEIGHT//2+100)) - - screen.blit(easy_surf,easy_rect) - screen.blit(med_surf, med_rect) - screen.blit(hard_surf, hard_rect) + SCREEN.blit(easy_surf, easy_rect) + SCREEN.blit(med_surf, med_rect) + SCREEN.blit(hard_surf, hard_rect) + while DB == False: + clock.tick(60) + mpos = pygame.mouse.get_pos() - while True: for event in pygame.event.get(): if event.type == pygame.QUIT: - pygame.quit() - sys.exit() + DB = True elif event.type == pygame.MOUSEBUTTONDOWN: - if easy_rect.collidepoint(event.pos): - return 'easy' - elif med_rect.collidepoint(event.pos): - return 'medium' - elif hard_rect.collidepoint(event.pos): - return 'hard' - pygame.display.update() - -def draw_game_over(screen): - game_over_font = pygame.font.Font(None, 100) - button_font = pygame.font.Font(None, 40) - screen.fill(BG_COLOR) - if win: - text="Game Won!" - else: - text = "Game Over :(" - game_over_surf = game_over_font.render(text, 0, LINE_COLOR) - game_over_rect = game_over_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) - screen.blit(game_over_surf, game_over_rect) - - if win: - exit_text=button_font.render("EXIT",0,(255,255,255)) - exit_surf=pygame.Surface((exit_text.get_size()[0]+20,exit_text.get_size()[1]+20)) - exit_surf.fill(LINE_COLOR) - exit_surf.blit(exit_text,(10,10)) - exit_rect=exit_surf.get_rect(center=(WIDTH//2+135,570)) - screen.blit(exit_surf,exit_rect) - - else: - restart_text = button_font.render("RESTART", 0, (255, 255, 255)) - restart_surf = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) - restart_surf.fill(LINE_COLOR) - restart_surf.blit(restart_text, (10, 10)) - restart_rect = restart_surf.get_rect(center=(WIDTH//2, 570)) - screen.blit(restart_surf, restart_rect) - + if easy_rect.collidepoint(mpos): + DIFFICULTY = "Easy" + SCREEN.fill(GREY) + board = sudoku_generator.Board(50, 40, SCREEN, difficulty_chart["Easy"]) + board.draw() + elif med_rect.collidepoint(mpos): + DIFFICULTY = "Medium" + SCREEN.fill(GREY) + board = sudoku_generator.Board(50, 40, SCREEN, difficulty_chart["Medium"]) + board.draw() + elif hard_rect.collidepoint(mpos): + DIFFICULTY = "Hard" + SCREEN.fill(GREY) + board = sudoku_generator.Board(50, 40, SCREEN, difficulty_chart["Hard"]) + board.draw() + else: + DIFFICULTY = None + + pygame.display.flip() diff --git a/sudoku_generator.py b/sudoku_generator.py index ebc3b0da..22a1becf 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -1,141 +1,60 @@ -import math,random - -""" -This was adapted from a GeeksforGeeks article "Program for Sudoku Generator" by Aarti_Rathi and Ankur Trisal -https://www.geeksforgeeks.org/program-sudoku-generator/ - -""" +import math +import random +import pygame class SudokuGenerator: - ''' - create a sudoku board - initialize class variables and set up the 2D board - This should initialize: - self.row_length - the length of each row - self.removed_cells - the total number of cells to be removed - self.board - a 2D list of ints to represent the board - self.box_length - the square root of row_length - - Parameters: - row_length is the number of rows/columns of the board (always 9 for this project) - removed_cells is an integer value - the number of cells to be removed - - Return: - None - ''' def __init__(self, row_length, removed_cells): self.row_length = row_length self.removed_cells = removed_cells - self.board = [] - self.box_length = math.sqrt(self.row_length) - - ''' - Returns a 2D python list of numbers which represents the board + self.board = [[" " for _ in range(self.row_length)] for _ in range(self.row_length)] + self.box_length = int(math.sqrt(self.row_length)) - Parameters: None - Return: list[list] - ''' def get_board(self): - pass - - ''' - Displays the board to the console - This is not strictly required, but it may be useful for debugging purposes + return self.board - Parameters: None - Return: None - ''' def print_board(self): - pass - - ''' - Determines if num is contained in the specified row (horizontal) of the board - If num is already in the specified row, return False. Otherwise, return True + for row in self.get_board(): + for col in row: + print(col,end=" ") + print() - Parameters: - row is the index of the row we are checking - num is the value we are looking for in the row - - Return: boolean - ''' def valid_in_row(self, row, num): - pass + return num not in self.board[row] - ''' - Determines if num is contained in the specified column (vertical) of the board - If num is already in the specified col, return False. Otherwise, return True - - Parameters: - col is the index of the column we are checking - num is the value we are looking for in the column - - Return: boolean - ''' def valid_in_col(self, col, num): - pass + for row in range(self.row_length): + if self.board[row][col] == num: + return False + return True - ''' - Determines if num is contained in the 3x3 box specified on the board - If num is in the specified box starting at (row_start, col_start), return False. - Otherwise, return True - - Parameters: - row_start and col_start are the starting indices of the box to check - i.e. the box is from (row_start, col_start) to (row_start+2, col_start+2) - num is the value we are looking for in the box - - Return: boolean - ''' def valid_in_box(self, row_start, col_start, num): - pass - - ''' - Determines if it is valid to enter num at (row, col) in the board - This is done by checking that num is unused in the appropriate, row, column, and box + for row in range(self.box_length): + for col in range(self.box_length): + if self.board[row_start + row][col_start + col] == num: + return False + return True - Parameters: - row and col are the row index and col index of the cell to check in the board - num is the value to test if it is safe to enter in this cell - - Return: boolean - ''' def is_valid(self, row, col, num): - pass + return self.valid_in_row(row, num) and self.valid_in_col(col, num) and self.valid_in_box(row - row % 3, col - col % 3, num) - ''' - Fills the specified 3x3 box with values - For each position, generates a random digit which has not yet been used in the box + # def unused_in_box(self, row_start, col_start, num): + # for row in range(row_start, row_start + 3): + # for col in range(col_start, col_start + 3): + # if self.board[row][col] == num: + # return False + # return True - Parameters: - row_start and col_start are the starting indices of the box to check - i.e. the box is from (row_start, col_start) to (row_start+2, col_start+2) - - Return: None - ''' def fill_box(self, row_start, col_start): - pass - - ''' - Fills the three boxes along the main diagonal of the board - These are the boxes which start at (0,0), (3,3), and (6,6) + nums = list(range(1, self.row_length + 1)) + random.shuffle(nums) + for i in range(self.box_length): + for j in range(self.box_length): + self.board[row_start + i][col_start + j] = nums.pop() - Parameters: None - Return: None - ''' def fill_diagonal(self): - pass + for i in range(0, self.row_length, 3): + self.fill_box(i, i) - ''' - DO NOT CHANGE - Provided for students - Fills the remaining cells of the board - Should be called after the diagonal boxes have been filled - - Parameters: - row, col specify the coordinates of the first empty (0) cell - - Return: - boolean (whether or not we could solve the board) - ''' def fill_remaining(self, row, col): if (col >= self.row_length and row < self.row_length - 1): row += 1 @@ -163,65 +82,85 @@ def fill_remaining(self, row, col): self.board[row][col] = 0 return False - ''' - DO NOT CHANGE - Provided for students - Constructs a solution by calling fill_diagonal and fill_remaining - - Parameters: None - Return: None - ''' def fill_values(self): self.fill_diagonal() - self.fill_remaining(0, self.box_length) - - ''' - Removes the appropriate number of cells from the board - This is done by setting some values to 0 - Should be called after the entire solution has been constructed - i.e. after fill_values has been called - - NOTE: Be careful not to 'remove' the same cell multiple times - i.e. if a cell is already 0, it cannot be removed again - - Parameters: None - Return: None - ''' + self.fill_remaining(0,3) + def remove_cells(self): - pass + for i in range(self.removed_cells): + row = random.randint(0, self.row_length - 1) + col = random.randint(0, self.row_length - 1) + while self.board[row][col] == 0: + row = random.randint(0, self.row_length - 1) + col = random.randint(0, self.row_length - 1) + self.board[row][col] = 0 + +# class Cell: +# # Constructor for this class +# def __int__(self, value, row, col, screen): +# self.value = value +# self.row = row +# self.col = col +# self.screen = screen +# +# # Setter for this cell's value +# def set_cell_value(self, value): +# pass +# +# # Setter for this cell's sketched value +# def set_sketched_value(self, value): +# pass +# +# # Draws this cell, along with the value inside it. +# # If this cell has a nonzero value, that value is displayed. +# # Otherwise, no value is displayed in the cell. +# # The cell is outlined red if it is currently selected +# def draw(self): +# pass + +class Board(): -class Cell: - # Constructor for this class - def __int__(self, value, row, col, screen): - pass + def __init__(self, width, height, screen, difficulty): + self.width = width + self.height = height + self.screen = screen + self.difficulty = difficulty + self.row, self.col = 9,9 + self.color = (0,0,0) + self.board = generate_sudoku(9,difficulty) + self.margin = 1 - # Setter for this cell's value - def set_cell_value(self, value): - pass + # Draws an outline of the Sudoku grid, with bold lines to delineate the 3x3 boxes + # Draws every cell on this board. + def draw(self): + for rows in range(self.row): + for cols in range(self.col): - # Setter for this cell's sketched value - def set_sketched_value(self, value): - pass + if str(self.board[rows][cols]) != "0": + x = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * cols + self.margin,(self.margin + self.height) * rows + self.margin,self.width, self.height], 1) + font = pygame.font.Font(None, 25) - # Draws this cell, along with the value inside it. - # If this cell has a nonzero value, that value is displayed. - # Otherwise, no value is displayed in the cell. - # The cell is outlined red if it is currently selected - def draw(self): - pass + cell_text = font.render(str(self.board[rows][cols]), True, self.color) + x_rect = cell_text.get_rect(center=x.center) + self.screen.blit(cell_text, x_rect) + else: + x = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * cols + self.margin, (self.margin + self.height) * rows + self.margin, self.width, self.height], 1) + font = pygame.font.Font(None, 25) -class Board: - # Constructor for the Board class. - # screen is a window from PyGame. - # difficulty is a variable to indicate if the user chose easy, medium, or hard. + cell_text = font.render("", True, self.color) + x_rect = cell_text.get_rect(center=x.center) + self.screen.blit(cell_text, x_rect) - def __init__(self, width, height, screen, difficulty): - pass + pygame.draw.line(self.screen, self.color, [0, 122], [457, 122], 2) + pygame.draw.line(self.screen, self.color, [0, 246], [457, 246], 2) + pygame.draw.line(self.screen, self.color, [0, 368], [457, 368], 2) + + pygame.draw.line(self.screen, self.color, [153, 0], [153, 368], 2) + pygame.draw.line(self.screen, self.color, [305, 0], [305, 368], 2) - # Draws an outline of the Sudoku grid, with bold lines to delineate the 3x3 boxes - # Draws every cell on this board. - def draw(self): - pass + + def board_solution(self): + return # Marks the cell at (row, col) in the board as the current selected cell. # Once a cell has been selected, the user can edit its value or sketched value. @@ -268,27 +207,11 @@ def find_empty(self): def check_board(self): pass -''' -DO NOT CHANGE -Provided for students -Given a number of rows and number of cells to remove, this function: -1. creates a SudokuGenerator -2. fills its values and saves this as the solved state -3. removes the appropriate number of cells -4. returns the representative 2D Python Lists of the board and solution - -Parameters: -size is the number of rows/columns of the board (9 for this project) -removed is the number of cells to clear (set to 0) - -Return: list[list] (a 2D Python list to represent the board) -''' def generate_sudoku(size, removed): sudoku = SudokuGenerator(size, removed) sudoku.fill_values() board = sudoku.get_board() sudoku.remove_cells() board = sudoku.get_board() - return board - -print(generate_sudoku(9,0)) + sudoku.print_board() + return board \ No newline at end of file From 55de09c6e8561f36d68195a5bd8bdf8a98c8eada Mon Sep 17 00:00:00 2001 From: psparkyg Date: Tue, 23 Apr 2024 15:35:52 -0400 Subject: [PATCH 06/12] Updated code. --- sudoku.py | 87 +++++++++++++++++++++------ sudoku_generator.py | 141 ++++++++++++++++++++++++++------------------ 2 files changed, 154 insertions(+), 74 deletions(-) diff --git a/sudoku.py b/sudoku.py index 10038d2b..aa3ca1bb 100644 --- a/sudoku.py +++ b/sudoku.py @@ -1,5 +1,6 @@ import pygame import sudoku_generator +from tkinter import * pygame.init() @@ -12,11 +13,13 @@ WHITE = (255,255,255) BLACK = (0,0,0) GREY = (192,192,192) +RED = (250,160,160) DIFFICULTY = None # Game initializer DB = False +menu_showed = False clock = pygame.time.Clock() # Window caption @@ -75,22 +78,72 @@ if event.type == pygame.QUIT: DB = True elif event.type == pygame.MOUSEBUTTONDOWN: - if easy_rect.collidepoint(mpos): - DIFFICULTY = "Easy" - SCREEN.fill(GREY) - board = sudoku_generator.Board(50, 40, SCREEN, difficulty_chart["Easy"]) - board.draw() - elif med_rect.collidepoint(mpos): - DIFFICULTY = "Medium" - SCREEN.fill(GREY) - board = sudoku_generator.Board(50, 40, SCREEN, difficulty_chart["Medium"]) - board.draw() - elif hard_rect.collidepoint(mpos): - DIFFICULTY = "Hard" - SCREEN.fill(GREY) - board = sudoku_generator.Board(50, 40, SCREEN, difficulty_chart["Hard"]) - board.draw() + if menu_showed == False: + if easy_rect.collidepoint(mpos): + DIFFICULTY = "Easy" + SCREEN.fill(GREY) + + board_list = sudoku_generator.generate_sudoku(9, difficulty_chart["Easy"]) + board = sudoku_generator.Board(SCREEN, board_list) + board.draw() + + menu_showed = True + elif med_rect.collidepoint(mpos): + DIFFICULTY = "Medium" + SCREEN.fill(GREY) + + board_list = sudoku_generator.generate_sudoku(9, difficulty_chart["Medium"]) + board = sudoku_generator.Board(SCREEN, board_list) + board.draw() + + menu_showed = True + elif hard_rect.collidepoint(mpos): + DIFFICULTY = "Hard" + SCREEN.fill(GREY) + + board_list = sudoku_generator.generate_sudoku(9, difficulty_chart["Hard"]) + board = sudoku_generator.Board(SCREEN, board_list) + board.draw() + + menu_showed = True else: - DIFFICULTY = None - pygame.display.flip() + for index in range(0, len(sudoku_generator.empty_locations), 2): + x = pygame.Rect(sudoku_generator.empty_locations[index]) + + if x.collidepoint(mpos): + + root = Tk() + root.geometry("60x60") + + def save_input(): + INPUT = inputtxt.get("1.0", "end-1c") + + if sudoku_generator.empty_locations[index + 1][2] == True: + print(f"This cell can be edited. Changing the value to {INPUT}") + + pygame.draw.rect(SCREEN, RED, x) + + r,c = sudoku_generator.empty_locations[index + 1][0], sudoku_generator.empty_locations[index + 1][1] + + board.board[r][c] = int(INPUT) + else: + print("This cell cannot be edited!") + + root.destroy() + + l = Label(root, text="Input #") + + inputtxt = Text(root, height=1, width=10, bg="Grey") + + submit_button = Button(root, height=3, width=5, text="Submit", command=lambda:save_input()) + + l.pack() + inputtxt.pack() + submit_button.pack() + + root.mainloop() + + board.draw() + + pygame.display.flip() \ No newline at end of file diff --git a/sudoku_generator.py b/sudoku_generator.py index 22a1becf..d80485ec 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -2,6 +2,9 @@ import random import pygame +empty_locations = [] +puzzle_solution = [] + class SudokuGenerator: def __init__(self, row_length, removed_cells): self.row_length = row_length @@ -37,13 +40,6 @@ def valid_in_box(self, row_start, col_start, num): def is_valid(self, row, col, num): return self.valid_in_row(row, num) and self.valid_in_col(col, num) and self.valid_in_box(row - row % 3, col - col % 3, num) - # def unused_in_box(self, row_start, col_start, num): - # for row in range(row_start, row_start + 3): - # for col in range(col_start, col_start + 3): - # if self.board[row][col] == num: - # return False - # return True - def fill_box(self, row_start, col_start): nums = list(range(1, self.row_length + 1)) random.shuffle(nums) @@ -87,6 +83,7 @@ def fill_values(self): self.fill_remaining(0,3) def remove_cells(self): + for i in range(self.removed_cells): row = random.randint(0, self.row_length - 1) col = random.randint(0, self.row_length - 1) @@ -95,61 +92,96 @@ def remove_cells(self): col = random.randint(0, self.row_length - 1) self.board[row][col] = 0 -# class Cell: -# # Constructor for this class -# def __int__(self, value, row, col, screen): -# self.value = value -# self.row = row -# self.col = col -# self.screen = screen -# -# # Setter for this cell's value -# def set_cell_value(self, value): -# pass -# -# # Setter for this cell's sketched value -# def set_sketched_value(self, value): -# pass -# -# # Draws this cell, along with the value inside it. -# # If this cell has a nonzero value, that value is displayed. -# # Otherwise, no value is displayed in the cell. -# # The cell is outlined red if it is currently selected -# def draw(self): -# pass - -class Board(): - - def __init__(self, width, height, screen, difficulty): - self.width = width - self.height = height +class Cell: + # Constructor for this class + def __init__(self, value, row, col, screen, board, count): + self.value = value + self.row = row + self.col = col + self.screen = screen + self.board = board + self.color = (0,0,0) + self.margin = 1 + self.width = 50 + self.height = 40 + self.count = count + self.can_edit = False + + def data(self): + return (self.row, self.col, self.width, self.height) + + def draw(self): + global empty_locations + + if self.count <= 1: + if self.value != "0": + z = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * self.col + self.margin, + (self.margin + self.height) * self.row + self.margin, + self.width, self.height], 1) + font = pygame.font.Font(None, 25) + + cell_text = font.render(str(self.board[self.row][self.col]), True, self.color) + z_rect = cell_text.get_rect(center=z.center) + self.screen.blit(cell_text, z_rect) + + self.can_edit = False + else: + z = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * self.col + self.margin, + (self.margin + self.height) * self.row + self.margin, + self.width, self.height], 1) + font = pygame.font.Font(None, 25) + + cell_text = font.render("", True, self.color) + z_rect = cell_text.get_rect(center=z.center) + self.screen.blit(cell_text, z_rect) + + self.can_edit = True + + empty_locations.append((z.x, z.y, z.width, z.height)) + empty_locations.append((self.row, self.col, self.can_edit)) + else: + if self.value != "0": + z = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * self.col + self.margin, + (self.margin + self.height) * self.row + self.margin, + self.width, self.height], 1) + font = pygame.font.Font(None, 25) + + cell_text = font.render(str(self.board[self.row][self.col]), True, self.color) + z_rect = cell_text.get_rect(center=z.center) + self.screen.blit(cell_text, z_rect) + + self.can_edit = False + else: + z = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * self.col + self.margin, + (self.margin + self.height) * self.row + self.margin, + self.width, self.height], 1) + font = pygame.font.Font(None, 25) + + cell_text = font.render("", True, self.color) + z_rect = cell_text.get_rect(center=z.center) + self.screen.blit(cell_text, z_rect) + + self.can_edit = True + +class Board: + def __init__(self, screen, board): self.screen = screen - self.difficulty = difficulty + self.difficulty = board self.row, self.col = 9,9 self.color = (0,0,0) - self.board = generate_sudoku(9,difficulty) + self.board = board self.margin = 1 + self.count = 0 - # Draws an outline of the Sudoku grid, with bold lines to delineate the 3x3 boxes - # Draws every cell on this board. def draw(self): + self.count += 1 + for rows in range(self.row): for cols in range(self.col): - if str(self.board[rows][cols]) != "0": - x = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * cols + self.margin,(self.margin + self.height) * rows + self.margin,self.width, self.height], 1) - font = pygame.font.Font(None, 25) + indiv_cell = Cell(str(self.board[rows][cols]), rows, cols, self.screen, self.board, self.count) - cell_text = font.render(str(self.board[rows][cols]), True, self.color) - x_rect = cell_text.get_rect(center=x.center) - self.screen.blit(cell_text, x_rect) - else: - x = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * cols + self.margin, (self.margin + self.height) * rows + self.margin, self.width, self.height], 1) - font = pygame.font.Font(None, 25) - - cell_text = font.render("", True, self.color) - x_rect = cell_text.get_rect(center=x.center) - self.screen.blit(cell_text, x_rect) + indiv_cell.draw() pygame.draw.line(self.screen, self.color, [0, 122], [457, 122], 2) pygame.draw.line(self.screen, self.color, [0, 246], [457, 246], 2) @@ -158,10 +190,6 @@ def draw(self): pygame.draw.line(self.screen, self.color, [153, 0], [153, 368], 2) pygame.draw.line(self.screen, self.color, [305, 0], [305, 368], 2) - - def board_solution(self): - return - # Marks the cell at (row, col) in the board as the current selected cell. # Once a cell has been selected, the user can edit its value or sketched value. def select(self, row, col): @@ -213,5 +241,4 @@ def generate_sudoku(size, removed): board = sudoku.get_board() sudoku.remove_cells() board = sudoku.get_board() - sudoku.print_board() return board \ No newline at end of file From f942a942ffefa2c98c101048698c8535f29c97ac Mon Sep 17 00:00:00 2001 From: ADomonkos04 Date: Tue, 23 Apr 2024 16:33:32 -0400 Subject: [PATCH 07/12] Finished Classes and main code. I need help with the sketch function because it's not working fully correctly. --- sudoku.py | 487 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 465 insertions(+), 22 deletions(-) diff --git a/sudoku.py b/sudoku.py index 150270aa..3ce3797d 100644 --- a/sudoku.py +++ b/sudoku.py @@ -115,6 +115,257 @@ def generate_sudoku(size, removed): board = sudoku.get_board() return board + +class Cell: + def __init__(self, value, row, col, screen): + self.value = value + self.row = row + self.col = col + self.screen = screen + + self.sketched_value = value + self.selected = False + + def set_cell_value(self, value): + self.value = value + + def set_sketched_value(self, value): + if value != 0: + self.sketched_value = value + + def draw(self): + chip_font = pygame.font.Font(None, 60) + chip_surf = chip_font.render(str(self.value), 1, LINE_COLOR) if self.value != 0 else None + + chip_1_surf = chip_font.render('1', 1, LINE_COLOR) + chip_2_surf = chip_font.render('2', 1, LINE_COLOR) + chip_3_surf = chip_font.render('3', 1, LINE_COLOR) + chip_4_surf = chip_font.render('4', 1, LINE_COLOR) + chip_5_surf = chip_font.render('5', 1, LINE_COLOR) + chip_6_surf = chip_font.render('6', 1, LINE_COLOR) + chip_7_surf = chip_font.render('7', 1, LINE_COLOR) + chip_8_surf = chip_font.render('8', 1, LINE_COLOR) + chip_9_surf = chip_font.render('9', 1, LINE_COLOR) + + if self.sketched_value != 0 and self.value == 0: + chip_surf = chip_font.render(str(self.sketched_value), 1, LINE_COLOR) + + if self.selected: + pygame.draw.rect(self.screen, RED, pygame.Rect(self.col * SQUARE_SIZE, self.row * SQUARE_SIZE, + SQUARE_SIZE, SQUARE_SIZE), 3) + + if chip_surf: + chip_rect = chip_surf.get_rect(center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, + self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_surf, chip_rect) + + if self.selected: + pygame.draw.rect(screen, RED, + pygame.Rect(self.col * SQUARE_SIZE, self.row * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE), 3) + self.selected = False + + if self.value == 1: + chip_1_rect = chip_1_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_1_surf, chip_1_rect) + + elif self.value == 2: + chip_2_rect = chip_2_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_2_surf, chip_2_rect) + + elif self.value == 3: + chip_3_rect = chip_3_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_3_surf, chip_3_rect) + + elif self.value == 4: + chip_4_rect = chip_4_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_4_surf, chip_4_rect) + + elif self.value == 5: + chip_5_rect = chip_5_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_5_surf, chip_5_rect) + + elif self.value == 6: + chip_6_rect = chip_6_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_6_surf, chip_6_rect) + + elif self.value == 7: + chip_7_rect = chip_7_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_7_surf, chip_7_rect) + + elif self.value == 8: + chip_8_rect = chip_8_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_8_surf, chip_8_rect) + + elif self.value == 9: + chip_9_rect = chip_9_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_9_surf, chip_9_rect) + + +class Board: + def __init__(self, width, height, screen, difficulty): + self.width = width + self.height = height + self.screen = screen + self.difficulty = difficulty + self.board = generate_sudoku(self.difficulty, 9) + self.cells = [[Cell(self.board[row][col], row, col, self.screen) for col in range(9)] for row in range(9)] + self.selected_row = 0 + self.selected_col = 0 + + def draw(self): + self.screen.fill(BG_COLOR) + button_font = pygame.font.Font(None, 35) + + for i in range(1, BOARD_ROWS): + pygame.draw.line(self.screen, LINE_COLOR, (0, i * SQUARE_SIZE), (WIDTH, i * SQUARE_SIZE), LINE_WIDTH) + pygame.draw.line(self.screen, LINE_COLOR, (0, i * SQUARE_SIZE * 3), (WIDTH, i * SQUARE_SIZE * 3), + LINE_WIDTH * 3) + + for i in range(1, BOARD_COLS): + pygame.draw.line(self.screen, LINE_COLOR, (i * SQUARE_SIZE, 0), (i * SQUARE_SIZE, HEIGHT - SQUARE_SIZE), + LINE_WIDTH) + pygame.draw.line(self.screen, LINE_COLOR, (i * SQUARE_SIZE * 3, 0), + (i * SQUARE_SIZE * 3, HEIGHT - SQUARE_SIZE), + LINE_WIDTH * 3) + + # Draw cells + for i in range(9): + for j in range(9): + self.cells[i][j].set_cell_value(self.board[i][j]) + self.cells[i][j].draw() + + exit_text = button_font.render("EXIT", 0, (255, 255, 255)) + exit_surf = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) + exit_surf.fill(LINE_COLOR) + exit_surf.blit(exit_text, (10, 10)) + exit_rect = exit_surf.get_rect(center=(WIDTH // 2 + 135, 570)) + screen.blit(exit_surf, exit_rect) + + restart_text = button_font.render("RESTART", 0, (255, 255, 255)) + restart_surf = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) + restart_surf.fill(LINE_COLOR) + restart_surf.blit(restart_text, (10, 10)) + restart_rect = restart_surf.get_rect(center=(WIDTH // 2, 570)) + screen.blit(restart_surf, restart_rect) + + reset_text = button_font.render("RESET", 0, (255, 255, 255)) + reset_surf = pygame.Surface((reset_text.get_size()[0] + 20, reset_text.get_size()[1] + 20)) + reset_surf.fill(LINE_COLOR) + reset_surf.blit(reset_text, (10, 10)) + reset_rect = reset_surf.get_rect(center=(WIDTH // 2 - 140, 570)) + screen.blit(reset_surf, reset_rect) + + def update_display(self): + pygame.display.update() + + def select(self, row, col): + self.cells[self.selected_row][self.selected_col].selected = True + + if row in range(9) and col in range(9): + self.row = row + self.col = col + self.cells[self.selected_row][self.selected_col].selected = True + + def click(self, x, y): + cell_width = self.width // 9 + cell_height = self.height // 9 + click_row = x // cell_width + click_col = y // cell_height + position = (click_row, click_col) + return position + + def clear(self): + if not empty[clicked_row][clicked_col]: + board.board[clicked_row][clicked_col] = 0 + + def find_preset_values(self, sudoku_board): + dict = [] + for row in range(9): + rowdict = {} + for i, val in enumerate(sudoku_board[row]): + rowdict[i] = val + if val == 0: + rowdict[str(i)] = False + else: + rowdict[str(i)] = True + dict.append(rowdict) + return dict + + def sketch(self, value): + self.sketch = value + + def place_number(self, value): + self.number = value + + def reset_to_original(self): + for i, dict in enumerate(self.find_preset_values()): + for col in range(9): + if dict[str(col)] == True: + dict[col] = 0 + + def is_full(self): + count = 0 + for row, dict in enumerate(self.find_preset_values(self.board)): + for col in range(9): + if dict[col] == 0: + count += 1 + if count == 0: + return True + else: + return False + + def update_board(self): + for row in range(9): + for col in range(9): + self.board[row][col] = self.cells[row][col].value + + def check_board(self): + for row in range(9): + for col in range(9): + if not self.is_valid(row, col): + return False + return True + + def is_valid(self, row, col): + + test_set = {1, 2, 3, 4, 5, 6, 7, 8, 9} + + # Check row + for row in range(9): + set1 = set(self.board[row]) + if set1 != test_set: + return False + + # Check column + for col in range(9): + col_list = [] + for row in range(9): + col_list.append(self.board[row][col]) + set2 = set(col_list) + if set2 != test_set: + return False + + # Check 3x3 box + for row in range(0, 9, 3): + for col in range(0, 9, 3): + box = [self.board[row][col], self.board[row][col + 1], self.board[row][col + 2], + self.board[row + 1][col], self.board[row + 1][col + 1], self.board[row + 1][col + 2], + self.board[row + 2][col], self.board[row + 2][col + 1], self.board[row + 2][col + 2]] + set3 = set(box) + if set3 != test_set: + return False + return True + + def draw_menu(screen): start_title_font = pygame.font.Font(None, 70) select_title_font = pygame.font.Font(None, 55) @@ -123,21 +374,20 @@ def draw_menu(screen): screen.fill(BG_COLOR) title_surf = start_title_font.render("Welcome to Sudoku", 1, LINE_COLOR) - title_rect = title_surf.get_rect(center=(WIDTH//2, HEIGHT//2-150)) + title_rect = title_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 150)) screen.blit(title_surf, title_rect) select_title_surf = select_title_font.render("Select Game Mode:", 1, LINE_COLOR) - select_title_rect = select_title_surf.get_rect(center=(WIDTH//2, HEIGHT//2)) + select_title_rect = select_title_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2)) screen.blit(select_title_surf, select_title_rect) + easy = button_font.render("Easy", 0, (255, 255, 255)) + med = button_font.render("Medium", 0, (255, 255, 255)) + hard = button_font.render("Hard", 0, (255, 255, 255)) - easy=button_font.render("Easy",0,(255,255,255)) - med=button_font.render("Medium",0,(255,255,255)) - hard=button_font.render("Hard",0,(255,255,255)) - - easy_surf=pygame.Surface((easy.get_size()[0]+20,easy.get_size()[1]+20)) + easy_surf = pygame.Surface((easy.get_size()[0] + 20, easy.get_size()[1] + 20)) easy_surf.fill(LINE_COLOR) - easy_surf.blit(easy,(10,10)) + easy_surf.blit(easy, (10, 10)) med_surf = pygame.Surface((med.get_size()[0] + 20, med.get_size()[1] + 20)) med_surf.fill(LINE_COLOR) med_surf.blit(med, (10, 10)) @@ -145,17 +395,14 @@ def draw_menu(screen): hard_surf.fill(LINE_COLOR) hard_surf.blit(hard, (10, 10)) + easy_rect = easy.get_rect(center=(WIDTH // 2 - 120, HEIGHT // 2 + 100)) + med_rect = med.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) + hard_rect = hard.get_rect(center=(WIDTH // 2 + 120, HEIGHT // 2 + 100)) - easy_rect=easy.get_rect(center=(WIDTH//2-120,HEIGHT//2+100)) - med_rect=med.get_rect(center=(WIDTH//2,HEIGHT//2+100)) - hard_rect=hard.get_rect(center=(WIDTH//2+120,HEIGHT//2+100)) - - screen.blit(easy_surf,easy_rect) + screen.blit(easy_surf, easy_rect) screen.blit(med_surf, med_rect) screen.blit(hard_surf, hard_rect) - - while True: for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -170,12 +417,13 @@ def draw_menu(screen): return 'hard' pygame.display.update() + def draw_game_over(screen): game_over_font = pygame.font.Font(None, 100) button_font = pygame.font.Font(None, 40) screen.fill(BG_COLOR) if win: - text="Game Won!" + text = "Game Won!" else: text = "Game Over :(" game_over_surf = game_over_font.render(text, 0, LINE_COLOR) @@ -183,18 +431,213 @@ def draw_game_over(screen): screen.blit(game_over_surf, game_over_rect) if win: - exit_text=button_font.render("EXIT",0,(255,255,255)) - exit_surf=pygame.Surface((exit_text.get_size()[0]+20,exit_text.get_size()[1]+20)) + exit_text = button_font.render("EXIT", 0, (255, 255, 255)) + exit_surf = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) exit_surf.fill(LINE_COLOR) - exit_surf.blit(exit_text,(10,10)) - exit_rect=exit_surf.get_rect(center=(WIDTH//2+135,570)) - screen.blit(exit_surf,exit_rect) + exit_surf.blit(exit_text, (10, 10)) + exit_rect = exit_surf.get_rect(center=(WIDTH // 2 + 135, 570)) + screen.blit(exit_surf, exit_rect) else: restart_text = button_font.render("RESTART", 0, (255, 255, 255)) restart_surf = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) restart_surf.fill(LINE_COLOR) restart_surf.blit(restart_text, (10, 10)) - restart_rect = restart_surf.get_rect(center=(WIDTH//2, 570)) + restart_rect = restart_surf.get_rect(center=(WIDTH // 2, 570)) screen.blit(restart_surf, restart_rect) + +if __name__ == '__main__': + screen = pygame.display.set_mode((WIDTH, HEIGHT)) + screen.fill(BG_COLOR) + game_over = False + win = False + + pygame.init() + pygame.display.set_caption('Sudoku') + + chip_font = pygame.font.Font(None, 35) + chip_1_surf_1 = chip_font.render('1', 1, GRAY) + chip_2_surf_1 = chip_font.render('2', 1, GRAY) + chip_3_surf_1 = chip_font.render('3', 1, GRAY) + chip_4_surf_1 = chip_font.render('4', 1, GRAY) + chip_5_surf_1 = chip_font.render('5', 1, GRAY) + chip_6_surf_1 = chip_font.render('6', 1, GRAY) + chip_7_surf_1 = chip_font.render('7', 1, GRAY) + chip_8_surf_1 = chip_font.render('8', 1, GRAY) + chip_9_surf_1 = chip_font.render('9', 1, GRAY) + + option = draw_menu(screen) + if option == "easy": + difficulty = 30 + elif option == 'medium': + difficulty = 40 + elif option == 'hard': + difficulty = 50 + + board = Board(WIDTH, HEIGHT, screen, difficulty) + board.draw() + empty = board.find_preset_values(board.board) + board.update_display() + + clicked_row = 0 + clicked_col = 0 + running = True + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_LEFT: + clicked_col = (clicked_col - 1) % 9 + elif event.key == pygame.K_RIGHT: + clicked_col = (clicked_col + 1) % 9 + elif event.key == pygame.K_UP: + clicked_row = (clicked_row - 1) % 9 + elif event.key == pygame.K_DOWN: + clicked_row = (clicked_row + 1) % 9 + if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: + board.cells[clicked_row][clicked_col].selected = True + board.draw() + + + + elif event.type == pygame.MOUSEBUTTONDOWN and not game_over: + clicked_row = int(event.pos[1] / SQUARE_SIZE) + clicked_col = int(event.pos[0] / SQUARE_SIZE) + if clicked_row == 9 and 1 <= clicked_col <= 2: + for i in range(9): + for j in range(9): + if not empty[i][j]: + board.board[i][j] = 0 + board.draw() + + if clicked_row == 9 and 3 <= clicked_col <= 5: + option = draw_menu(screen) + if option == "easy": + difficulty = 30 + elif option == 'medium': + difficulty = 40 + elif option == 'hard': + difficulty = 50 + + board = Board(WIDTH, HEIGHT, screen, difficulty) + board.draw() + empty = board.find_preset_values(board.board) + board.update_display() + + if clicked_row == 9 and 6 <= clicked_col <= 7: + sys.exit() + + if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: + board.cells[clicked_row][clicked_col].selected = True + board.draw() + board.update_display() + + if event.type == pygame.KEYUP: + if event.key == pygame.K_1: + i = 1 + chip_1_rect = chip_1_surf_1.get_rect(center=(clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_1_surf_1, chip_1_rect) + pygame.display.update() + + + + + elif event.key == pygame.K_2: + i = 2 + chip_2_rect = chip_2_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_2_surf_1, chip_2_rect) + pygame.display.update() + + elif event.key == pygame.K_3: + i = 3 + chip_3_rect = chip_3_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_3_surf_1, chip_3_rect) + pygame.display.update() + + elif event.key == pygame.K_4: + i = 4 + chip_4_rect = chip_4_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_4_surf_1, chip_4_rect) + pygame.display.update() + + elif event.key == pygame.K_5: + i = 5 + chip_5_rect = chip_5_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_5_surf_1, chip_5_rect) + pygame.display.update() + + elif event.key == pygame.K_5: + i = 5 + chip_5_rect = chip_5_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_5_surf_1, chip_5_rect) + pygame.display.update() + + elif event.key == pygame.K_6: + i = 6 + chip_6_rect = chip_6_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_6_surf_1, chip_6_rect) + pygame.display.update() + + elif event.key == pygame.K_7: + i = 7 + chip_7_rect = chip_7_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_7_surf_1, chip_7_rect) + pygame.display.update() + + elif event.key == pygame.K_8: + i = 8 + chip_8_rect = chip_8_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_8_surf_1, chip_8_rect) + pygame.display.update() + + elif event.key == pygame.K_9: + i = 9 + chip_9_rect = chip_9_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_9_surf_1, chip_9_rect) + pygame.display.update() + + elif event.key == pygame.K_BACKSPACE: + board.clear() + board.draw() + board.update_display() + + + elif event.key == pygame.K_RETURN: + digit = i + if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: + if not empty[clicked_row][str(clicked_col)]: + board.board[clicked_row][clicked_col] = digit + board.draw() + board.update_display() + + if board.is_full(): + if board.check_board(): + win = True + draw_game_over(screen) + pygame.display.update() + else: + draw_game_over(screen) + pygame.display.update() + From d000932665678207b955ee79d6cd5c2b590ec95d Mon Sep 17 00:00:00 2001 From: ADomonkos04 Date: Tue, 23 Apr 2024 16:34:12 -0400 Subject: [PATCH 08/12] Finished Classes and main code. I need help with the sketch function because it's not working fully correctly. Also, we need to make the graphic design choices better; I just used the basic ones from the tictactoe example --- .idea/.gitignore | 3 +++ .idea/Sudoku.iml | 12 ++++++++++++ .idea/inspectionProfiles/profiles_settings.xml | 6 ++++++ .idea/misc.xml | 7 +++++++ .idea/modules.xml | 8 ++++++++ .idea/vcs.xml | 6 ++++++ 6 files changed, 42 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/Sudoku.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..26d33521 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/Sudoku.iml b/.idea/Sudoku.iml new file mode 100644 index 00000000..8a05c6ed --- /dev/null +++ b/.idea/Sudoku.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..db8786c0 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..64cc2ec2 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From fc3e34830fb4a81d2cdb4598c3a6069a4e0a1223 Mon Sep 17 00:00:00 2001 From: ADomonkos04 Date: Tue, 23 Apr 2024 16:52:40 -0400 Subject: [PATCH 09/12] Merge remote-tracking branch 'origin/main' # Conflicts: # sudoku.py --- sudoku.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sudoku.py b/sudoku.py index 3ce3797d..7e8f8da4 100644 --- a/sudoku.py +++ b/sudoku.py @@ -237,7 +237,6 @@ def draw(self): (i * SQUARE_SIZE * 3, HEIGHT - SQUARE_SIZE), LINE_WIDTH * 3) - # Draw cells for i in range(9): for j in range(9): self.cells[i][j].set_cell_value(self.board[i][j]) @@ -339,13 +338,11 @@ def is_valid(self, row, col): test_set = {1, 2, 3, 4, 5, 6, 7, 8, 9} - # Check row for row in range(9): set1 = set(self.board[row]) if set1 != test_set: return False - # Check column for col in range(9): col_list = [] for row in range(9): @@ -354,7 +351,6 @@ def is_valid(self, row, col): if set2 != test_set: return False - # Check 3x3 box for row in range(0, 9, 3): for col in range(0, 9, 3): box = [self.board[row][col], self.board[row][col + 1], self.board[row][col + 2], From 9e8373b98db7e3c7843570fe028cf3c252fce60b Mon Sep 17 00:00:00 2001 From: psparkyg Date: Tue, 23 Apr 2024 17:48:24 -0400 Subject: [PATCH 10/12] Updated Code --- sudoku.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sudoku.py b/sudoku.py index 7e8f8da4..1184b736 100644 --- a/sudoku.py +++ b/sudoku.py @@ -13,6 +13,7 @@ CHIP_COLOR = (171, 176, 172) FIXED_CHIP_COLOR = (0, 0, 0) +i = 0 class SudokuGenerator: @@ -487,21 +488,25 @@ def draw_game_over(screen): elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: clicked_col = (clicked_col - 1) % 9 + i = 0 elif event.key == pygame.K_RIGHT: clicked_col = (clicked_col + 1) % 9 + i = 0 elif event.key == pygame.K_UP: clicked_row = (clicked_row - 1) % 9 + i = 0 elif event.key == pygame.K_DOWN: clicked_row = (clicked_row + 1) % 9 + i = 0 + if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: board.cells[clicked_row][clicked_col].selected = True board.draw() - - elif event.type == pygame.MOUSEBUTTONDOWN and not game_over: clicked_row = int(event.pos[1] / SQUARE_SIZE) clicked_col = int(event.pos[0] / SQUARE_SIZE) + i = 0 if clicked_row == 9 and 1 <= clicked_col <= 2: for i in range(9): for j in range(9): @@ -539,9 +544,6 @@ def draw_game_over(screen): screen.blit(chip_1_surf_1, chip_1_rect) pygame.display.update() - - - elif event.key == pygame.K_2: i = 2 chip_2_rect = chip_2_surf_1.get_rect(center=( @@ -619,13 +621,14 @@ def draw_game_over(screen): board.draw() board.update_display() - elif event.key == pygame.K_RETURN: digit = i if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: if not empty[clicked_row][str(clicked_col)]: board.board[clicked_row][clicked_col] = digit board.draw() + i = 0 + board.update_display() if board.is_full(): From b6bc311f655509cb4fcc2bfcf64cf491cbe7d54e Mon Sep 17 00:00:00 2001 From: miguel-elie Date: Thu, 25 Apr 2024 17:18:51 -0400 Subject: [PATCH 11/12] Made sudoku_generator the same as sudoku.py --- sudoku.py | 1 + sudoku_generator.py | 665 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 533 insertions(+), 133 deletions(-) diff --git a/sudoku.py b/sudoku.py index 1184b736..35d60f1f 100644 --- a/sudoku.py +++ b/sudoku.py @@ -9,6 +9,7 @@ RED = (255, 0, 0) GRAY = (168, 168, 168) BG_COLOR = (255, 255, 245) +BG_COLOR_1 = (0,255,0) LINE_COLOR = (0, 0, 0) CHIP_COLOR = (171, 176, 172) FIXED_CHIP_COLOR = (0, 0, 0) diff --git a/sudoku_generator.py b/sudoku_generator.py index d80485ec..0ea28f6d 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -1,25 +1,34 @@ -import math -import random -import pygame - -empty_locations = [] -puzzle_solution = [] +import random, pygame, sys + +WIDTH = 540 +HEIGHT = 600 +LINE_WIDTH = 2 +BOARD_ROWS = 10 +BOARD_COLS = 9 +SQUARE_SIZE = 60 +RED = (255, 0, 0) +GRAY = (168, 168, 168) +BG_COLOR = (255, 255, 245) +BG_COLOR_1 = (0,255,0) +LINE_COLOR = (0, 0, 0) +CHIP_COLOR = (171, 176, 172) +FIXED_CHIP_COLOR = (0, 0, 0) + +i = 0 class SudokuGenerator: - def __init__(self, row_length, removed_cells): + + def __init__(self, removed_cells, row_length=9): self.row_length = row_length self.removed_cells = removed_cells + self.box_length = 3 self.board = [[" " for _ in range(self.row_length)] for _ in range(self.row_length)] - self.box_length = int(math.sqrt(self.row_length)) def get_board(self): return self.board def print_board(self): - for row in self.get_board(): - for col in row: - print(col,end=" ") - print() + print(self.board) def valid_in_row(self, row, num): return num not in self.board[row] @@ -31,14 +40,22 @@ def valid_in_col(self, col, num): return True def valid_in_box(self, row_start, col_start, num): - for row in range(self.box_length): - for col in range(self.box_length): + for row in range(3): + for col in range(3): if self.board[row_start + row][col_start + col] == num: return False return True def is_valid(self, row, col, num): - return self.valid_in_row(row, num) and self.valid_in_col(col, num) and self.valid_in_box(row - row % 3, col - col % 3, num) + return self.valid_in_row(row, num) and self.valid_in_col(col, num) and self.valid_in_box(row - row % 3, + col - col % 3, num) + + def unused_in_box(self, row_start, col_start, num): + for row in range(row_start, row_start + 3): + for col in range(col_start, col_start + 3): + if self.board[row][col] == num: + return False + return True def fill_box(self, row_start, col_start): nums = list(range(1, self.row_length + 1)) @@ -80,10 +97,9 @@ def fill_remaining(self, row, col): def fill_values(self): self.fill_diagonal() - self.fill_remaining(0,3) + self.fill_remaining(0, 3) def remove_cells(self): - for i in range(self.removed_cells): row = random.randint(0, self.row_length - 1) col = random.randint(0, self.row_length - 1) @@ -92,153 +108,536 @@ def remove_cells(self): col = random.randint(0, self.row_length - 1) self.board[row][col] = 0 + +def generate_sudoku(size, removed): + sudoku = SudokuGenerator(size, removed) + sudoku.fill_values() + board = sudoku.get_board() + sudoku.remove_cells() + board = sudoku.get_board() + return board + + class Cell: - # Constructor for this class - def __init__(self, value, row, col, screen, board, count): + def __init__(self, value, row, col, screen): self.value = value self.row = row self.col = col self.screen = screen - self.board = board - self.color = (0,0,0) - self.margin = 1 - self.width = 50 - self.height = 40 - self.count = count - self.can_edit = False - def data(self): - return (self.row, self.col, self.width, self.height) - - def draw(self): - global empty_locations - - if self.count <= 1: - if self.value != "0": - z = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * self.col + self.margin, - (self.margin + self.height) * self.row + self.margin, - self.width, self.height], 1) - font = pygame.font.Font(None, 25) - - cell_text = font.render(str(self.board[self.row][self.col]), True, self.color) - z_rect = cell_text.get_rect(center=z.center) - self.screen.blit(cell_text, z_rect) - - self.can_edit = False - else: - z = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * self.col + self.margin, - (self.margin + self.height) * self.row + self.margin, - self.width, self.height], 1) - font = pygame.font.Font(None, 25) - - cell_text = font.render("", True, self.color) - z_rect = cell_text.get_rect(center=z.center) - self.screen.blit(cell_text, z_rect) - - self.can_edit = True - - empty_locations.append((z.x, z.y, z.width, z.height)) - empty_locations.append((self.row, self.col, self.can_edit)) - else: - if self.value != "0": - z = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * self.col + self.margin, - (self.margin + self.height) * self.row + self.margin, - self.width, self.height], 1) - font = pygame.font.Font(None, 25) + self.sketched_value = value + self.selected = False - cell_text = font.render(str(self.board[self.row][self.col]), True, self.color) - z_rect = cell_text.get_rect(center=z.center) - self.screen.blit(cell_text, z_rect) + def set_cell_value(self, value): + self.value = value - self.can_edit = False - else: - z = pygame.draw.rect(self.screen, self.color, [(self.margin + self.width) * self.col + self.margin, - (self.margin + self.height) * self.row + self.margin, - self.width, self.height], 1) - font = pygame.font.Font(None, 25) + def set_sketched_value(self, value): + if value != 0: + self.sketched_value = value - cell_text = font.render("", True, self.color) - z_rect = cell_text.get_rect(center=z.center) - self.screen.blit(cell_text, z_rect) + def draw(self): + chip_font = pygame.font.Font(None, 60) + chip_surf = chip_font.render(str(self.value), 1, LINE_COLOR) if self.value != 0 else None + + chip_1_surf = chip_font.render('1', 1, LINE_COLOR) + chip_2_surf = chip_font.render('2', 1, LINE_COLOR) + chip_3_surf = chip_font.render('3', 1, LINE_COLOR) + chip_4_surf = chip_font.render('4', 1, LINE_COLOR) + chip_5_surf = chip_font.render('5', 1, LINE_COLOR) + chip_6_surf = chip_font.render('6', 1, LINE_COLOR) + chip_7_surf = chip_font.render('7', 1, LINE_COLOR) + chip_8_surf = chip_font.render('8', 1, LINE_COLOR) + chip_9_surf = chip_font.render('9', 1, LINE_COLOR) + + if self.sketched_value != 0 and self.value == 0: + chip_surf = chip_font.render(str(self.sketched_value), 1, LINE_COLOR) + + if self.selected: + pygame.draw.rect(self.screen, RED, pygame.Rect(self.col * SQUARE_SIZE, self.row * SQUARE_SIZE, + SQUARE_SIZE, SQUARE_SIZE), 3) + + if chip_surf: + chip_rect = chip_surf.get_rect(center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, + self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_surf, chip_rect) + + if self.selected: + pygame.draw.rect(screen, RED, + pygame.Rect(self.col * SQUARE_SIZE, self.row * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE), 3) + self.selected = False + + if self.value == 1: + chip_1_rect = chip_1_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_1_surf, chip_1_rect) + + elif self.value == 2: + chip_2_rect = chip_2_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_2_surf, chip_2_rect) + + elif self.value == 3: + chip_3_rect = chip_3_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_3_surf, chip_3_rect) + + elif self.value == 4: + chip_4_rect = chip_4_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_4_surf, chip_4_rect) + + elif self.value == 5: + chip_5_rect = chip_5_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_5_surf, chip_5_rect) + + elif self.value == 6: + chip_6_rect = chip_6_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_6_surf, chip_6_rect) + + elif self.value == 7: + chip_7_rect = chip_7_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_7_surf, chip_7_rect) + + elif self.value == 8: + chip_8_rect = chip_8_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_8_surf, chip_8_rect) + + elif self.value == 9: + chip_9_rect = chip_9_surf.get_rect( + center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) + self.screen.blit(chip_9_surf, chip_9_rect) - self.can_edit = True class Board: - def __init__(self, screen, board): + def __init__(self, width, height, screen, difficulty): + self.width = width + self.height = height self.screen = screen - self.difficulty = board - self.row, self.col = 9,9 - self.color = (0,0,0) - self.board = board - self.margin = 1 - self.count = 0 + self.difficulty = difficulty + self.board = generate_sudoku(self.difficulty, 9) + self.cells = [[Cell(self.board[row][col], row, col, self.screen) for col in range(9)] for row in range(9)] + self.selected_row = 0 + self.selected_col = 0 def draw(self): - self.count += 1 - - for rows in range(self.row): - for cols in range(self.col): - - indiv_cell = Cell(str(self.board[rows][cols]), rows, cols, self.screen, self.board, self.count) - - indiv_cell.draw() - - pygame.draw.line(self.screen, self.color, [0, 122], [457, 122], 2) - pygame.draw.line(self.screen, self.color, [0, 246], [457, 246], 2) - pygame.draw.line(self.screen, self.color, [0, 368], [457, 368], 2) + self.screen.fill(BG_COLOR) + button_font = pygame.font.Font(None, 35) + + for i in range(1, BOARD_ROWS): + pygame.draw.line(self.screen, LINE_COLOR, (0, i * SQUARE_SIZE), (WIDTH, i * SQUARE_SIZE), LINE_WIDTH) + pygame.draw.line(self.screen, LINE_COLOR, (0, i * SQUARE_SIZE * 3), (WIDTH, i * SQUARE_SIZE * 3), + LINE_WIDTH * 3) + + for i in range(1, BOARD_COLS): + pygame.draw.line(self.screen, LINE_COLOR, (i * SQUARE_SIZE, 0), (i * SQUARE_SIZE, HEIGHT - SQUARE_SIZE), + LINE_WIDTH) + pygame.draw.line(self.screen, LINE_COLOR, (i * SQUARE_SIZE * 3, 0), + (i * SQUARE_SIZE * 3, HEIGHT - SQUARE_SIZE), + LINE_WIDTH * 3) + + for i in range(9): + for j in range(9): + self.cells[i][j].set_cell_value(self.board[i][j]) + self.cells[i][j].draw() + + exit_text = button_font.render("EXIT", 0, (255, 255, 255)) + exit_surf = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) + exit_surf.fill(LINE_COLOR) + exit_surf.blit(exit_text, (10, 10)) + exit_rect = exit_surf.get_rect(center=(WIDTH // 2 + 135, 570)) + screen.blit(exit_surf, exit_rect) + + restart_text = button_font.render("RESTART", 0, (255, 255, 255)) + restart_surf = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) + restart_surf.fill(LINE_COLOR) + restart_surf.blit(restart_text, (10, 10)) + restart_rect = restart_surf.get_rect(center=(WIDTH // 2, 570)) + screen.blit(restart_surf, restart_rect) + + reset_text = button_font.render("RESET", 0, (255, 255, 255)) + reset_surf = pygame.Surface((reset_text.get_size()[0] + 20, reset_text.get_size()[1] + 20)) + reset_surf.fill(LINE_COLOR) + reset_surf.blit(reset_text, (10, 10)) + reset_rect = reset_surf.get_rect(center=(WIDTH // 2 - 140, 570)) + screen.blit(reset_surf, reset_rect) + + def update_display(self): + pygame.display.update() - pygame.draw.line(self.screen, self.color, [153, 0], [153, 368], 2) - pygame.draw.line(self.screen, self.color, [305, 0], [305, 368], 2) - - # Marks the cell at (row, col) in the board as the current selected cell. - # Once a cell has been selected, the user can edit its value or sketched value. def select(self, row, col): - pass + self.cells[self.selected_row][self.selected_col].selected = True + + if row in range(9) and col in range(9): + self.row = row + self.col = col + self.cells[self.selected_row][self.selected_col].selected = True - # If a tuple of (x, y) coordinates is within the displayed board, this function returns a tuple of the (row, col) - # of the cell which was clicked. Otherwise, this function returns None. def click(self, x, y): - pass + cell_width = self.width // 9 + cell_height = self.height // 9 + click_row = x // cell_width + click_col = y // cell_height + position = (click_row, click_col) + return position - # Clears the value cell. Note that the user can only remove the cell values and sketched value that are - # filled by themselves. def clear(self): - pass + if not empty[clicked_row][clicked_col]: + board.board[clicked_row][clicked_col] = 0 + + def find_preset_values(self, sudoku_board): + dict = [] + for row in range(9): + rowdict = {} + for i, val in enumerate(sudoku_board[row]): + rowdict[i] = val + if val == 0: + rowdict[str(i)] = False + else: + rowdict[str(i)] = True + dict.append(rowdict) + return dict - # Sets the sketched value of the current selected cell equal to user entered value. - # It will be displayed at the top left corner of the cell using the draw() function. def sketch(self, value): - pass + self.sketch = value - # Sets the value of the current selected cell equal to user entered value. - # Called when the user presses the Enter key. def place_number(self, value): - pass + self.number = value - # Reset all cells in the board to their original values (0 if cleared, otherwise the corresponding digit). def reset_to_original(self): - pass + for i, dict in enumerate(self.find_preset_values()): + for col in range(9): + if dict[str(col)] == True: + dict[col] = 0 - # Returns a Boolean value indicating whether the board is full or not. def is_full(self): - pass + count = 0 + for row, dict in enumerate(self.find_preset_values(self.board)): + for col in range(9): + if dict[col] == 0: + count += 1 + if count == 0: + return True + else: + return False - # Updates the underlying 2D board with the values in all cells. def update_board(self): - pass - - # Finds an empty cell and returns its row and col as a tuple (x, y). - def find_empty(self): - pass + for row in range(9): + for col in range(9): + self.board[row][col] = self.cells[row][col].value - # Check whether the Sudoku board is solved correctly. def check_board(self): - pass + for row in range(9): + for col in range(9): + if not self.is_valid(row, col): + return False + return True + + def is_valid(self, row, col): + + test_set = {1, 2, 3, 4, 5, 6, 7, 8, 9} + + for row in range(9): + set1 = set(self.board[row]) + if set1 != test_set: + return False + + for col in range(9): + col_list = [] + for row in range(9): + col_list.append(self.board[row][col]) + set2 = set(col_list) + if set2 != test_set: + return False + + for row in range(0, 9, 3): + for col in range(0, 9, 3): + box = [self.board[row][col], self.board[row][col + 1], self.board[row][col + 2], + self.board[row + 1][col], self.board[row + 1][col + 1], self.board[row + 1][col + 2], + self.board[row + 2][col], self.board[row + 2][col + 1], self.board[row + 2][col + 2]] + set3 = set(box) + if set3 != test_set: + return False + return True + + +def draw_menu(screen): + start_title_font = pygame.font.Font(None, 70) + select_title_font = pygame.font.Font(None, 55) + button_font = pygame.font.Font(None, 40) + + screen.fill(BG_COLOR) + + title_surf = start_title_font.render("Welcome to Sudoku", 1, LINE_COLOR) + title_rect = title_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 150)) + screen.blit(title_surf, title_rect) + + select_title_surf = select_title_font.render("Select Game Mode:", 1, LINE_COLOR) + select_title_rect = select_title_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2)) + screen.blit(select_title_surf, select_title_rect) + + easy = button_font.render("Easy", 0, (255, 255, 255)) + med = button_font.render("Medium", 0, (255, 255, 255)) + hard = button_font.render("Hard", 0, (255, 255, 255)) + + easy_surf = pygame.Surface((easy.get_size()[0] + 20, easy.get_size()[1] + 20)) + easy_surf.fill(LINE_COLOR) + easy_surf.blit(easy, (10, 10)) + med_surf = pygame.Surface((med.get_size()[0] + 20, med.get_size()[1] + 20)) + med_surf.fill(LINE_COLOR) + med_surf.blit(med, (10, 10)) + hard_surf = pygame.Surface((hard.get_size()[0] + 20, hard.get_size()[1] + 20)) + hard_surf.fill(LINE_COLOR) + hard_surf.blit(hard, (10, 10)) + + easy_rect = easy.get_rect(center=(WIDTH // 2 - 120, HEIGHT // 2 + 100)) + med_rect = med.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) + hard_rect = hard.get_rect(center=(WIDTH // 2 + 120, HEIGHT // 2 + 100)) + + screen.blit(easy_surf, easy_rect) + screen.blit(med_surf, med_rect) + screen.blit(hard_surf, hard_rect) + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + elif event.type == pygame.MOUSEBUTTONDOWN: + if easy_rect.collidepoint(event.pos): + return 'easy' + elif med_rect.collidepoint(event.pos): + return 'medium' + elif hard_rect.collidepoint(event.pos): + return 'hard' + pygame.display.update() + + +def draw_game_over(screen): + game_over_font = pygame.font.Font(None, 100) + button_font = pygame.font.Font(None, 40) + screen.fill(BG_COLOR) + if win: + text = "Game Won!" + else: + text = "Game Over :(" + game_over_surf = game_over_font.render(text, 0, LINE_COLOR) + game_over_rect = game_over_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) + screen.blit(game_over_surf, game_over_rect) + + if win: + exit_text = button_font.render("EXIT", 0, (255, 255, 255)) + exit_surf = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) + exit_surf.fill(LINE_COLOR) + exit_surf.blit(exit_text, (10, 10)) + exit_rect = exit_surf.get_rect(center=(WIDTH // 2 + 135, 570)) + screen.blit(exit_surf, exit_rect) + + else: + restart_text = button_font.render("RESTART", 0, (255, 255, 255)) + restart_surf = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) + restart_surf.fill(LINE_COLOR) + restart_surf.blit(restart_text, (10, 10)) + restart_rect = restart_surf.get_rect(center=(WIDTH // 2, 570)) + screen.blit(restart_surf, restart_rect) + + +if __name__ == '__main__': + screen = pygame.display.set_mode((WIDTH, HEIGHT)) + screen.fill(BG_COLOR) + game_over = False + win = False + + pygame.init() + pygame.display.set_caption('Sudoku') + + chip_font = pygame.font.Font(None, 35) + chip_1_surf_1 = chip_font.render('1', 1, GRAY) + chip_2_surf_1 = chip_font.render('2', 1, GRAY) + chip_3_surf_1 = chip_font.render('3', 1, GRAY) + chip_4_surf_1 = chip_font.render('4', 1, GRAY) + chip_5_surf_1 = chip_font.render('5', 1, GRAY) + chip_6_surf_1 = chip_font.render('6', 1, GRAY) + chip_7_surf_1 = chip_font.render('7', 1, GRAY) + chip_8_surf_1 = chip_font.render('8', 1, GRAY) + chip_9_surf_1 = chip_font.render('9', 1, GRAY) + + option = draw_menu(screen) + if option == "easy": + difficulty = 30 + elif option == 'medium': + difficulty = 40 + elif option == 'hard': + difficulty = 50 + + board = Board(WIDTH, HEIGHT, screen, difficulty) + board.draw() + empty = board.find_preset_values(board.board) + board.update_display() + + clicked_row = 0 + clicked_col = 0 + running = True + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_LEFT: + clicked_col = (clicked_col - 1) % 9 + i = 0 + elif event.key == pygame.K_RIGHT: + clicked_col = (clicked_col + 1) % 9 + i = 0 + elif event.key == pygame.K_UP: + clicked_row = (clicked_row - 1) % 9 + i = 0 + elif event.key == pygame.K_DOWN: + clicked_row = (clicked_row + 1) % 9 + i = 0 + + if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: + board.cells[clicked_row][clicked_col].selected = True + board.draw() + + elif event.type == pygame.MOUSEBUTTONDOWN and not game_over: + clicked_row = int(event.pos[1] / SQUARE_SIZE) + clicked_col = int(event.pos[0] / SQUARE_SIZE) + i = 0 + if clicked_row == 9 and 1 <= clicked_col <= 2: + for i in range(9): + for j in range(9): + if not empty[i][j]: + board.board[i][j] = 0 + board.draw() + + if clicked_row == 9 and 3 <= clicked_col <= 5: + option = draw_menu(screen) + if option == "easy": + difficulty = 30 + elif option == 'medium': + difficulty = 40 + elif option == 'hard': + difficulty = 50 + + board = Board(WIDTH, HEIGHT, screen, difficulty) + board.draw() + empty = board.find_preset_values(board.board) + board.update_display() + + if clicked_row == 9 and 6 <= clicked_col <= 7: + sys.exit() + + if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: + board.cells[clicked_row][clicked_col].selected = True + board.draw() + board.update_display() + + if event.type == pygame.KEYUP: + if event.key == pygame.K_1: + i = 1 + chip_1_rect = chip_1_surf_1.get_rect(center=(clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_1_surf_1, chip_1_rect) + pygame.display.update() + + elif event.key == pygame.K_2: + i = 2 + chip_2_rect = chip_2_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_2_surf_1, chip_2_rect) + pygame.display.update() + + elif event.key == pygame.K_3: + i = 3 + chip_3_rect = chip_3_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_3_surf_1, chip_3_rect) + pygame.display.update() + + elif event.key == pygame.K_4: + i = 4 + chip_4_rect = chip_4_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_4_surf_1, chip_4_rect) + pygame.display.update() + + elif event.key == pygame.K_5: + i = 5 + chip_5_rect = chip_5_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_5_surf_1, chip_5_rect) + pygame.display.update() + + elif event.key == pygame.K_5: + i = 5 + chip_5_rect = chip_5_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_5_surf_1, chip_5_rect) + pygame.display.update() + + elif event.key == pygame.K_6: + i = 6 + chip_6_rect = chip_6_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_6_surf_1, chip_6_rect) + pygame.display.update() + + elif event.key == pygame.K_7: + i = 7 + chip_7_rect = chip_7_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_7_surf_1, chip_7_rect) + pygame.display.update() + + elif event.key == pygame.K_8: + i = 8 + chip_8_rect = chip_8_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_8_surf_1, chip_8_rect) + pygame.display.update() + + elif event.key == pygame.K_9: + i = 9 + chip_9_rect = chip_9_surf_1.get_rect(center=( + clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, + clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) + screen.blit(chip_9_surf_1, chip_9_rect) + pygame.display.update() + + elif event.key == pygame.K_BACKSPACE: + board.clear() + board.draw() + board.update_display() + + elif event.key == pygame.K_RETURN: + digit = i + if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: + if not empty[clicked_row][str(clicked_col)]: + board.board[clicked_row][clicked_col] = digit + board.draw() + i = 0 + + board.update_display() + + if board.is_full(): + if board.check_board(): + win = True + draw_game_over(screen) + pygame.display.update() + else: + draw_game_over(screen) + pygame.display.update() -def generate_sudoku(size, removed): - sudoku = SudokuGenerator(size, removed) - sudoku.fill_values() - board = sudoku.get_board() - sudoku.remove_cells() - board = sudoku.get_board() - return board \ No newline at end of file From 0a083ef3c4097a108c3fd4fcfc595f0de5e4b9d4 Mon Sep 17 00:00:00 2001 From: miguel-elie Date: Thu, 25 Apr 2024 18:49:08 -0400 Subject: [PATCH 12/12] Fixed sudoku.py and sudoku_generator.py --- sudoku.py | 94 +------- sudoku_generator.py | 527 +------------------------------------------- 2 files changed, 2 insertions(+), 619 deletions(-) diff --git a/sudoku.py b/sudoku.py index 35d60f1f..774b4133 100644 --- a/sudoku.py +++ b/sudoku.py @@ -1,4 +1,5 @@ import random, pygame, sys +from sudoku_generator import SudokuGenerator WIDTH = 540 HEIGHT = 600 @@ -16,99 +17,6 @@ i = 0 -class SudokuGenerator: - - def __init__(self, removed_cells, row_length=9): - self.row_length = row_length - self.removed_cells = removed_cells - self.box_length = 3 - self.board = [[" " for _ in range(self.row_length)] for _ in range(self.row_length)] - - def get_board(self): - return self.board - - def print_board(self): - print(self.board) - - def valid_in_row(self, row, num): - return num not in self.board[row] - - def valid_in_col(self, col, num): - for row in range(self.row_length): - if self.board[row][col] == num: - return False - return True - - def valid_in_box(self, row_start, col_start, num): - for row in range(3): - for col in range(3): - if self.board[row_start + row][col_start + col] == num: - return False - return True - - def is_valid(self, row, col, num): - return self.valid_in_row(row, num) and self.valid_in_col(col, num) and self.valid_in_box(row - row % 3, - col - col % 3, num) - - def unused_in_box(self, row_start, col_start, num): - for row in range(row_start, row_start + 3): - for col in range(col_start, col_start + 3): - if self.board[row][col] == num: - return False - return True - - def fill_box(self, row_start, col_start): - nums = list(range(1, self.row_length + 1)) - random.shuffle(nums) - for i in range(self.box_length): - for j in range(self.box_length): - self.board[row_start + i][col_start + j] = nums.pop() - - def fill_diagonal(self): - for i in range(0, self.row_length, 3): - self.fill_box(i, i) - - def fill_remaining(self, row, col): - if (col >= self.row_length and row < self.row_length - 1): - row += 1 - col = 0 - if row >= self.row_length and col >= self.row_length: - return True - if row < self.box_length: - if col < self.box_length: - col = self.box_length - elif row < self.row_length - self.box_length: - if col == int(row // self.box_length * self.box_length): - col += self.box_length - else: - if col == self.row_length - self.box_length: - row += 1 - col = 0 - if row >= self.row_length: - return True - - for num in range(1, self.row_length + 1): - if self.is_valid(row, col, num): - self.board[row][col] = num - if self.fill_remaining(row, col + 1): - return True - self.board[row][col] = 0 - return False - - def fill_values(self): - self.fill_diagonal() - self.fill_remaining(0, 3) - - def remove_cells(self): - for i in range(self.removed_cells): - row = random.randint(0, self.row_length - 1) - col = random.randint(0, self.row_length - 1) - while self.board[row][col] == 0: - row = random.randint(0, self.row_length - 1) - col = random.randint(0, self.row_length - 1) - self.board[row][col] = 0 - - def generate_sudoku(size, removed): sudoku = SudokuGenerator(size, removed) sudoku.fill_values() diff --git a/sudoku_generator.py b/sudoku_generator.py index 0ea28f6d..ac3b4c9a 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -115,529 +115,4 @@ def generate_sudoku(size, removed): board = sudoku.get_board() sudoku.remove_cells() board = sudoku.get_board() - return board - - -class Cell: - def __init__(self, value, row, col, screen): - self.value = value - self.row = row - self.col = col - self.screen = screen - - self.sketched_value = value - self.selected = False - - def set_cell_value(self, value): - self.value = value - - def set_sketched_value(self, value): - if value != 0: - self.sketched_value = value - - def draw(self): - chip_font = pygame.font.Font(None, 60) - chip_surf = chip_font.render(str(self.value), 1, LINE_COLOR) if self.value != 0 else None - - chip_1_surf = chip_font.render('1', 1, LINE_COLOR) - chip_2_surf = chip_font.render('2', 1, LINE_COLOR) - chip_3_surf = chip_font.render('3', 1, LINE_COLOR) - chip_4_surf = chip_font.render('4', 1, LINE_COLOR) - chip_5_surf = chip_font.render('5', 1, LINE_COLOR) - chip_6_surf = chip_font.render('6', 1, LINE_COLOR) - chip_7_surf = chip_font.render('7', 1, LINE_COLOR) - chip_8_surf = chip_font.render('8', 1, LINE_COLOR) - chip_9_surf = chip_font.render('9', 1, LINE_COLOR) - - if self.sketched_value != 0 and self.value == 0: - chip_surf = chip_font.render(str(self.sketched_value), 1, LINE_COLOR) - - if self.selected: - pygame.draw.rect(self.screen, RED, pygame.Rect(self.col * SQUARE_SIZE, self.row * SQUARE_SIZE, - SQUARE_SIZE, SQUARE_SIZE), 3) - - if chip_surf: - chip_rect = chip_surf.get_rect(center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, - self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_surf, chip_rect) - - if self.selected: - pygame.draw.rect(screen, RED, - pygame.Rect(self.col * SQUARE_SIZE, self.row * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE), 3) - self.selected = False - - if self.value == 1: - chip_1_rect = chip_1_surf.get_rect( - center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_1_surf, chip_1_rect) - - elif self.value == 2: - chip_2_rect = chip_2_surf.get_rect( - center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_2_surf, chip_2_rect) - - elif self.value == 3: - chip_3_rect = chip_3_surf.get_rect( - center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_3_surf, chip_3_rect) - - elif self.value == 4: - chip_4_rect = chip_4_surf.get_rect( - center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_4_surf, chip_4_rect) - - elif self.value == 5: - chip_5_rect = chip_5_surf.get_rect( - center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_5_surf, chip_5_rect) - - elif self.value == 6: - chip_6_rect = chip_6_surf.get_rect( - center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_6_surf, chip_6_rect) - - elif self.value == 7: - chip_7_rect = chip_7_surf.get_rect( - center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_7_surf, chip_7_rect) - - elif self.value == 8: - chip_8_rect = chip_8_surf.get_rect( - center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_8_surf, chip_8_rect) - - elif self.value == 9: - chip_9_rect = chip_9_surf.get_rect( - center=(self.col * SQUARE_SIZE + SQUARE_SIZE // 2, self.row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3)) - self.screen.blit(chip_9_surf, chip_9_rect) - - -class Board: - def __init__(self, width, height, screen, difficulty): - self.width = width - self.height = height - self.screen = screen - self.difficulty = difficulty - self.board = generate_sudoku(self.difficulty, 9) - self.cells = [[Cell(self.board[row][col], row, col, self.screen) for col in range(9)] for row in range(9)] - self.selected_row = 0 - self.selected_col = 0 - - def draw(self): - self.screen.fill(BG_COLOR) - button_font = pygame.font.Font(None, 35) - - for i in range(1, BOARD_ROWS): - pygame.draw.line(self.screen, LINE_COLOR, (0, i * SQUARE_SIZE), (WIDTH, i * SQUARE_SIZE), LINE_WIDTH) - pygame.draw.line(self.screen, LINE_COLOR, (0, i * SQUARE_SIZE * 3), (WIDTH, i * SQUARE_SIZE * 3), - LINE_WIDTH * 3) - - for i in range(1, BOARD_COLS): - pygame.draw.line(self.screen, LINE_COLOR, (i * SQUARE_SIZE, 0), (i * SQUARE_SIZE, HEIGHT - SQUARE_SIZE), - LINE_WIDTH) - pygame.draw.line(self.screen, LINE_COLOR, (i * SQUARE_SIZE * 3, 0), - (i * SQUARE_SIZE * 3, HEIGHT - SQUARE_SIZE), - LINE_WIDTH * 3) - - for i in range(9): - for j in range(9): - self.cells[i][j].set_cell_value(self.board[i][j]) - self.cells[i][j].draw() - - exit_text = button_font.render("EXIT", 0, (255, 255, 255)) - exit_surf = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) - exit_surf.fill(LINE_COLOR) - exit_surf.blit(exit_text, (10, 10)) - exit_rect = exit_surf.get_rect(center=(WIDTH // 2 + 135, 570)) - screen.blit(exit_surf, exit_rect) - - restart_text = button_font.render("RESTART", 0, (255, 255, 255)) - restart_surf = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) - restart_surf.fill(LINE_COLOR) - restart_surf.blit(restart_text, (10, 10)) - restart_rect = restart_surf.get_rect(center=(WIDTH // 2, 570)) - screen.blit(restart_surf, restart_rect) - - reset_text = button_font.render("RESET", 0, (255, 255, 255)) - reset_surf = pygame.Surface((reset_text.get_size()[0] + 20, reset_text.get_size()[1] + 20)) - reset_surf.fill(LINE_COLOR) - reset_surf.blit(reset_text, (10, 10)) - reset_rect = reset_surf.get_rect(center=(WIDTH // 2 - 140, 570)) - screen.blit(reset_surf, reset_rect) - - def update_display(self): - pygame.display.update() - - def select(self, row, col): - self.cells[self.selected_row][self.selected_col].selected = True - - if row in range(9) and col in range(9): - self.row = row - self.col = col - self.cells[self.selected_row][self.selected_col].selected = True - - def click(self, x, y): - cell_width = self.width // 9 - cell_height = self.height // 9 - click_row = x // cell_width - click_col = y // cell_height - position = (click_row, click_col) - return position - - def clear(self): - if not empty[clicked_row][clicked_col]: - board.board[clicked_row][clicked_col] = 0 - - def find_preset_values(self, sudoku_board): - dict = [] - for row in range(9): - rowdict = {} - for i, val in enumerate(sudoku_board[row]): - rowdict[i] = val - if val == 0: - rowdict[str(i)] = False - else: - rowdict[str(i)] = True - dict.append(rowdict) - return dict - - def sketch(self, value): - self.sketch = value - - def place_number(self, value): - self.number = value - - def reset_to_original(self): - for i, dict in enumerate(self.find_preset_values()): - for col in range(9): - if dict[str(col)] == True: - dict[col] = 0 - - def is_full(self): - count = 0 - for row, dict in enumerate(self.find_preset_values(self.board)): - for col in range(9): - if dict[col] == 0: - count += 1 - if count == 0: - return True - else: - return False - - def update_board(self): - for row in range(9): - for col in range(9): - self.board[row][col] = self.cells[row][col].value - - def check_board(self): - for row in range(9): - for col in range(9): - if not self.is_valid(row, col): - return False - return True - - def is_valid(self, row, col): - - test_set = {1, 2, 3, 4, 5, 6, 7, 8, 9} - - for row in range(9): - set1 = set(self.board[row]) - if set1 != test_set: - return False - - for col in range(9): - col_list = [] - for row in range(9): - col_list.append(self.board[row][col]) - set2 = set(col_list) - if set2 != test_set: - return False - - for row in range(0, 9, 3): - for col in range(0, 9, 3): - box = [self.board[row][col], self.board[row][col + 1], self.board[row][col + 2], - self.board[row + 1][col], self.board[row + 1][col + 1], self.board[row + 1][col + 2], - self.board[row + 2][col], self.board[row + 2][col + 1], self.board[row + 2][col + 2]] - set3 = set(box) - if set3 != test_set: - return False - return True - - -def draw_menu(screen): - start_title_font = pygame.font.Font(None, 70) - select_title_font = pygame.font.Font(None, 55) - button_font = pygame.font.Font(None, 40) - - screen.fill(BG_COLOR) - - title_surf = start_title_font.render("Welcome to Sudoku", 1, LINE_COLOR) - title_rect = title_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 150)) - screen.blit(title_surf, title_rect) - - select_title_surf = select_title_font.render("Select Game Mode:", 1, LINE_COLOR) - select_title_rect = select_title_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2)) - screen.blit(select_title_surf, select_title_rect) - - easy = button_font.render("Easy", 0, (255, 255, 255)) - med = button_font.render("Medium", 0, (255, 255, 255)) - hard = button_font.render("Hard", 0, (255, 255, 255)) - - easy_surf = pygame.Surface((easy.get_size()[0] + 20, easy.get_size()[1] + 20)) - easy_surf.fill(LINE_COLOR) - easy_surf.blit(easy, (10, 10)) - med_surf = pygame.Surface((med.get_size()[0] + 20, med.get_size()[1] + 20)) - med_surf.fill(LINE_COLOR) - med_surf.blit(med, (10, 10)) - hard_surf = pygame.Surface((hard.get_size()[0] + 20, hard.get_size()[1] + 20)) - hard_surf.fill(LINE_COLOR) - hard_surf.blit(hard, (10, 10)) - - easy_rect = easy.get_rect(center=(WIDTH // 2 - 120, HEIGHT // 2 + 100)) - med_rect = med.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) - hard_rect = hard.get_rect(center=(WIDTH // 2 + 120, HEIGHT // 2 + 100)) - - screen.blit(easy_surf, easy_rect) - screen.blit(med_surf, med_rect) - screen.blit(hard_surf, hard_rect) - - while True: - for event in pygame.event.get(): - if event.type == pygame.QUIT: - pygame.quit() - sys.exit() - elif event.type == pygame.MOUSEBUTTONDOWN: - if easy_rect.collidepoint(event.pos): - return 'easy' - elif med_rect.collidepoint(event.pos): - return 'medium' - elif hard_rect.collidepoint(event.pos): - return 'hard' - pygame.display.update() - - -def draw_game_over(screen): - game_over_font = pygame.font.Font(None, 100) - button_font = pygame.font.Font(None, 40) - screen.fill(BG_COLOR) - if win: - text = "Game Won!" - else: - text = "Game Over :(" - game_over_surf = game_over_font.render(text, 0, LINE_COLOR) - game_over_rect = game_over_surf.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) - screen.blit(game_over_surf, game_over_rect) - - if win: - exit_text = button_font.render("EXIT", 0, (255, 255, 255)) - exit_surf = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) - exit_surf.fill(LINE_COLOR) - exit_surf.blit(exit_text, (10, 10)) - exit_rect = exit_surf.get_rect(center=(WIDTH // 2 + 135, 570)) - screen.blit(exit_surf, exit_rect) - - else: - restart_text = button_font.render("RESTART", 0, (255, 255, 255)) - restart_surf = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) - restart_surf.fill(LINE_COLOR) - restart_surf.blit(restart_text, (10, 10)) - restart_rect = restart_surf.get_rect(center=(WIDTH // 2, 570)) - screen.blit(restart_surf, restart_rect) - - -if __name__ == '__main__': - screen = pygame.display.set_mode((WIDTH, HEIGHT)) - screen.fill(BG_COLOR) - game_over = False - win = False - - pygame.init() - pygame.display.set_caption('Sudoku') - - chip_font = pygame.font.Font(None, 35) - chip_1_surf_1 = chip_font.render('1', 1, GRAY) - chip_2_surf_1 = chip_font.render('2', 1, GRAY) - chip_3_surf_1 = chip_font.render('3', 1, GRAY) - chip_4_surf_1 = chip_font.render('4', 1, GRAY) - chip_5_surf_1 = chip_font.render('5', 1, GRAY) - chip_6_surf_1 = chip_font.render('6', 1, GRAY) - chip_7_surf_1 = chip_font.render('7', 1, GRAY) - chip_8_surf_1 = chip_font.render('8', 1, GRAY) - chip_9_surf_1 = chip_font.render('9', 1, GRAY) - - option = draw_menu(screen) - if option == "easy": - difficulty = 30 - elif option == 'medium': - difficulty = 40 - elif option == 'hard': - difficulty = 50 - - board = Board(WIDTH, HEIGHT, screen, difficulty) - board.draw() - empty = board.find_preset_values(board.board) - board.update_display() - - clicked_row = 0 - clicked_col = 0 - running = True - while running: - for event in pygame.event.get(): - if event.type == pygame.QUIT: - pygame.quit() - sys.exit() - elif event.type == pygame.KEYDOWN: - if event.key == pygame.K_LEFT: - clicked_col = (clicked_col - 1) % 9 - i = 0 - elif event.key == pygame.K_RIGHT: - clicked_col = (clicked_col + 1) % 9 - i = 0 - elif event.key == pygame.K_UP: - clicked_row = (clicked_row - 1) % 9 - i = 0 - elif event.key == pygame.K_DOWN: - clicked_row = (clicked_row + 1) % 9 - i = 0 - - if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: - board.cells[clicked_row][clicked_col].selected = True - board.draw() - - elif event.type == pygame.MOUSEBUTTONDOWN and not game_over: - clicked_row = int(event.pos[1] / SQUARE_SIZE) - clicked_col = int(event.pos[0] / SQUARE_SIZE) - i = 0 - if clicked_row == 9 and 1 <= clicked_col <= 2: - for i in range(9): - for j in range(9): - if not empty[i][j]: - board.board[i][j] = 0 - board.draw() - - if clicked_row == 9 and 3 <= clicked_col <= 5: - option = draw_menu(screen) - if option == "easy": - difficulty = 30 - elif option == 'medium': - difficulty = 40 - elif option == 'hard': - difficulty = 50 - - board = Board(WIDTH, HEIGHT, screen, difficulty) - board.draw() - empty = board.find_preset_values(board.board) - board.update_display() - - if clicked_row == 9 and 6 <= clicked_col <= 7: - sys.exit() - - if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: - board.cells[clicked_row][clicked_col].selected = True - board.draw() - board.update_display() - - if event.type == pygame.KEYUP: - if event.key == pygame.K_1: - i = 1 - chip_1_rect = chip_1_surf_1.get_rect(center=(clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_1_surf_1, chip_1_rect) - pygame.display.update() - - elif event.key == pygame.K_2: - i = 2 - chip_2_rect = chip_2_surf_1.get_rect(center=( - clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_2_surf_1, chip_2_rect) - pygame.display.update() - - elif event.key == pygame.K_3: - i = 3 - chip_3_rect = chip_3_surf_1.get_rect(center=( - clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_3_surf_1, chip_3_rect) - pygame.display.update() - - elif event.key == pygame.K_4: - i = 4 - chip_4_rect = chip_4_surf_1.get_rect(center=( - clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_4_surf_1, chip_4_rect) - pygame.display.update() - - elif event.key == pygame.K_5: - i = 5 - chip_5_rect = chip_5_surf_1.get_rect(center=( - clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_5_surf_1, chip_5_rect) - pygame.display.update() - - elif event.key == pygame.K_5: - i = 5 - chip_5_rect = chip_5_surf_1.get_rect(center=( - clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_5_surf_1, chip_5_rect) - pygame.display.update() - - elif event.key == pygame.K_6: - i = 6 - chip_6_rect = chip_6_surf_1.get_rect(center=( - clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_6_surf_1, chip_6_rect) - pygame.display.update() - - elif event.key == pygame.K_7: - i = 7 - chip_7_rect = chip_7_surf_1.get_rect(center=( - clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_7_surf_1, chip_7_rect) - pygame.display.update() - - elif event.key == pygame.K_8: - i = 8 - chip_8_rect = chip_8_surf_1.get_rect(center=( - clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_8_surf_1, chip_8_rect) - pygame.display.update() - - elif event.key == pygame.K_9: - i = 9 - chip_9_rect = chip_9_surf_1.get_rect(center=( - clicked_col * SQUARE_SIZE + SQUARE_SIZE // 2 - 10, - clicked_row * SQUARE_SIZE + SQUARE_SIZE // 2 + 3 - 10)) - screen.blit(chip_9_surf_1, chip_9_rect) - pygame.display.update() - - elif event.key == pygame.K_BACKSPACE: - board.clear() - board.draw() - board.update_display() - - elif event.key == pygame.K_RETURN: - digit = i - if 0 <= clicked_row <= 8 and 0 <= clicked_col <= 8: - if not empty[clicked_row][str(clicked_col)]: - board.board[clicked_row][clicked_col] = digit - board.draw() - i = 0 - - board.update_display() - - if board.is_full(): - if board.check_board(): - win = True - draw_game_over(screen) - pygame.display.update() - else: - draw_game_over(screen) - pygame.display.update() - + return board \ No newline at end of file