From 1edd6243d701a81e7eaee9d53c9cb81aa9bac21d Mon Sep 17 00:00:00 2001 From: sickunicorn24 Date: Wed, 20 Nov 2024 22:14:15 -0500 Subject: [PATCH 01/30] sudoku class update --- sudoku_generator.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index 7ec18a59..8462a167 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -1,11 +1,5 @@ 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/ - -""" - class SudokuGenerator: ''' create a sudoku board - initialize class variables and set up the 2D board @@ -23,7 +17,11 @@ class SudokuGenerator: None ''' def __init__(self, row_length, removed_cells): - pass + self.row_length = row_length + self.removed_cells = removed_cells + self.board = [["-" for i in range(9)] for j in range(9)] + self.box_length = row_length ** 0.5 + ''' Returns a 2D python list of numbers which represents the board @@ -32,7 +30,7 @@ def __init__(self, row_length, removed_cells): Return: list[list] ''' def get_board(self): - pass + return self.board ''' Displays the board to the console @@ -42,7 +40,10 @@ def get_board(self): Return: None ''' def print_board(self): - pass + for row in self.board: + for col in row: + print(col, end = " ") + print() ''' Determines if num is contained in the specified row (horizontal) of the board @@ -55,7 +56,9 @@ def print_board(self): Return: boolean ''' def valid_in_row(self, row, num): - pass + if num in self.board[row]: + return False + return True ''' Determines if num is contained in the specified column (vertical) of the board @@ -68,7 +71,10 @@ def valid_in_row(self, row, num): Return: boolean ''' def valid_in_col(self, col, num): - pass + for row in self.board: + if row[col] == num: + return False + return True ''' Determines if num is contained in the 3x3 box specified on the board From f6e7ac1d970ff7b6c01199871b9f42ec7795107b Mon Sep 17 00:00:00 2001 From: sickunicorn24 Date: Wed, 20 Nov 2024 22:24:13 -0500 Subject: [PATCH 02/30] def is_valid --- sudoku_generator.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index 8462a167..b4e309ac 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -89,7 +89,11 @@ def valid_in_col(self, col, num): Return: boolean ''' def valid_in_box(self, row_start, col_start, num): - pass + for row in range(row_start, row_start+2): + for col in range(col_start, col_start+2): + if self.board[row][col] == num: + return False + return True ''' Determines if it is valid to enter num at (row, col) in the board From 26d369454c97478b96e535491af8d7e62d07d95c Mon Sep 17 00:00:00 2001 From: Derek Camilo Date: Sun, 24 Nov 2024 21:53:41 -0500 Subject: [PATCH 03/30] added a constants file --- constants.py | 10 ++++++++++ sudoku.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 constants.py create mode 100644 sudoku.py diff --git a/constants.py b/constants.py new file mode 100644 index 00000000..eb3d31ee --- /dev/null +++ b/constants.py @@ -0,0 +1,10 @@ +#All of these values are subject to change + +WIDTH = 540 +HEIGHT = 600 +BG_COLOR_1 = (255,255, 255) #White +BG_COLOR_2 = (150, 10, 255) #Purple *IF NECCESSARY* +TEXT = (0, 0, 0) #Black +TITLE_TEXT = (255, 10, 200) #Pink +BUTTON_COLOR = (255, 10, 200) #Pink +BUTTON_TEXT = (255,255, 255) diff --git a/sudoku.py b/sudoku.py new file mode 100644 index 00000000..39a9b34a --- /dev/null +++ b/sudoku.py @@ -0,0 +1,54 @@ +import pygame, sys +from constants import * +from sudoku_generator import * + +def game_start(screen): + #Title/Button font init + start_title_font = pygame.font.Font(None, 100) + button_font = pygame.font.Font(None, 70) + + #Background coloring + screen.fill(BG_COLOR_1) + + #Creating title text + title_surface = start_title_font.render("Welcome to Sudoku", 0, TITLE_TEXT) + title_rectangle = title_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 - 150)) + screen.blit(title_surface, title_rectangle) + + #Init Button + start_text = button_font.render("Start", 0, BUTTON_TEXT) + quit_text = button_font.render("Quit", 0, BUTTON_TEXT) + + #Init START/QUIT Button Text Box Background + start_surface = pygame.Surface((start_text.get_size()[0] * 20, start_text.get_size()[1] * 20)) + start_surface.fill(BUTTON_COLOR) + start_surface.blit(start_text, (10, 10)) + quit_surface = pygame.Surface((quit_text.get_size()[0] * 20, quit_text.get_size()[1] * 20)) + quit_surface.fill(BUTTON_COLOR) + quit_surface.blit(quit_text, (10, 10)) + + #Init Button Rectangle + start_rectangle = start_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 + 50)) + quit_rectangle = quit_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 + 150)) + + #Draw Buttons + screen.blit(start_surface, start_rectangle) + screen.blit(quit_surface, quit_rectangle) + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + if event.type == pygame.MOUSEBUTTONDOWN: + if start_rectangle.collidepoint(event.pos): + return + elif quit_rectangle.collidepoint(event.pos): + sys.exit() + pygame.display.update() + + + +def main (): + game_over = False + + pygame.init() From 1bc28bfe85d22e156957daa2ccc5210b9a1966ca Mon Sep 17 00:00:00 2001 From: Derek Camilo Date: Sun, 24 Nov 2024 22:11:48 -0500 Subject: [PATCH 04/30] Created a baseline for the title page, tweaked constants values --- constants.py | 4 ++-- sudoku.py | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/constants.py b/constants.py index eb3d31ee..4eac4d03 100644 --- a/constants.py +++ b/constants.py @@ -1,7 +1,7 @@ #All of these values are subject to change -WIDTH = 540 -HEIGHT = 600 +WIDTH = 850 +HEIGHT = 1000 BG_COLOR_1 = (255,255, 255) #White BG_COLOR_2 = (150, 10, 255) #Purple *IF NECCESSARY* TEXT = (0, 0, 0) #Black diff --git a/sudoku.py b/sudoku.py index 39a9b34a..236fd558 100644 --- a/sudoku.py +++ b/sudoku.py @@ -20,10 +20,10 @@ def game_start(screen): quit_text = button_font.render("Quit", 0, BUTTON_TEXT) #Init START/QUIT Button Text Box Background - start_surface = pygame.Surface((start_text.get_size()[0] * 20, start_text.get_size()[1] * 20)) + start_surface = pygame.Surface((start_text.get_size()[0] + 20, start_text.get_size()[1] + 20)) start_surface.fill(BUTTON_COLOR) start_surface.blit(start_text, (10, 10)) - quit_surface = pygame.Surface((quit_text.get_size()[0] * 20, quit_text.get_size()[1] * 20)) + quit_surface = pygame.Surface((quit_text.get_size()[0] + 20, quit_text.get_size()[1] + 20)) quit_surface.fill(BUTTON_COLOR) quit_surface.blit(quit_text, (10, 10)) @@ -52,3 +52,11 @@ def main (): game_over = False pygame.init() + screen = pygame.display.set_mode((WIDTH, HEIGHT)) + pygame.display.set_caption("Prog 1 Sudoku") + + game_start(screen) + + +if __name__ == "__main__": + main() From b43859a0ef432086c147e28446258584de018c0e Mon Sep 17 00:00:00 2001 From: sickunicorn24 Date: Mon, 25 Nov 2024 21:22:05 -0500 Subject: [PATCH 05/30] def is_valid --- sudoku_generator.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index b4e309ac..2ead6d17 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -19,7 +19,7 @@ class SudokuGenerator: def __init__(self, row_length, removed_cells): self.row_length = row_length self.removed_cells = removed_cells - self.board = [["-" for i in range(9)] for j in range(9)] + self.board = [["_" for i in range(row_length)] for j in range(row_length)] self.box_length = row_length ** 0.5 @@ -106,7 +106,19 @@ def valid_in_box(self, row_start, col_start, num): Return: boolean ''' def is_valid(self, row, col, num): - pass + row_start = row//3 + col_start = col//3 + + if self.valid_in_box(row_start, col_start, num): + if self.valid_in_row(row, num): + if self.valid_in_col(col, num): + return True + else: + return False + else: + return False + else: + return False ''' Fills the specified 3x3 box with values @@ -119,8 +131,19 @@ def is_valid(self, row, col, num): Return: None ''' def fill_box(self, row_start, col_start): - pass - + nums_list = [1, 2, 3, 4, 5, 6, 7, 8, 9] + + row = random.randint(row_start, row_start+2) + col = random.randint(col_start, col_start+2) + + for i in range(4): + num = random.choice(nums_list) + + if self.board[row][col] == "_": + self.board[row][col] = num + + nums_list.remove(num) + ''' 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) From f8859ce2fbf419c0453eb973a54d9c598262613d Mon Sep 17 00:00:00 2001 From: sickunicorn24 Date: Mon, 25 Nov 2024 21:22:26 -0500 Subject: [PATCH 06/30] def is_valid --- sudoku_generator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index 2ead6d17..7588800b 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -138,7 +138,6 @@ def fill_box(self, row_start, col_start): for i in range(4): num = random.choice(nums_list) - if self.board[row][col] == "_": self.board[row][col] = num From a5136ca77091acaa2ad2bdd4fddf0e79271f2ceb Mon Sep 17 00:00:00 2001 From: guhansattanathan Date: Thu, 28 Nov 2024 13:30:10 -0500 Subject: [PATCH 07/30] Add files via upload --- board.py | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 board.py diff --git a/board.py b/board.py new file mode 100644 index 00000000..d3da3b02 --- /dev/null +++ b/board.py @@ -0,0 +1,147 @@ +import pygame +from cell import Cell + + +class Board: + + def __init__(self, width, height, screen, difficulty): + + self.width = width + self.height = height + self.screen = screen + self.difficulty = difficulty + self.select_cell = (0,0) + self.grid = [] + + for x in range(0,9): + self.grid.append([0] * 9) + + self.cells = [] + + for i in range(0,9): + cells_row = [] + for j in range(0,9): + + cells_row.append(Cell(0, i, j, self.screen)) + + self.cells.append(cells_row) + + def draw(self): + + for x in range(0,10): + + width = 1 + + if x % 3 == 0: + width = 3 + + pygame.draw.line(self.screen, (0,0,0), (0, x * self.height // 9), (self.width, x * self.height // 9), width) + pygame.draw.line(self.screen, (0,0,0), (x * self.width // 9, 0), (x * self.width // 9, self.height), width) + + for x in self.cells: + for y in x: + y.draw() + + def select(self, row, col): + + self.select_cell = (row,col) + + def click(self, row, col): + + if (row < self.width and row >=0 ) and (col < self.height and col >= 0): + i = row // (self.height // 9) + j = col // (self.width // 9) + return i, j + else: + return None + + def clear(self): + + r, c = self.select_cell + + if self.grid[r][c] == 0: + self.cells[r][c].set_cell_value(0) + self.cells[r][c].set_sketched_value(0) + + def sketch(self, value): + + r,c = self.select_cell + + if self.grid[r][c] == 0: + self.cells[r][c].set_sketched_value(value) + + def place_number(self, value): + + r,c = self.select_cell + + #for event in pygame.event.get(): + + # if event.type == pygame.KEYDOWN: + + # if event.key == pygame.K_RETURN: + self.cells[r][c].set_cell_value(value) + self.cells[r][c].set_sketched_value(value) + + def reset_to_original(self): + + for x in range(0,9): + for y in range(0,9): + + self.cells[x][y].set_cell_value(self.grid[x][y]) + self.cells[x][y].set_sketched_value(0) + + def is_full(self): + + for x in self.cells: + for y in x: + if y.value == 0: + return False + + return True + + def update_board(self): + + for i in range(0,9): + for j in range(0,9): + self.grid[i][j] = self.cells[i][j].value + + def find_empty(self): + + for x in range(0,9): + for y in range(0,9): + if self.cells[x][y].value == 0: + return x,y + + def check_board(self): + + for x in range(0,9): + values1 = [] + for y in range(0,9): + values1.append(self.cells[x][y].value) + if sorted(values1) != list(range(1,10)): + return False + + for i in range(0,9): + values2 = [] + for j in range(0,9): + values2.append(self.cells[j][i].value) + if sorted(values2)!= list(range(1,10)): + return False + + for row in range(0, 9, 3): + for col in range(0, 9, 3): + threebox = [] + for x in range(0,3): + for y in range(0,3): + threebox.append(self.cells[row + x][col + y].value) + if sorted(threebox) != list(range(1, 10)): + return False + + return True + + + + + + + From 7b2bceffefc17ae5ef0622115f4204322599b260 Mon Sep 17 00:00:00 2001 From: sickunicorn24 Date: Sat, 30 Nov 2024 23:26:07 -0500 Subject: [PATCH 08/30] fill functions and remove function --- sudoku_generator.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index 7588800b..89244e1c 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -1,4 +1,4 @@ -import math,random +import random class SudokuGenerator: ''' @@ -106,8 +106,8 @@ def valid_in_box(self, row_start, col_start, num): Return: boolean ''' def is_valid(self, row, col, num): - row_start = row//3 - col_start = col//3 + row_start = row // 3 + col_start = col // 3 if self.valid_in_box(row_start, col_start, num): if self.valid_in_row(row, num): @@ -133,15 +133,12 @@ def is_valid(self, row, col, num): def fill_box(self, row_start, col_start): nums_list = [1, 2, 3, 4, 5, 6, 7, 8, 9] - row = random.randint(row_start, row_start+2) - col = random.randint(col_start, col_start+2) - - for i in range(4): - num = random.choice(nums_list) - if self.board[row][col] == "_": - self.board[row][col] = num - - nums_list.remove(num) + for row in range(row_start, row_start+3): + for col in range(col_start, col_start+3): + num = random.choice(nums_list) + if self.valid_in_box(row_start, col_start, num): + self.board[row][col] = num + nums_list.remove(num) ''' Fills the three boxes along the main diagonal of the board @@ -151,7 +148,8 @@ def fill_box(self, row_start, col_start): Return: None ''' def fill_diagonal(self): - pass + for start in range(0, self.row_length, 3): + self.fill_box(start, start) ''' DO NOT CHANGE @@ -217,7 +215,14 @@ def fill_values(self): Return: None ''' 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) + + if self.board[row][col] == 0: + continue + + self.board[row][col] = 0 ''' DO NOT CHANGE From 3386993098678874600278161dcbb6c93422aa3c Mon Sep 17 00:00:00 2001 From: sickunicorn24 Date: Sat, 30 Nov 2024 23:27:34 -0500 Subject: [PATCH 09/30] fill functions and remove function --- sudoku_generator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index 89244e1c..c9724e66 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -8,7 +8,6 @@ class SudokuGenerator: 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 From 08762b312edea4ce669ac715df7e1d50b406eb01 Mon Sep 17 00:00:00 2001 From: Derek Camilo Date: Mon, 2 Dec 2024 01:28:16 -0500 Subject: [PATCH 10/30] changed the buttons because they were wrong --- constants.py | 3 +++ sudoku.py | 68 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/constants.py b/constants.py index 4eac4d03..fe46bd08 100644 --- a/constants.py +++ b/constants.py @@ -8,3 +8,6 @@ TITLE_TEXT = (255, 10, 200) #Pink BUTTON_COLOR = (255, 10, 200) #Pink BUTTON_TEXT = (255,255, 255) +EASY = 30 +MEDIUM = 40 +HARD = 50 diff --git a/sudoku.py b/sudoku.py index 236fd558..17c96123 100644 --- a/sudoku.py +++ b/sudoku.py @@ -5,57 +5,73 @@ def game_start(screen): #Title/Button font init start_title_font = pygame.font.Font(None, 100) + subtitle_font = pygame.font.Font(None, 75) button_font = pygame.font.Font(None, 70) - + #Background coloring screen.fill(BG_COLOR_1) #Creating title text - title_surface = start_title_font.render("Welcome to Sudoku", 0, TITLE_TEXT) - title_rectangle = title_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 - 150)) - screen.blit(title_surface, title_rectangle) - - #Init Button - start_text = button_font.render("Start", 0, BUTTON_TEXT) - quit_text = button_font.render("Quit", 0, BUTTON_TEXT) - - #Init START/QUIT Button Text Box Background - start_surface = pygame.Surface((start_text.get_size()[0] + 20, start_text.get_size()[1] + 20)) - start_surface.fill(BUTTON_COLOR) - start_surface.blit(start_text, (10, 10)) - quit_surface = pygame.Surface((quit_text.get_size()[0] + 20, quit_text.get_size()[1] + 20)) - quit_surface.fill(BUTTON_COLOR) - quit_surface.blit(quit_text, (10, 10)) + main_title_surface = start_title_font.render("Welcome to Sudoku", 0, TITLE_TEXT) + main_title_rectangle = main_title_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 - 300)) + screen.blit(main_title_surface, main_title_rectangle) + subtitle_surface = subtitle_font.render("Select Game Mode:", 0, TITLE_TEXT) + subtitle_rectangle = subtitle_surface.get_rect(center = (WIDTH // 2 , HEIGHT // 2 - 50)) + screen.blit(subtitle_surface, subtitle_rectangle) + + #Init Buttons + easy_text = button_font.render("Easy", 0, BUTTON_TEXT) + medium_text = button_font.render("Medium", 0, BUTTON_TEXT) + hard_text = button_font.render("Hard", 0, BUTTON_TEXT) + + #Init Easy/Medium/Hard Button Text Box Background + easy_surface = pygame.Surface((easy_text.get_size()[0] + 20, easy_text.get_size()[1] + 20)) + easy_surface.fill(BUTTON_COLOR) + easy_surface.blit(easy_text, (10, 10)) + medium_surface = pygame.Surface((medium_text.get_size()[0] + 20, medium_text.get_size()[1] + 20)) + medium_surface.fill(BUTTON_COLOR) + medium_surface.blit(medium_text, (10, 10)) + hard_surface = pygame.Surface((hard_text.get_size()[0] + 20, hard_text.get_size()[1] + 20)) + hard_surface.fill(BUTTON_COLOR) + hard_surface.blit(hard_text, (10, 10)) + #Init Button Rectangle - start_rectangle = start_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 + 50)) - quit_rectangle = quit_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 + 150)) + easy_rectangle = easy_surface.get_rect(center = (WIDTH // 2 + 200 , HEIGHT // 2 + 150)) + medium_rectangle = medium_surface.get_rect(center = (WIDTH // 2 , HEIGHT // 2 + 150)) + hard_rectangle = hard_surface.get_rect(center = (WIDTH // 2 - 200, HEIGHT // 2 + 150)) #Draw Buttons - screen.blit(start_surface, start_rectangle) - screen.blit(quit_surface, quit_rectangle) - + screen.blit(easy_surface, easy_rectangle) + screen.blit(medium_surface, medium_rectangle) + screen.blit(hard_surface, hard_rectangle) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: - if start_rectangle.collidepoint(event.pos): + if easy_rectangle.collidepoint(event.pos): + return + elif medium_rectangle.collidepoint(event.pos): + return + elif hard_rectangle.collidepoint(event.pos): return - elif quit_rectangle.collidepoint(event.pos): - sys.exit() pygame.display.update() def main (): - game_over = False + game_over = False pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Prog 1 Sudoku") - game_start(screen) + difficulty = game_start(screen) + board = SudokuGenerator(9, difficulty) + + #board.print_board() + #For debugging ^ if __name__ == "__main__": From 27e5dccd03a60139f46f24782e795f301bef5fcd Mon Sep 17 00:00:00 2001 From: Derek Camilo Date: Mon, 2 Dec 2024 02:20:34 -0500 Subject: [PATCH 11/30] filled out the during game screen function --- sudoku.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/sudoku.py b/sudoku.py index 17c96123..67dc0623 100644 --- a/sudoku.py +++ b/sudoku.py @@ -1,4 +1,9 @@ +from idlelib.pyshell import restart_line +from sys import displayhook + import pygame, sys +from pygame.display import update + from constants import * from sudoku_generator import * @@ -51,17 +56,71 @@ def game_start(screen): sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: if easy_rectangle.collidepoint(event.pos): - return + return EASY elif medium_rectangle.collidepoint(event.pos): - return + return MEDIUM elif hard_rectangle.collidepoint(event.pos): - return + return HARD pygame.display.update() +def during_game(screen, difficulty): + #Init Fonts + bottom_button_font = pygame.font.Font(None, 50) + small_msg_font = pygame.font.Font(None, 30) + + # BG color + screen.fill(BG_COLOR_2) + + #Init small message that displays the difficulty + small_msg_surface = small_msg_font.render(difficulty, 0, TEXT) + small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2, HEIGHT - 50)) + screen.blit(small_msg_surface, small_msg_rectangle) + + + #Text displays for the RESET/RESTART/EXIT buttons + reset_text = bottom_button_font.render("RESET", 0, TEXT) + restart_text = bottom_button_font.render("RESTART", 0, TEXT) + exit_text = bottom_button_font.render("EXIT", 0, TEXT) + + # + reset_surface = pygame.Surface((reset_text.get_size()[0] + 20, reset_text.get_size()[1] + 20)) + reset_surface.fill(BUTTON_COLOR) + reset_surface.blit(reset_text, (10, 10)) + restart_surface = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) + restart_surface.fill(BUTTON_COLOR) + restart_surface.blit(restart_text, (10, 10)) + exit_surface = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) + exit_surface.fill(BUTTON_COLOR) + exit_surface.blit(exit_text, (10, 10)) + + # + reset_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 150)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 150)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 150)) + + # + screen.blit(reset_surface, reset_rectangle) + screen.blit(restart_surface, restart_rectangle) + screen.blit(exit_surface, exit_rectangle) + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + if event.type == pygame.MOUSEBUTTONDOWN: + if reset_rectangle.collidepoint(event.pos): + return + elif restart_rectangle.collidepoint(event.pos): + return + elif exit_rectangle.collidepoint(event.pos): + sys.exit() + pygame.display.update() + def main (): game_over = False + dif = "" pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) @@ -69,6 +128,14 @@ def main (): difficulty = game_start(screen) board = SudokuGenerator(9, difficulty) + if difficulty == 30: + dif = "EASY" + elif difficulty == 40: + dif = "MEDIUM" + elif difficulty == 50: + dif = "HARD" + screen.fill(BG_COLOR_1) + during_game(screen, dif) #board.print_board() #For debugging ^ From 0eb4038a3d634265dc68b7b12e8aa8acf0a94446 Mon Sep 17 00:00:00 2001 From: Derek Camilo Date: Mon, 2 Dec 2024 02:42:21 -0500 Subject: [PATCH 12/30] def win_screen function --- constants.py | 7 +++++-- sudoku.py | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/constants.py b/constants.py index fe46bd08..c49cb6b4 100644 --- a/constants.py +++ b/constants.py @@ -2,12 +2,15 @@ WIDTH = 850 HEIGHT = 1000 -BG_COLOR_1 = (255,255, 255) #White +BG_COLOR_1 = (125, 248, 255) #Light Blue BG_COLOR_2 = (150, 10, 255) #Purple *IF NECCESSARY* +WIN_BG = (125, 255, 125) # Green +LOSE_BG = (250, 52, 52) # Red TEXT = (0, 0, 0) #Black TITLE_TEXT = (255, 10, 200) #Pink BUTTON_COLOR = (255, 10, 200) #Pink -BUTTON_TEXT = (255,255, 255) +BUTTON_COLOR_2 = (255, 255, 255) +BUTTON_TEXT = (125, 248, 255) #Light Blue EASY = 30 MEDIUM = 40 HARD = 50 diff --git a/sudoku.py b/sudoku.py index 67dc0623..8887e94e 100644 --- a/sudoku.py +++ b/sudoku.py @@ -115,7 +115,45 @@ def during_game(screen, difficulty): elif exit_rectangle.collidepoint(event.pos): sys.exit() pygame.display.update() - + +def win_screen(screen): + # Title/Button font init + title_font = pygame.font.Font(None, 100) + button_font = pygame.font.Font(None, 100) + + # Background coloring + screen.fill(WIN_BG) + + # Creating title text + title_surface = title_font.render("YOU WON!!!", 0, TEXT) + title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 300)) + screen.blit(title_surface, title_rectangle) + + # Init Buttons + exit_text = button_font.render("EXIT", 0, TEXT) + + # Init Easy/Medium/Hard Button Text Box Background + exit_surface = pygame.Surface((exit_text.get_size()[0] + 40, exit_text.get_size()[1] + 40)) + exit_surface.fill(BG_COLOR_2) + exit_surface.blit(exit_text, (20, 20)) + + # Init Button Rectangle + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2)) + + # Draw Buttons + screen.blit(exit_surface, exit_rectangle) + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + if event.type == pygame.MOUSEBUTTONDOWN: + if exit_rectangle.collidepoint(event.pos): + sys.exit() + pygame.display.update() + +def lose_screen(screen): + pass + def main (): @@ -136,6 +174,7 @@ def main (): dif = "HARD" screen.fill(BG_COLOR_1) during_game(screen, dif) + win_screen(screen) #board.print_board() #For debugging ^ From c0309a5abe67038bef50933ac2e50ae1e26a5ad4 Mon Sep 17 00:00:00 2001 From: Derek Camilo Date: Mon, 2 Dec 2024 03:50:08 -0500 Subject: [PATCH 13/30] figured out outlines --- sudoku.py | 144 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 121 insertions(+), 23 deletions(-) diff --git a/sudoku.py b/sudoku.py index 8887e94e..c2479e7a 100644 --- a/sudoku.py +++ b/sudoku.py @@ -9,8 +9,8 @@ def game_start(screen): #Title/Button font init - start_title_font = pygame.font.Font(None, 100) - subtitle_font = pygame.font.Font(None, 75) + start_title_font = pygame.font.Font(None, 120) + subtitle_font = pygame.font.Font(None, 90) button_font = pygame.font.Font(None, 70) #Background coloring @@ -19,15 +19,25 @@ def game_start(screen): #Creating title text main_title_surface = start_title_font.render("Welcome to Sudoku", 0, TITLE_TEXT) main_title_rectangle = main_title_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 - 300)) + #Create outline + main_title_outline = start_title_font.render("Welcome to Sudoku", 0, TEXT) + for i in range (-3, 4): + for j in range(-3, 4): + screen.blit(main_title_outline, main_title_surface.get_rect(center = (WIDTH //2 + i, HEIGHT // 2 - 300 + j))) screen.blit(main_title_surface, main_title_rectangle) + #Creating Subtitle subtitle_surface = subtitle_font.render("Select Game Mode:", 0, TITLE_TEXT) subtitle_rectangle = subtitle_surface.get_rect(center = (WIDTH // 2 , HEIGHT // 2 - 50)) + subtitle_outline = subtitle_font.render("Select Game Mode:", 0, TEXT) + for i in range(-3, 4): + for j in range(-3, 4): + screen.blit(subtitle_outline, subtitle_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 50 + j))) screen.blit(subtitle_surface, subtitle_rectangle) #Init Buttons - easy_text = button_font.render("Easy", 0, BUTTON_TEXT) - medium_text = button_font.render("Medium", 0, BUTTON_TEXT) - hard_text = button_font.render("Hard", 0, BUTTON_TEXT) + easy_text = button_font.render("Easy", 0, TEXT) + medium_text = button_font.render("Medium", 0, TEXT) + hard_text = button_font.render("Hard", 0, TEXT) #Init Easy/Medium/Hard Button Text Box Background easy_surface = pygame.Surface((easy_text.get_size()[0] + 20, easy_text.get_size()[1] + 20)) @@ -46,7 +56,23 @@ def game_start(screen): medium_rectangle = medium_surface.get_rect(center = (WIDTH // 2 , HEIGHT // 2 + 150)) hard_rectangle = hard_surface.get_rect(center = (WIDTH // 2 - 200, HEIGHT // 2 + 150)) + #Init Button Outlines + easy_ot_surface = pygame.Surface((easy_text.get_size()[0] + 30, easy_text.get_size()[1] + 30)) + easy_ot_surface.fill(TEXT) + medium_ot_surface = pygame.Surface((medium_text.get_size()[0] + 30, medium_text.get_size()[1] + 30)) + medium_ot_surface.fill(TEXT) + hard_ot_surface = pygame.Surface((hard_text.get_size()[0] + 30, hard_text.get_size()[1] + 30)) + hard_ot_surface.fill(TEXT) + + easy_ot_rectangle = easy_ot_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT // 2 + 150)) + medium_ot_rectangle = medium_ot_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) + hard_ot_rectangle = hard_ot_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT // 2 + 150)) + + #Draw Buttons + screen.blit(easy_ot_surface, easy_ot_rectangle) + screen.blit(medium_ot_surface, medium_ot_rectangle) + screen.blit(hard_ot_surface, hard_ot_rectangle) screen.blit(easy_surface, easy_rectangle) screen.blit(medium_surface, medium_rectangle) screen.blit(hard_surface, hard_rectangle) @@ -118,7 +144,7 @@ def during_game(screen, difficulty): def win_screen(screen): # Title/Button font init - title_font = pygame.font.Font(None, 100) + title_font = pygame.font.Font(None, 150) button_font = pygame.font.Font(None, 100) # Background coloring @@ -126,22 +152,47 @@ def win_screen(screen): # Creating title text title_surface = title_font.render("YOU WON!!!", 0, TEXT) - title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 300)) + title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 250)) screen.blit(title_surface, title_rectangle) - # Init Buttons + # Init Exit Button exit_text = button_font.render("EXIT", 0, TEXT) - # Init Easy/Medium/Hard Button Text Box Background + # Init Exit Button Text Box Background exit_surface = pygame.Surface((exit_text.get_size()[0] + 40, exit_text.get_size()[1] + 40)) exit_surface.fill(BG_COLOR_2) exit_surface.blit(exit_text, (20, 20)) # Init Button Rectangle - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) + + # Init Restart Button + restart_text = button_font.render("RESTART", 0, TEXT) + + # Init Restart Button Text Box Background + restart_surface = pygame.Surface((restart_text.get_size()[0] + 40, restart_text.get_size()[1] + 40)) + restart_surface.fill(BG_COLOR_2) + restart_surface.blit(restart_text, (20, 20)) + + # Init Button Rectangle + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) + + #Init Restart Button Outline + restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 50, restart_text.get_size()[1] + 50)) + restart_ot_surface.fill(TEXT) + restart_ot_rectangle = restart_ot_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) + + #Init Exit Button Outline + exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 50, exit_text.get_size()[1] + 50)) + exit_ot_surface.fill(TEXT) + exit_ot_rectangle = exit_ot_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) # Draw Buttons + screen.blit(restart_ot_surface, restart_ot_rectangle) + screen.blit(exit_ot_surface, exit_ot_rectangle) + screen.blit(restart_surface, restart_rectangle) screen.blit(exit_surface, exit_rectangle) + while True: for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -149,10 +200,56 @@ def win_screen(screen): if event.type == pygame.MOUSEBUTTONDOWN: if exit_rectangle.collidepoint(event.pos): sys.exit() + elif restart_rectangle.collidepoint(event.pos): + return pygame.display.update() def lose_screen(screen): - pass + # Title/Button font init + title_font = pygame.font.Font(None, 150) + button_font = pygame.font.Font(None, 100) + + # Background coloring + screen.fill(LOSE_BG) + + # Creating title text + title_surface = title_font.render("YOU LOST :<(", 0, TEXT) + title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 250)) + screen.blit(title_surface, title_rectangle) + + # Init Restart Button + restart_text = button_font.render("RESTART", 0, TEXT) + + # Init Restart Button Text Box Background + restart_surface = pygame.Surface((restart_text.get_size()[0] + 40, restart_text.get_size()[1] + 40)) + restart_surface.fill(BG_COLOR_1) + restart_surface.blit(restart_text, (20, 20)) + + # Init Button Rectangle + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2 + 150, HEIGHT // 2)) + + # Init Exit Button + exit_text = button_font.render("EXIT", 0, TEXT) + + # Init Exit Button Text Box Background + exit_surface = pygame.Surface((exit_text.get_size()[0] + 40, exit_text.get_size()[1] + 40)) + exit_surface.fill(BG_COLOR_1) + exit_surface.blit(exit_text, (20, 20)) + + # Init Button Rectangle + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 150, HEIGHT // 2)) + + # Draw Buttons + screen.blit(restart_surface, restart_rectangle) + screen.blit(exit_surface, exit_rectangle) + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + if event.type == pygame.MOUSEBUTTONDOWN: + if restart_rectangle.collidepoint(event.pos): + return + pygame.display.update() @@ -163,18 +260,19 @@ def main (): pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Prog 1 Sudoku") - - difficulty = game_start(screen) - board = SudokuGenerator(9, difficulty) - if difficulty == 30: - dif = "EASY" - elif difficulty == 40: - dif = "MEDIUM" - elif difficulty == 50: - dif = "HARD" - screen.fill(BG_COLOR_1) - during_game(screen, dif) - win_screen(screen) + while True: + difficulty = game_start(screen) + board = SudokuGenerator(9, difficulty) + if difficulty == 30: + dif = "EASY" + elif difficulty == 40: + dif = "MEDIUM" + elif difficulty == 50: + dif = "HARD" + screen.fill(BG_COLOR_1) + during_game(screen, dif) + lose_screen(screen) + win_screen(screen) #board.print_board() #For debugging ^ From 8a9ea48da8aa2b58e0004bf3cdfe6529f43a65d1 Mon Sep 17 00:00:00 2001 From: sickunicorn24 Date: Mon, 2 Dec 2024 13:22:07 -0500 Subject: [PATCH 14/30] finished --- sudoku_generator.py | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index c9724e66..635211a7 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -18,16 +18,16 @@ class SudokuGenerator: def __init__(self, row_length, removed_cells): self.row_length = row_length self.removed_cells = removed_cells - self.board = [["_" for i in range(row_length)] for j in range(row_length)] - self.box_length = row_length ** 0.5 - + self.board = [[0 for i in range(row_length)] for j in range(row_length)] + self.box_length = int(row_length ** 0.5) ''' - Returns a 2D python list of numbers which represents the board + Returns a 2D python list of numbers which represents the board Parameters: None Return: list[list] ''' + def get_board(self): return self.board @@ -38,6 +38,7 @@ def get_board(self): Parameters: None Return: None ''' + def print_board(self): for row in self.board: for col in row: @@ -54,6 +55,7 @@ def print_board(self): Return: boolean ''' + def valid_in_row(self, row, num): if num in self.board[row]: return False @@ -69,6 +71,7 @@ def valid_in_row(self, row, num): Return: boolean ''' + def valid_in_col(self, col, num): for row in self.board: if row[col] == num: @@ -87,9 +90,10 @@ def valid_in_col(self, col, num): Return: boolean ''' + def valid_in_box(self, row_start, col_start, num): - for row in range(row_start, row_start+2): - for col in range(col_start, col_start+2): + 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 @@ -104,20 +108,16 @@ def valid_in_box(self, row_start, col_start, num): Return: boolean ''' + def is_valid(self, row, col, num): - row_start = row // 3 - col_start = col // 3 + row_start = (row // 3) * 3 + col_start = (col // 3) * 3 if self.valid_in_box(row_start, col_start, num): if self.valid_in_row(row, num): if self.valid_in_col(col, num): return True - else: - return False - else: - return False - else: - return False + return False ''' Fills the specified 3x3 box with values @@ -129,15 +129,18 @@ def is_valid(self, row, col, num): Return: None ''' + def fill_box(self, row_start, col_start): nums_list = [1, 2, 3, 4, 5, 6, 7, 8, 9] + random.shuffle(nums_list) for row in range(row_start, row_start+3): for col in range(col_start, col_start+3): - num = random.choice(nums_list) - if self.valid_in_box(row_start, col_start, num): - self.board[row][col] = num - nums_list.remove(num) + for num in nums_list: + if self.valid_in_box(row_start, col_start, num): + self.board[row][col] = num + nums_list.remove(num) + break ''' Fills the three boxes along the main diagonal of the board @@ -146,6 +149,7 @@ def fill_box(self, row_start, col_start): Parameters: None Return: None ''' + def fill_diagonal(self): for start in range(0, self.row_length, 3): self.fill_box(start, start) @@ -162,6 +166,7 @@ def fill_diagonal(self): 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 @@ -197,6 +202,7 @@ def fill_remaining(self, row, col): Parameters: None Return: None ''' + def fill_values(self): self.fill_diagonal() self.fill_remaining(0, self.box_length) @@ -213,6 +219,7 @@ def fill_values(self): Parameters: None Return: None ''' + def remove_cells(self): for i in range(self.removed_cells): row = random.randint(0, self.row_length-1) @@ -238,6 +245,7 @@ def remove_cells(self): Return: list[list] (a 2D Python list to represent the board) ''' + def generate_sudoku(size, removed): sudoku = SudokuGenerator(size, removed) sudoku.fill_values() @@ -245,3 +253,4 @@ def generate_sudoku(size, removed): sudoku.remove_cells() board = sudoku.get_board() return board + From 42973f6b9797754d30bb54f783d4a8ec569034eb Mon Sep 17 00:00:00 2001 From: sickunicorn24 Date: Mon, 2 Dec 2024 13:36:07 -0500 Subject: [PATCH 15/30] fill box and removed functions changed --- sudoku_generator.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index 635211a7..846e9195 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -137,7 +137,7 @@ def fill_box(self, row_start, col_start): for row in range(row_start, row_start+3): for col in range(col_start, col_start+3): for num in nums_list: - if self.valid_in_box(row_start, col_start, num): + if self.valid_in_box(row_start, col_start, num) and self.valid_in_col(col, num) and self.valid_in_row(row, num): self.board[row][col] = num nums_list.remove(num) break @@ -221,7 +221,8 @@ def fill_values(self): ''' def remove_cells(self): - for i in range(self.removed_cells): + removed = 0 + while removed < self.removed_cells: row = random.randint(0, self.row_length-1) col = random.randint(0, self.row_length-1) @@ -229,6 +230,7 @@ def remove_cells(self): continue self.board[row][col] = 0 + removed += 1 ''' DO NOT CHANGE From c99233d4e50cc5bcbf14b44872f01136f7859e80 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Mon, 2 Dec 2024 14:06:53 -0500 Subject: [PATCH 16/30] Added cell and board --- .idea/.gitignore | 8 ++ .idea/Sudoku-Project.iml | 12 +++ .idea/inspectionProfiles/Project_Default.xml | 20 +++++ .../inspectionProfiles/profiles_settings.xml | 6 ++ .idea/misc.xml | 7 ++ .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 ++ board.py | 84 +++++++++++++++++++ cell.py | 33 ++++++++ 9 files changed, 184 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/Sudoku-Project.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml 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 create mode 100644 board.py create mode 100644 cell.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/Sudoku-Project.iml b/.idea/Sudoku-Project.iml new file mode 100644 index 00000000..8a05c6ed --- /dev/null +++ b/.idea/Sudoku-Project.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..ae089e89 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,20 @@ + + + + \ 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..e557d17a --- /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..4de2d014 --- /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 diff --git a/board.py b/board.py new file mode 100644 index 00000000..d8ec1143 --- /dev/null +++ b/board.py @@ -0,0 +1,84 @@ +import pygame +from cell import Cell + +class Board: + def __init__(self, width, height, screen, difficulty): + self.width = width + self.height = height + self.screen = screen + self.difficulty = difficulty + self.cells = [] + self.selected_cell = None + self.generate_board() + + def generate_board(self): + board_values = [[0 for _ in range(9)] for _ in range(9)] + for row in range(9): + cell_row = [] + for col in range(9): + cell_row.append(Cell(board_values[row][col], row, col, self.screen)) + self.cells.append(cell_row) + + def draw(self): + for row in range(10): + thickness = 2 if row % 3 == 0 else 1 + pygame.draw.line(self.screen, (0, 0, 0), (0, row * 60), (540, row * 60), thickness) + pygame.draw.line(self.screen, (0, 0, 0), (row * 60, 0), (row * 60, 540), thickness) + + for row in self.cells: + for cell in row: + cell.draw() + + def select(self, row, col): + if self.selected_cell: + self.selected_cell.selected = False + self.selected_cell = self.cells[row][col] + self.selected_cell.selected = True + + def click(self, x, y): + if x < self.width and y < self.height: + row, col = y // 60, x // 60 + self.select(row, col) + return row, col + return None + + def clear(self): + if self.selected_cell and self.selected_cell.value == 0: + self.selected_cell.set_sketched_value(0) + + def sketch(self, value): + if self.selected_cell and self.selected_cell.value == 0: + self.selected_cell.set_sketched_value(value) + + def place_number(self, value): + if self.selected_cell and self.selected_cell.value == 0: + self.selected_cell.set_cell_value(value) + self.selected_cell.set_sketched_value(0) + + def reset_to_original(self): + for row in self.cells: + for cell in row: + if cell.value == 0: + cell.set_cell_value(0) + cell.set_sketched_value(0) + + def is_full(self): + for row in self.cells: + for cell in row: + if cell.value == 0: + return False + return True + + def update_board(self): + board = [[cell.value for cell in row] for row in self.cells] + return board + + def find_empty(self): + for row in range(9): + for col in range(9): + if self.cells[row][col].value == 0: + return row, col + return None + + def check_board(self): + pass diff --git a/cell.py b/cell.py new file mode 100644 index 00000000..cda8da58 --- /dev/null +++ b/cell.py @@ -0,0 +1,33 @@ +import pygame + +class Cell: + def __init__(self, value, row, col, screen, size=60): + self.value = value + self.sketched_value = 0 + self.row = row + self.col = col + self.screen = screen + self.size = size + self.selected = False + + def set_cell_value(self, value): + self.value = value + + def set_sketched_value(self, value): + self.sketched_value = value + + def draw(self): + x = self.col * self.size + y = self.row * self.size + + color = (255, 0, 0) if self.selected else (0, 0, 0) + pygame.draw.rect(self.screen, color, (x, y, self.size, self.size), 2) + + font = pygame.font.Font(None, 40) + + if self.value != 0: + text = font.render(str(self.value), True, (0, 0, 0)) + self.screen.blit(text, (x + self.size // 3, y + self.size // 4)) + elif self.sketched_value != 0: + text = font.render(str(self.sketched_value), True, (128, 128, 128)) + self.screen.blit(text, (x + 5, y + 5)) From da48ba26cef4de1c66f2d80644d8efc879a77c95 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Mon, 2 Dec 2024 14:22:23 -0500 Subject: [PATCH 17/30] Updated Board --- board.py | 100 ++++++++++--------------------------------------------- 1 file changed, 18 insertions(+), 82 deletions(-) diff --git a/board.py b/board.py index d8ec1143..8868eb7b 100644 --- a/board.py +++ b/board.py @@ -1,84 +1,20 @@ -import pygame -from cell import Cell - class Board: - def __init__(self, width, height, screen, difficulty): - self.width = width - self.height = height - self.screen = screen - self.difficulty = difficulty - self.cells = [] - self.selected_cell = None - self.generate_board() - - def generate_board(self): - board_values = [[0 for _ in range(9)] for _ in range(9)] - for row in range(9): - cell_row = [] - for col in range(9): - cell_row.append(Cell(board_values[row][col], row, col, self.screen)) - self.cells.append(cell_row) - - def draw(self): - for row in range(10): - thickness = 2 if row % 3 == 0 else 1 - pygame.draw.line(self.screen, (0, 0, 0), (0, row * 60), (540, row * 60), thickness) - pygame.draw.line(self.screen, (0, 0, 0), (row * 60, 0), (row * 60, 540), thickness) - - for row in self.cells: - for cell in row: - cell.draw() - - def select(self, row, col): - if self.selected_cell: - self.selected_cell.selected = False - self.selected_cell = self.cells[row][col] - self.selected_cell.selected = True - - def click(self, x, y): - if x < self.width and y < self.height: - row, col = y // 60, x // 60 - self.select(row, col) - return row, col - return None - - def clear(self): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_sketched_value(0) - - def sketch(self, value): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_sketched_value(value) - - def place_number(self, value): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_cell_value(value) - self.selected_cell.set_sketched_value(0) - - def reset_to_original(self): - for row in self.cells: - for cell in row: - if cell.value == 0: - cell.set_cell_value(0) - cell.set_sketched_value(0) - - def is_full(self): - for row in self.cells: - for cell in row: - if cell.value == 0: - return False + def __init__(self, row_length=9): + self.row_length = row_length + self.board = [[0] * row_length for _ in range(row_length)] + + def print_board(self): + for row in self.board: + print(" ".join(str(cell) if cell != 0 else '.' for cell in row)) + + def update_cell(self, row, col, num): + if 1 <= num <= 9 and self.board[row][col] == 0: + self.board[row][col] = num + return True + return False + + def is_solved(self): + for row in self.board: + if 0 in row: + return False return True - - def update_board(self): - board = [[cell.value for cell in row] for row in self.cells] - return board - - def find_empty(self): - for row in range(9): - for col in range(9): - if self.cells[row][col].value == 0: - return row, col - return None - - def check_board(self): - pass From e4b69e735e330bd65450f323ee11292a3216cfe8 Mon Sep 17 00:00:00 2001 From: Derek Camilo Date: Mon, 2 Dec 2024 14:32:50 -0500 Subject: [PATCH 18/30] changed constant variables to reflect colors to avoid confusion, changed the button types and fixed any errors with the buttons. --- constants.py | 26 +++++---- sudoku.py | 149 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 103 insertions(+), 72 deletions(-) diff --git a/constants.py b/constants.py index c49cb6b4..063064cd 100644 --- a/constants.py +++ b/constants.py @@ -1,16 +1,14 @@ #All of these values are subject to change -WIDTH = 850 -HEIGHT = 1000 -BG_COLOR_1 = (125, 248, 255) #Light Blue -BG_COLOR_2 = (150, 10, 255) #Purple *IF NECCESSARY* -WIN_BG = (125, 255, 125) # Green -LOSE_BG = (250, 52, 52) # Red -TEXT = (0, 0, 0) #Black -TITLE_TEXT = (255, 10, 200) #Pink -BUTTON_COLOR = (255, 10, 200) #Pink -BUTTON_COLOR_2 = (255, 255, 255) -BUTTON_TEXT = (125, 248, 255) #Light Blue -EASY = 30 -MEDIUM = 40 -HARD = 50 +WIDTH = 850 # Window Width +HEIGHT = 1000 # Window Height +LIGHT_BLUE = (125, 248, 255) #Light Blue +PURPLE = (150, 10, 255) #Purple +GREEN = (125, 255, 125) # Green +RED = (250, 52, 52) # Red +BLACK = (0, 0, 0) #Black +PINK = (255, 10, 200) #Pink +WHITE = (255, 255, 255) #White +EASY = 30 # Easy difficulty squares unfilled +MEDIUM = 40 # Medium difficulty squares unfilled +HARD = 50 # Hard difficulty squares unfilled diff --git a/sudoku.py b/sudoku.py index c2479e7a..44f3c910 100644 --- a/sudoku.py +++ b/sudoku.py @@ -3,7 +3,8 @@ import pygame, sys from pygame.display import update - +from board import Board +from cell import Cell from constants import * from sudoku_generator import * @@ -14,40 +15,40 @@ def game_start(screen): button_font = pygame.font.Font(None, 70) #Background coloring - screen.fill(BG_COLOR_1) + screen.fill(LIGHT_BLUE) #Creating title text - main_title_surface = start_title_font.render("Welcome to Sudoku", 0, TITLE_TEXT) + main_title_surface = start_title_font.render("Welcome to Sudoku", 0, PINK) main_title_rectangle = main_title_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 - 300)) #Create outline - main_title_outline = start_title_font.render("Welcome to Sudoku", 0, TEXT) - for i in range (-3, 4): - for j in range(-3, 4): + main_title_outline = start_title_font.render("Welcome to Sudoku", 0, BLACK) + for i in range (-4, 5): + for j in range(-4, 5): screen.blit(main_title_outline, main_title_surface.get_rect(center = (WIDTH //2 + i, HEIGHT // 2 - 300 + j))) screen.blit(main_title_surface, main_title_rectangle) #Creating Subtitle - subtitle_surface = subtitle_font.render("Select Game Mode:", 0, TITLE_TEXT) + subtitle_surface = subtitle_font.render("Select Game Mode:", 0, PINK) subtitle_rectangle = subtitle_surface.get_rect(center = (WIDTH // 2 , HEIGHT // 2 - 50)) - subtitle_outline = subtitle_font.render("Select Game Mode:", 0, TEXT) - for i in range(-3, 4): - for j in range(-3, 4): + subtitle_outline = subtitle_font.render("Select Game Mode:", 0, BLACK) + for i in range(-4, 5): + for j in range(-4, 5): screen.blit(subtitle_outline, subtitle_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 50 + j))) screen.blit(subtitle_surface, subtitle_rectangle) #Init Buttons - easy_text = button_font.render("Easy", 0, TEXT) - medium_text = button_font.render("Medium", 0, TEXT) - hard_text = button_font.render("Hard", 0, TEXT) + easy_text = button_font.render("Easy", 0, BLACK) + medium_text = button_font.render("Medium", 0, BLACK) + hard_text = button_font.render("Hard", 0, BLACK) #Init Easy/Medium/Hard Button Text Box Background easy_surface = pygame.Surface((easy_text.get_size()[0] + 20, easy_text.get_size()[1] + 20)) - easy_surface.fill(BUTTON_COLOR) + easy_surface.fill(PINK) easy_surface.blit(easy_text, (10, 10)) medium_surface = pygame.Surface((medium_text.get_size()[0] + 20, medium_text.get_size()[1] + 20)) - medium_surface.fill(BUTTON_COLOR) + medium_surface.fill(PINK) medium_surface.blit(medium_text, (10, 10)) hard_surface = pygame.Surface((hard_text.get_size()[0] + 20, hard_text.get_size()[1] + 20)) - hard_surface.fill(BUTTON_COLOR) + hard_surface.fill(PINK) hard_surface.blit(hard_text, (10, 10)) @@ -58,15 +59,15 @@ def game_start(screen): #Init Button Outlines easy_ot_surface = pygame.Surface((easy_text.get_size()[0] + 30, easy_text.get_size()[1] + 30)) - easy_ot_surface.fill(TEXT) + easy_ot_surface.fill(BLACK) medium_ot_surface = pygame.Surface((medium_text.get_size()[0] + 30, medium_text.get_size()[1] + 30)) - medium_ot_surface.fill(TEXT) + medium_ot_surface.fill(BLACK) hard_ot_surface = pygame.Surface((hard_text.get_size()[0] + 30, hard_text.get_size()[1] + 30)) - hard_ot_surface.fill(TEXT) + hard_ot_surface.fill(BLACK) - easy_ot_rectangle = easy_ot_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT // 2 + 150)) - medium_ot_rectangle = medium_ot_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) - hard_ot_rectangle = hard_ot_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT // 2 + 150)) + easy_ot_rectangle = easy_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT // 2 + 150)) + medium_ot_rectangle = medium_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) + hard_ot_rectangle = hard_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT // 2 + 150)) #Draw Buttons @@ -95,36 +96,52 @@ def during_game(screen, difficulty): small_msg_font = pygame.font.Font(None, 30) # BG color - screen.fill(BG_COLOR_2) + screen.fill(PURPLE) #Init small message that displays the difficulty - small_msg_surface = small_msg_font.render(difficulty, 0, TEXT) + small_msg_surface = small_msg_font.render(difficulty, 0, BLACK) small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2, HEIGHT - 50)) screen.blit(small_msg_surface, small_msg_rectangle) #Text displays for the RESET/RESTART/EXIT buttons - reset_text = bottom_button_font.render("RESET", 0, TEXT) - restart_text = bottom_button_font.render("RESTART", 0, TEXT) - exit_text = bottom_button_font.render("EXIT", 0, TEXT) + reset_text = bottom_button_font.render("RESET", 0, BLACK) + restart_text = bottom_button_font.render("RESTART", 0, BLACK) + exit_text = bottom_button_font.render("EXIT", 0, BLACK) - # + #Init Text Box for Buttons reset_surface = pygame.Surface((reset_text.get_size()[0] + 20, reset_text.get_size()[1] + 20)) - reset_surface.fill(BUTTON_COLOR) + reset_surface.fill(PINK) reset_surface.blit(reset_text, (10, 10)) restart_surface = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) - restart_surface.fill(BUTTON_COLOR) + restart_surface.fill(PINK) restart_surface.blit(restart_text, (10, 10)) exit_surface = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) - exit_surface.fill(BUTTON_COLOR) + exit_surface.fill(PINK) exit_surface.blit(exit_text, (10, 10)) - # + #Init Rectangles for Buttons reset_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 150)) restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 150)) exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 150)) + #Init Outlines + reset_ot_surface = pygame.Surface((reset_text.get_size()[0] + 30, reset_text.get_size()[1] + 30)) + reset_ot_surface.fill(BLACK) + restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 30, restart_text.get_size()[1] + 30)) + restart_ot_surface.fill(BLACK) + exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 30, exit_text.get_size()[1] + 30)) + exit_ot_surface.fill(BLACK) + + #Init Outline Rectangles + reset_ot_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 150)) + restart_ot_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 150)) + exit_ot_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 150)) + # + screen.blit(reset_ot_surface, reset_ot_rectangle) + screen.blit(restart_ot_surface, restart_ot_rectangle) + screen.blit(exit_ot_surface, exit_ot_rectangle) screen.blit(reset_surface, reset_rectangle) screen.blit(restart_surface, restart_rectangle) screen.blit(exit_surface, exit_rectangle) @@ -148,44 +165,44 @@ def win_screen(screen): button_font = pygame.font.Font(None, 100) # Background coloring - screen.fill(WIN_BG) + screen.fill(GREEN) # Creating title text - title_surface = title_font.render("YOU WON!!!", 0, TEXT) + title_surface = title_font.render("YOU WON!!!", 0, BLACK) title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 250)) screen.blit(title_surface, title_rectangle) # Init Exit Button - exit_text = button_font.render("EXIT", 0, TEXT) + exit_text = button_font.render("EXIT", 0, BLACK) # Init Exit Button Text Box Background exit_surface = pygame.Surface((exit_text.get_size()[0] + 40, exit_text.get_size()[1] + 40)) - exit_surface.fill(BG_COLOR_2) + exit_surface.fill(PURPLE) exit_surface.blit(exit_text, (20, 20)) # Init Button Rectangle - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) # Init Restart Button - restart_text = button_font.render("RESTART", 0, TEXT) + restart_text = button_font.render("RESTART", 0, BLACK) # Init Restart Button Text Box Background restart_surface = pygame.Surface((restart_text.get_size()[0] + 40, restart_text.get_size()[1] + 40)) - restart_surface.fill(BG_COLOR_2) + restart_surface.fill(PURPLE) restart_surface.blit(restart_text, (20, 20)) # Init Button Rectangle - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 300)) #Init Restart Button Outline restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 50, restart_text.get_size()[1] + 50)) - restart_ot_surface.fill(TEXT) - restart_ot_rectangle = restart_ot_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) + restart_ot_surface.fill(BLACK) + restart_ot_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 300)) #Init Exit Button Outline exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 50, exit_text.get_size()[1] + 50)) - exit_ot_surface.fill(TEXT) - exit_ot_rectangle = exit_ot_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) + exit_ot_surface.fill(BLACK) + exit_ot_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) # Draw Buttons screen.blit(restart_ot_surface, restart_ot_rectangle) @@ -210,36 +227,48 @@ def lose_screen(screen): button_font = pygame.font.Font(None, 100) # Background coloring - screen.fill(LOSE_BG) + screen.fill(RED) # Creating title text - title_surface = title_font.render("YOU LOST :<(", 0, TEXT) + title_surface = title_font.render("YOU LOST :<(", 0, BLACK) title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 250)) screen.blit(title_surface, title_rectangle) # Init Restart Button - restart_text = button_font.render("RESTART", 0, TEXT) + restart_text = button_font.render("RESTART", 0, BLACK) # Init Restart Button Text Box Background restart_surface = pygame.Surface((restart_text.get_size()[0] + 40, restart_text.get_size()[1] + 40)) - restart_surface.fill(BG_COLOR_1) + restart_surface.fill(LIGHT_BLUE) restart_surface.blit(restart_text, (20, 20)) # Init Button Rectangle - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2 + 150, HEIGHT // 2)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2 , HEIGHT // 2 + 300)) # Init Exit Button - exit_text = button_font.render("EXIT", 0, TEXT) + exit_text = button_font.render("EXIT", 0, BLACK) # Init Exit Button Text Box Background exit_surface = pygame.Surface((exit_text.get_size()[0] + 40, exit_text.get_size()[1] + 40)) - exit_surface.fill(BG_COLOR_1) + exit_surface.fill(LIGHT_BLUE) exit_surface.blit(exit_text, (20, 20)) # Init Button Rectangle - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 150, HEIGHT // 2)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) + + # Init Restart Button Outline + restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 50, restart_text.get_size()[1] + 50)) + restart_ot_surface.fill(BLACK) + restart_ot_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 300)) + + # Init Exit Button Outline + exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 50, exit_text.get_size()[1] + 50)) + exit_ot_surface.fill(BLACK) + exit_ot_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) # Draw Buttons + screen.blit(restart_ot_surface, restart_ot_rectangle) + screen.blit(exit_ot_surface, exit_ot_rectangle) screen.blit(restart_surface, restart_rectangle) screen.blit(exit_surface, exit_rectangle) while True: @@ -247,7 +276,9 @@ def lose_screen(screen): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: - if restart_rectangle.collidepoint(event.pos): + if exit_rectangle.collidepoint(event.pos): + sys.exit() + elif restart_rectangle.collidepoint(event.pos): return pygame.display.update() @@ -269,13 +300,15 @@ def main (): dif = "MEDIUM" elif difficulty == 50: dif = "HARD" - screen.fill(BG_COLOR_1) + screen.fill(LIGHT_BLUE) during_game(screen, dif) - lose_screen(screen) - win_screen(screen) + # lose_screen(screen) + # win_screen(screen) + # board.print_board() + # For debugging ^ + + - #board.print_board() - #For debugging ^ if __name__ == "__main__": From f57b5205a1308a1fb345cd779faa36222100b434 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Tue, 3 Dec 2024 08:50:17 -0500 Subject: [PATCH 19/30] Revert Board --- board.py | 86 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 18 deletions(-) diff --git a/board.py b/board.py index 8868eb7b..5b09d5d7 100644 --- a/board.py +++ b/board.py @@ -1,20 +1,70 @@ +import pygame +from cell import Cell class Board: - def __init__(self, row_length=9): - self.row_length = row_length - self.board = [[0] * row_length for _ in range(row_length)] - - def print_board(self): - for row in self.board: - print(" ".join(str(cell) if cell != 0 else '.' for cell in row)) - - def update_cell(self, row, col, num): - if 1 <= num <= 9 and self.board[row][col] == 0: - self.board[row][col] = num - return True - return False - - def is_solved(self): - for row in self.board: - if 0 in row: - return False + def __init__(self, width, height, screen, difficulty): + self.width = width + self.height = height + self.screen = screen + self.difficulty = difficulty + self.cells = [] + self.selected_cell = None + self.generate_board() + def generate_board(self): + board_values = [[0 for _ in range(9)] for _ in range(9)] + for row in range(9): + cell_row = [] + for col in range(9): + cell_row.append(Cell(board_values[row][col], row, col, self.screen)) + self.cells.append(cell_row) + def draw(self): + for row in range(10): + thickness = 2 if row % 3 == 0 else 1 + pygame.draw.line(self.screen, (0, 0, 0), (0, row * 60), (540, row * 60), thickness) + pygame.draw.line(self.screen, (0, 0, 0), (row * 60, 0), (row * 60, 540), thickness) + for row in self.cells: + for cell in row: + cell.draw() + def select(self, row, col): + if self.selected_cell: + self.selected_cell.selected = False + self.selected_cell = self.cells[row][col] + self.selected_cell.selected = True + def click(self, x, y): + if x < self.width and y < self.height: + row, col = y // 60, x // 60 + self.select(row, col) + return row, col + return None + def clear(self): + if self.selected_cell and self.selected_cell.value == 0: + self.selected_cell.set_sketched_value(0) + def sketch(self, value): + if self.selected_cell and self.selected_cell.value == 0: + self.selected_cell.set_sketched_value(value) + def place_number(self, value): + if self.selected_cell and self.selected_cell.value == 0: + self.selected_cell.set_cell_value(value) + self.selected_cell.set_sketched_value(0) + def reset_to_original(self): + for row in self.cells: + for cell in row: + if cell.value == 0: + cell.set_cell_value(0) + cell.set_sketched_value(0) + def is_full(self): + for row in self.cells: + for cell in row: + if cell.value == 0: + return False return True + def update_board(self): + board = [[cell.value for cell in row] for row in self.cells] + return board + def find_empty(self): + for row in range(9): + for col in range(9): + if self.cells[row][col].value == 0: + return row, col + return None + def check_board(self): + pass \ No newline at end of file From ea3bd330217b1bbb26386756a03e14ae05044285 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Tue, 3 Dec 2024 12:40:47 -0500 Subject: [PATCH 20/30] Attempted to get the board to appear. --- sudoku.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/sudoku.py b/sudoku.py index c2479e7a..68abf9a2 100644 --- a/sudoku.py +++ b/sudoku.py @@ -4,6 +4,7 @@ import pygame, sys from pygame.display import update +from board import Board from constants import * from sudoku_generator import * @@ -262,7 +263,24 @@ def main (): pygame.display.set_caption("Prog 1 Sudoku") while True: difficulty = game_start(screen) - board = SudokuGenerator(9, difficulty) + board = Board(WIDTH, HEIGHT, screen, difficulty) + board.draw + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + if event.type == pygame.MOUSEBUTTONDOWN: + pos = pygame.mouse.get_pos() + clicked_cell = board.click(pos[0], pos[1]) + + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_r: # Reset game + board.reset_to_original() + + if pygame.K_1 <= event.key <= pygame.K_9: + board.place_number(event.key - pygame.K_0) + if difficulty == 30: dif = "EASY" elif difficulty == 40: From 394f5a3e5066b51bfd1addd9efb6fbc98a4b77f1 Mon Sep 17 00:00:00 2001 From: sickunicorn24 Date: Tue, 3 Dec 2024 15:11:03 -0500 Subject: [PATCH 21/30] updated --- sudoku_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sudoku_generator.py b/sudoku_generator.py index 846e9195..d12f33b1 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -18,7 +18,7 @@ class SudokuGenerator: def __init__(self, row_length, removed_cells): self.row_length = row_length self.removed_cells = removed_cells - self.board = [[0 for i in range(row_length)] for j in range(row_length)] + self.board = [[0 for row in range(row_length)] for col in range(row_length)] self.box_length = int(row_length ** 0.5) ''' From c6044ca34e9191fc924770736153e16cd3bc858b Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Tue, 3 Dec 2024 17:45:33 -0500 Subject: [PATCH 22/30] Got the board to appear --- board.py | 152 ++++++++++---------- cell.py | 36 +++-- constants.py | 1 + sudoku.py | 382 +++++++++++++++++++++++---------------------------- 4 files changed, 276 insertions(+), 295 deletions(-) diff --git a/board.py b/board.py index 50b9d69a..3703cc35 100644 --- a/board.py +++ b/board.py @@ -1,70 +1,84 @@ -import pygame -from cell import Cell -class Board: - def __init__(self, width, height, screen, difficulty): - self.width = width - self.height = height - self.screen = screen - self.difficulty = difficulty - self.cells = [] - self.selected_cell = None - self.generate_board() - def generate_board(self): - board_values = [[0 for _ in range(9)] for _ in range(9)] - for row in range(9): - cell_row = [] - for col in range(9): - cell_row.append(Cell(board_values[row][col], row, col, self.screen)) - self.cells.append(cell_row) - def draw(self): - for row in range(10): - thickness = 2 if row % 3 == 0 else 1 - pygame.draw.line(self.screen, (0, 0, 0), (0, row * 60), (540, row * 60), thickness) - pygame.draw.line(self.screen, (0, 0, 0), (row * 60, 0), (row * 60, 540), thickness) - for row in self.cells: - for cell in row: - cell.draw() - def select(self, row, col): - if self.selected_cell: - self.selected_cell.selected = False - self.selected_cell = self.cells[row][col] - self.selected_cell.selected = True - def click(self, x, y): - if x < self.width and y < self.height: - row, col = y // 60, x // 60 - self.select(row, col) - return row, col - return None - def clear(self): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_sketched_value(0) - def sketch(self, value): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_sketched_value(value) - def place_number(self, value): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_cell_value(value) - self.selected_cell.set_sketched_value(0) - def reset_to_original(self): - for row in self.cells: - for cell in row: - if cell.value == 0: - cell.set_cell_value(0) - cell.set_sketched_value(0) - def is_full(self): - for row in self.cells: - for cell in row: - if cell.value == 0: - return False - return True - def update_board(self): - board = [[cell.value for cell in row] for row in self.cells] - return board - def find_empty(self): - for row in range(9): - for col in range(9): - if self.cells[row][col].value == 0: - return row, col - return None - def check_board(self): +import pygame +from cell import Cell +from constants import* + +class Board: + def __init__(self, width, height, screen, difficulty): + self.width = width + self.height = height + self.screen = screen + self.difficulty = difficulty + self.cells = [[Cell(0, i, j, screen) for j in range(9)] for i in range(9)] + self.current = None + + def draw(self): + for row in range(10): + thickness = 2 if row % 3 == 0 else 1 + pygame.draw.line(self.screen, (0, 0, 0), (0, row * 60), (540, row * 60), thickness) + pygame.draw.line(self.screen, (0, 0, 0), (row * 60, 0), (row * 60, 540), thickness) + for row in self.cells: + for cell in row: + cell.draw() # Draw each cell, and highlight the selected one + + def select(self, row, col): + # Deselect any previously selected cell before selecting a new one + if self.current: + self.current.selected = False # Unselect the previously selected cell + + self.cells[row][col].selected = True # Select the new cell + self.current = self.cells[row][col] # Update the current selected cell + + def click(self, x, y): + """ + Converts mouse click position (x, y) into a row and column, and selects the corresponding cell. + """ + if x < self.width and y < self.height: + # Calculate row and column based on click position + row = y // 60 # Calculate the row (divide y by the cell height) + col = x // 60 # Calculate the column (divide x by the cell width) + + # Select the clicked cell + self.select(row, col) + return row, col + return None + + def clear(self): + if self.selected_cell and self.selected_cell.value == 0: + self.selected_cell.set_sketched_value(0) + + def sketch(self, value): + if self.selected_cell and self.selected_cell.value == 0: + self.selected_cell.set_sketched_value(value) + + def place_number(self, value): + if self.selected_cell and self.selected_cell.value == 0: + self.selected_cell.set_cell_value(value) + self.selected_cell.set_sketched_value(0) + + def reset_to_original(self): + for row in self.cells: + for cell in row: + if cell.value == 0: + cell.set_cell_value(0) + cell.set_sketched_value(0) + + def is_full(self): + for row in self.cells: + for cell in row: + if cell.value == 0: + return False + return True + + def update_board(self): + board = [[cell.value for cell in row] for row in self.cells] + return board + + def find_empty(self): + for row in range(9): + for col in range(9): + if self.cells[row][col].value == 0: + return row, col + return None + + def check_board(self): pass \ No newline at end of file diff --git a/cell.py b/cell.py index cda8da58..f87a09b5 100644 --- a/cell.py +++ b/cell.py @@ -1,14 +1,15 @@ import pygame +from constants import TEXT class Cell: - def __init__(self, value, row, col, screen, size=60): + def __init__(self, value, row, col, screen): self.value = value - self.sketched_value = 0 self.row = row self.col = col self.screen = screen - self.size = size self.selected = False + self.sketched_val = None + self.editable = True def set_cell_value(self, value): self.value = value @@ -17,17 +18,24 @@ def set_sketched_value(self, value): self.sketched_value = value def draw(self): - x = self.col * self.size - y = self.row * self.size + font_num = pygame.font.Font(None, 80) - color = (255, 0, 0) if self.selected else (0, 0, 0) - pygame.draw.rect(self.screen, color, (x, y, self.size, self.size), 2) + # Only display number if the cell value is not 0 + if self.value != 0: + num_surface = font_num.render(str(self.value), True, TEXT) + num_rectangle = num_surface.get_rect( + center=(60 * self.col + 30, 60 * self.row + 30)) + self.screen.blit(num_surface, num_rectangle) - font = pygame.font.Font(None, 40) + # Highlight the cell if it's selected + if self.selected: + red_square = pygame.Rect(self.col * 60, self.row * 60, 60, 60) + pygame.draw.rect(self.screen, (255, 0, 0), red_square, 3) # Red outline with 3 px thickness - if self.value != 0: - text = font.render(str(self.value), True, (0, 0, 0)) - self.screen.blit(text, (x + self.size // 3, y + self.size // 4)) - elif self.sketched_value != 0: - text = font.render(str(self.sketched_value), True, (128, 128, 128)) - self.screen.blit(text, (x + 5, y + 5)) + # If the cell has a sketch value, display it + if self.sketched_val is not None: + font_sketch = pygame.font.Font(None, 40) + sketch_surface = font_sketch.render(str(self.sketched_val), True, TEXT) + sketch_rectangle = sketch_surface.get_rect( + center=(60 * self.col + 30, 60 * self.row + 30)) + self.screen.blit(sketch_surface, sketch_rectangle) \ No newline at end of file diff --git a/constants.py b/constants.py index c49cb6b4..cc3adf6a 100644 --- a/constants.py +++ b/constants.py @@ -14,3 +14,4 @@ EASY = 30 MEDIUM = 40 HARD = 50 +LINE_COLOR = (245, 152, 66) diff --git a/sudoku.py b/sudoku.py index 68abf9a2..682fcc9c 100644 --- a/sudoku.py +++ b/sudoku.py @@ -1,199 +1,189 @@ -from idlelib.pyshell import restart_line -from sys import displayhook +import pygame +import sys +from board import Board # Ensure Board is imported properly +from constants import * # Make sure constants like WIDTH, HEIGHT, BG_COLOR_1 are defined +from sudoku_generator import SudokuGenerator -import pygame, sys -from pygame.display import update - -from board import Board -from constants import * -from sudoku_generator import * def game_start(screen): - #Title/Button font init + # Initialize title, subtitle, and button fonts start_title_font = pygame.font.Font(None, 120) subtitle_font = pygame.font.Font(None, 90) button_font = pygame.font.Font(None, 70) - - #Background coloring - screen.fill(BG_COLOR_1) - #Creating title text - main_title_surface = start_title_font.render("Welcome to Sudoku", 0, TITLE_TEXT) - main_title_rectangle = main_title_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 - 300)) - #Create outline - main_title_outline = start_title_font.render("Welcome to Sudoku", 0, TEXT) - for i in range (-3, 4): - for j in range(-3, 4): - screen.blit(main_title_outline, main_title_surface.get_rect(center = (WIDTH //2 + i, HEIGHT // 2 - 300 + j))) + # Color background and display title + screen.fill(BG_COLOR_1) + main_title_surface = start_title_font.render("Welcome to Sudoku", True, TITLE_TEXT) + main_title_rectangle = main_title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 300)) screen.blit(main_title_surface, main_title_rectangle) - #Creating Subtitle - subtitle_surface = subtitle_font.render("Select Game Mode:", 0, TITLE_TEXT) - subtitle_rectangle = subtitle_surface.get_rect(center = (WIDTH // 2 , HEIGHT // 2 - 50)) - subtitle_outline = subtitle_font.render("Select Game Mode:", 0, TEXT) - for i in range(-3, 4): - for j in range(-3, 4): - screen.blit(subtitle_outline, subtitle_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 50 + j))) + + subtitle_surface = subtitle_font.render("Select Game Mode:", True, TITLE_TEXT) + subtitle_rectangle = subtitle_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) screen.blit(subtitle_surface, subtitle_rectangle) - #Init Buttons - easy_text = button_font.render("Easy", 0, TEXT) - medium_text = button_font.render("Medium", 0, TEXT) - hard_text = button_font.render("Hard", 0, TEXT) - - #Init Easy/Medium/Hard Button Text Box Background - easy_surface = pygame.Surface((easy_text.get_size()[0] + 20, easy_text.get_size()[1] + 20)) - easy_surface.fill(BUTTON_COLOR) - easy_surface.blit(easy_text, (10, 10)) - medium_surface = pygame.Surface((medium_text.get_size()[0] + 20, medium_text.get_size()[1] + 20)) - medium_surface.fill(BUTTON_COLOR) - medium_surface.blit(medium_text, (10, 10)) - hard_surface = pygame.Surface((hard_text.get_size()[0] + 20, hard_text.get_size()[1] + 20)) - hard_surface.fill(BUTTON_COLOR) - hard_surface.blit(hard_text, (10, 10)) - - - #Init Button Rectangle - easy_rectangle = easy_surface.get_rect(center = (WIDTH // 2 + 200 , HEIGHT // 2 + 150)) - medium_rectangle = medium_surface.get_rect(center = (WIDTH // 2 , HEIGHT // 2 + 150)) - hard_rectangle = hard_surface.get_rect(center = (WIDTH // 2 - 200, HEIGHT // 2 + 150)) - - #Init Button Outlines - easy_ot_surface = pygame.Surface((easy_text.get_size()[0] + 30, easy_text.get_size()[1] + 30)) - easy_ot_surface.fill(TEXT) - medium_ot_surface = pygame.Surface((medium_text.get_size()[0] + 30, medium_text.get_size()[1] + 30)) - medium_ot_surface.fill(TEXT) - hard_ot_surface = pygame.Surface((hard_text.get_size()[0] + 30, hard_text.get_size()[1] + 30)) - hard_ot_surface.fill(TEXT) - - easy_ot_rectangle = easy_ot_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT // 2 + 150)) - medium_ot_rectangle = medium_ot_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) - hard_ot_rectangle = hard_ot_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT // 2 + 150)) - - - #Draw Buttons - screen.blit(easy_ot_surface, easy_ot_rectangle) - screen.blit(medium_ot_surface, medium_ot_rectangle) - screen.blit(hard_ot_surface, hard_ot_rectangle) - screen.blit(easy_surface, easy_rectangle) - screen.blit(medium_surface, medium_rectangle) - screen.blit(hard_surface, hard_rectangle) + # Define buttons + button_data = [("Easy", WIDTH // 2 + 200), ("Medium", WIDTH // 2), ("Hard", WIDTH // 2 - 200)] + buttons = [] + for text, x_pos in button_data: + button_text = button_font.render(text, True, TEXT) + button_surface = pygame.Surface((button_text.get_width() + 20, button_text.get_height() + 20)) + button_surface.fill(BUTTON_COLOR) + button_surface.blit(button_text, (10, 10)) + button_rectangle = button_surface.get_rect(center=(x_pos, HEIGHT // 2 + 150)) + buttons.append((button_surface, button_rectangle, text.lower())) + screen.blit(button_surface, button_rectangle) + + # Wait for user to select difficulty while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: - if easy_rectangle.collidepoint(event.pos): - return EASY - elif medium_rectangle.collidepoint(event.pos): - return MEDIUM - elif hard_rectangle.collidepoint(event.pos): - return HARD + for _, button_rect, difficulty in buttons: + if button_rect.collidepoint(event.pos): + return difficulty pygame.display.update() -def during_game(screen, difficulty): - #Init Fonts + +def during_game(screen, display_board, difficulty): + # Init Fonts bottom_button_font = pygame.font.Font(None, 50) small_msg_font = pygame.font.Font(None, 30) - # BG color - screen.fill(BG_COLOR_2) - - #Init small message that displays the difficulty + # Init small message that displays the difficulty small_msg_surface = small_msg_font.render(difficulty, 0, TEXT) small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2, HEIGHT - 50)) screen.blit(small_msg_surface, small_msg_rectangle) - - #Text displays for the RESET/RESTART/EXIT buttons + # Text displays for the RESET/RESTART/EXIT buttons reset_text = bottom_button_font.render("RESET", 0, TEXT) restart_text = bottom_button_font.render("RESTART", 0, TEXT) exit_text = bottom_button_font.render("EXIT", 0, TEXT) - # reset_surface = pygame.Surface((reset_text.get_size()[0] + 20, reset_text.get_size()[1] + 20)) reset_surface.fill(BUTTON_COLOR) reset_surface.blit(reset_text, (10, 10)) + restart_surface = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) restart_surface.fill(BUTTON_COLOR) restart_surface.blit(restart_text, (10, 10)) + exit_surface = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) exit_surface.fill(BUTTON_COLOR) exit_surface.blit(exit_text, (10, 10)) - # reset_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 150)) restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 150)) exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 150)) - # - screen.blit(reset_surface, reset_rectangle) - screen.blit(restart_surface, restart_rectangle) - screen.blit(exit_surface, exit_rectangle) + # Track the selected square (initialize clicked_row and clicked_col) + clicked_row, clicked_col = -1, -1 # Start with an invalid selection while True: + screen.fill(BG_COLOR_1) # Clear the screen on each loop iteration + + # Draw the board and highlight the selected square + display_board.draw() + if clicked_row != -1 and clicked_col != -1: + display_board.select(clicked_row, clicked_col) + + # Draw the reset/restart/exit buttons on top of the board + screen.blit(reset_surface, reset_rectangle) + screen.blit(restart_surface, restart_rectangle) + screen.blit(exit_surface, exit_rectangle) + + # Event handling for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() + if event.type == pygame.MOUSEBUTTONDOWN: + # Handle button clicks (reset, restart, exit) if reset_rectangle.collidepoint(event.pos): - return + main() # Restart the game (to reset) elif restart_rectangle.collidepoint(event.pos): - return + main() # Restart the game elif exit_rectangle.collidepoint(event.pos): sys.exit() - pygame.display.update() - -def win_screen(screen): - # Title/Button font init - title_font = pygame.font.Font(None, 150) - button_font = pygame.font.Font(None, 100) - - # Background coloring - screen.fill(WIN_BG) - - # Creating title text - title_surface = title_font.render("YOU WON!!!", 0, TEXT) - title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 250)) - screen.blit(title_surface, title_rectangle) - - # Init Exit Button - exit_text = button_font.render("EXIT", 0, TEXT) - - # Init Exit Button Text Box Background - exit_surface = pygame.Surface((exit_text.get_size()[0] + 40, exit_text.get_size()[1] + 40)) - exit_surface.fill(BG_COLOR_2) - exit_surface.blit(exit_text, (20, 20)) - # Init Button Rectangle - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) + # Handle board clicks (select the cell) + if event.pos[1] <= 630: # If user clicks inside the board area + clicked_row, clicked_col = display_board.click(event.pos[1], event.pos[0]) - # Init Restart Button - restart_text = button_font.render("RESTART", 0, TEXT) - - # Init Restart Button Text Box Background - restart_surface = pygame.Surface((restart_text.get_size()[0] + 40, restart_text.get_size()[1] + 40)) - restart_surface.fill(BG_COLOR_2) - restart_surface.blit(restart_text, (20, 20)) - - # Init Button Rectangle - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) - - #Init Restart Button Outline - restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 50, restart_text.get_size()[1] + 50)) - restart_ot_surface.fill(TEXT) - restart_ot_rectangle = restart_ot_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) - - #Init Exit Button Outline - exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 50, exit_text.get_size()[1] + 50)) - exit_ot_surface.fill(TEXT) - exit_ot_rectangle = exit_ot_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) + # Keyboard input (handling number placement) + if event.type == pygame.KEYDOWN: + input_val = None + if event.key == pygame.K_RETURN: # enter key + input_val = 0 + elif event.key == pygame.K_1: # "1" + input_val = 1 + elif event.key == pygame.K_2: # "2" + input_val = 2 + elif event.key == pygame.K_3: # "3" + input_val = 3 + elif event.key == pygame.K_4: # "4" + input_val = 4 + elif event.key == pygame.K_5: # "5" + input_val = 5 + elif event.key == pygame.K_6: # "6" + input_val = 6 + elif event.key == pygame.K_7: # "7" + input_val = 7 + elif event.key == pygame.K_8: # "8" + input_val = 8 + elif event.key == pygame.K_9: # "9" + input_val = 9 + # Move selected red square with arrow keys + elif event.key == pygame.K_UP: # Up arrow + if clicked_row - 1 >= 0: + clicked_row -= 1 + elif event.key == pygame.K_DOWN: # Down arrow + if clicked_row + 1 <= 8: + clicked_row += 1 + elif event.key == pygame.K_LEFT: # Left arrow + if clicked_col - 1 >= 0: + clicked_col -= 1 + elif event.key == pygame.K_RIGHT: # Right arrow + if clicked_col + 1 <= 8: + clicked_col += 1 + + try: + # Sketch input val onto screen + if 1 <= input_val <= 9: + display_board.sketch(input_val) + + # Turn sketch value into actual val (place number) + elif input_val == 0: + if display_board.current.editable and display_board.current.value: + display_board.current.value = 0 + else: + display_board.place_number() + + except: + pass # If a user enters a number not 1-9 it will do nothing + + pygame.display.update() # Update the display each frame + +def draw_game_win(screen): + win_font = pygame.font.Font(None, 120) + button_font = pygame.font.Font(None, 50) + + # Set background and text + screen.fill(BG_COLOR_1) + win_surface = win_font.render("Game Won!", True, WIN_BG) + win_rectangle = win_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) + screen.blit(win_surface, win_rectangle) + + # Display exit button + exit_text = button_font.render("EXIT", True, (255, 255, 255)) + exit_surface = pygame.Surface((exit_text.get_width() + 20, exit_text.get_height() + 20)) + exit_surface.fill(LINE_COLOR) + exit_surface.blit(exit_text, (10, 10)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) - # Draw Buttons - screen.blit(restart_ot_surface, restart_ot_rectangle) - screen.blit(exit_ot_surface, exit_ot_rectangle) - screen.blit(restart_surface, restart_rectangle) screen.blit(exit_surface, exit_rectangle) + # Handle button clicks for exit while True: for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -201,100 +191,68 @@ def win_screen(screen): if event.type == pygame.MOUSEBUTTONDOWN: if exit_rectangle.collidepoint(event.pos): sys.exit() - elif restart_rectangle.collidepoint(event.pos): - return pygame.display.update() -def lose_screen(screen): - # Title/Button font init - title_font = pygame.font.Font(None, 150) - button_font = pygame.font.Font(None, 100) - - # Background coloring - screen.fill(LOSE_BG) - - # Creating title text - title_surface = title_font.render("YOU LOST :<(", 0, TEXT) - title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 250)) - screen.blit(title_surface, title_rectangle) - - # Init Restart Button - restart_text = button_font.render("RESTART", 0, TEXT) - # Init Restart Button Text Box Background - restart_surface = pygame.Surface((restart_text.get_size()[0] + 40, restart_text.get_size()[1] + 40)) - restart_surface.fill(BG_COLOR_1) - restart_surface.blit(restart_text, (20, 20)) +def draw_game_lose(screen): + lose_font = pygame.font.Font(None, 120) + button_font = pygame.font.Font(None, 50) - # Init Button Rectangle - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2 + 150, HEIGHT // 2)) - - # Init Exit Button - exit_text = button_font.render("EXIT", 0, TEXT) - - # Init Exit Button Text Box Background - exit_surface = pygame.Surface((exit_text.get_size()[0] + 40, exit_text.get_size()[1] + 40)) - exit_surface.fill(BG_COLOR_1) - exit_surface.blit(exit_text, (20, 20)) - - # Init Button Rectangle - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 150, HEIGHT // 2)) + # Set background and text + screen.fill(BG_COLOR_1) + lose_surface = lose_font.render("Game Over :(", True, LOSE_BG) + lose_rectangle = lose_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) + screen.blit(lose_surface, lose_rectangle) + + # Display restart button + restart_text = button_font.render("RESTART", True, (255, 255, 255)) + restart_surface = pygame.Surface((restart_text.get_width() + 20, restart_text.get_height() + 20)) + restart_surface.fill(LINE_COLOR) + restart_surface.blit(restart_text, (10, 10)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) - # Draw Buttons screen.blit(restart_surface, restart_rectangle) - screen.blit(exit_surface, exit_rectangle) + + # Handle button clicks for restart while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: if restart_rectangle.collidepoint(event.pos): - return + main() pygame.display.update() - -def main (): - game_over = False - dif = "" - +def main(): pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) - pygame.display.set_caption("Prog 1 Sudoku") - while True: - difficulty = game_start(screen) - board = Board(WIDTH, HEIGHT, screen, difficulty) - board.draw - for event in pygame.event.get(): - if event.type == pygame.QUIT: - pygame.quit() - sys.exit() - if event.type == pygame.MOUSEBUTTONDOWN: - pos = pygame.mouse.get_pos() - clicked_cell = board.click(pos[0], pos[1]) + pygame.display.set_caption("Sudoku") + # Get the difficulty from the game start screen + difficulty = game_start(screen) - if event.type == pygame.KEYDOWN: - if event.key == pygame.K_r: # Reset game - board.reset_to_original() - - if pygame.K_1 <= event.key <= pygame.K_9: - board.place_number(event.key - pygame.K_0) + # Board generation based on difficulty + removed_cells = {"easy": 30, "medium": 40, "hard": 50} + sudoku = SudokuGenerator(9, removed_cells[difficulty]) + sudoku.fill_values() + sudoku.remove_cells() + board_state = sudoku.get_board() - if difficulty == 30: - dif = "EASY" - elif difficulty == 40: - dif = "MEDIUM" - elif difficulty == 50: - dif = "HARD" - screen.fill(BG_COLOR_1) - during_game(screen, dif) - lose_screen(screen) - win_screen(screen) + # Fill the screen with background color to clear the starting screen + screen.fill(BG_COLOR_1) - #board.print_board() - #For debugging ^ + # Initialize board display (this is where we create the display_board) + display_board = Board(630, 630, screen, removed_cells[difficulty]) # Ensure Board is initialized here + for i in range(9): + for j in range(9): + display_board.cells[i][j].value = board_state[i][j] + if board_state[i][j] != 0: + display_board.cells[i][j].editable = False + # Start the game + display_board.draw() # Draw the board initially + during_game(screen, display_board, difficulty) # Pass display_board to during_game if __name__ == "__main__": - main() + main() \ No newline at end of file From 38cd4e83a9c120e6d02761be8af3988169dea2c4 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Tue, 3 Dec 2024 23:12:16 -0500 Subject: [PATCH 23/30] Added user inputs, fixed highlights and buttons --- board.py | 51 +++++++++++++------------- sudoku.py | 105 ++++++++++++++++++++---------------------------------- 2 files changed, 62 insertions(+), 94 deletions(-) diff --git a/board.py b/board.py index 3703cc35..05a5bbcd 100644 --- a/board.py +++ b/board.py @@ -1,6 +1,6 @@ import pygame from cell import Cell -from constants import* +from constants import * class Board: def __init__(self, width, height, screen, difficulty): @@ -10,6 +10,7 @@ def __init__(self, width, height, screen, difficulty): self.difficulty = difficulty self.cells = [[Cell(0, i, j, screen) for j in range(9)] for i in range(9)] self.current = None + self.original_values = [[cell.value for cell in row] for row in self.cells] def draw(self): for row in range(10): @@ -18,49 +19,45 @@ def draw(self): pygame.draw.line(self.screen, (0, 0, 0), (row * 60, 0), (row * 60, 540), thickness) for row in self.cells: for cell in row: - cell.draw() # Draw each cell, and highlight the selected one + cell.draw() def select(self, row, col): - # Deselect any previously selected cell before selecting a new one if self.current: - self.current.selected = False # Unselect the previously selected cell + self.current.selected = False - self.cells[row][col].selected = True # Select the new cell - self.current = self.cells[row][col] # Update the current selected cell + if self.cells[row][col].editable: + self.cells[row][col].selected = True + self.current = self.cells[row][col] + else: + self.current = None def click(self, x, y): - """ - Converts mouse click position (x, y) into a row and column, and selects the corresponding cell. - """ if x < self.width and y < self.height: - # Calculate row and column based on click position - row = y // 60 # Calculate the row (divide y by the cell height) - col = x // 60 # Calculate the column (divide x by the cell width) - - # Select the clicked cell + row = y // 60 + col = x // 60 self.select(row, col) return row, col return None def clear(self): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_sketched_value(0) + if self.current and self.current.value == 0: + self.current.set_sketched_value(0) def sketch(self, value): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_sketched_value(value) + if self.current and self.current.value == 0: + self.current.set_sketched_value(value) def place_number(self, value): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_cell_value(value) - self.selected_cell.set_sketched_value(0) + if self.current and self.current.value == 0: + self.current.set_cell_value(value) + self.current.set_sketched_value(0) def reset_to_original(self): - for row in self.cells: - for cell in row: - if cell.value == 0: - cell.set_cell_value(0) - cell.set_sketched_value(0) + for i in range(9): + for j in range(9): + if self.cells[i][j].editable: + self.cells[i][j].set_cell_value(self.original_values[i][j]) + self.cells[i][j].set_sketched_value(0) def is_full(self): for row in self.cells: @@ -81,4 +78,4 @@ def find_empty(self): return None def check_board(self): - pass \ No newline at end of file + pass diff --git a/sudoku.py b/sudoku.py index 682fcc9c..29aecfad 100644 --- a/sudoku.py +++ b/sudoku.py @@ -1,7 +1,7 @@ import pygame import sys -from board import Board # Ensure Board is imported properly -from constants import * # Make sure constants like WIDTH, HEIGHT, BG_COLOR_1 are defined +from board import Board +from constants import * from sudoku_generator import SudokuGenerator @@ -52,7 +52,7 @@ def during_game(screen, display_board, difficulty): # Init small message that displays the difficulty small_msg_surface = small_msg_font.render(difficulty, 0, TEXT) - small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2, HEIGHT - 50)) + small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) screen.blit(small_msg_surface, small_msg_rectangle) # Text displays for the RESET/RESTART/EXIT buttons @@ -76,18 +76,13 @@ def during_game(screen, display_board, difficulty): restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 150)) exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 150)) - # Track the selected square (initialize clicked_row and clicked_col) - clicked_row, clicked_col = -1, -1 # Start with an invalid selection + clicked_row, clicked_col = -1, -1 while True: - screen.fill(BG_COLOR_1) # Clear the screen on each loop iteration - - # Draw the board and highlight the selected square + screen.fill(BG_COLOR_1) display_board.draw() if clicked_row != -1 and clicked_col != -1: display_board.select(clicked_row, clicked_col) - - # Draw the reset/restart/exit buttons on top of the board screen.blit(reset_surface, reset_rectangle) screen.blit(restart_surface, restart_rectangle) screen.blit(exit_surface, exit_rectangle) @@ -98,71 +93,47 @@ def during_game(screen, display_board, difficulty): sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: - # Handle button clicks (reset, restart, exit) if reset_rectangle.collidepoint(event.pos): - main() # Restart the game (to reset) + display_board.reset_to_original() + display_board.draw() elif restart_rectangle.collidepoint(event.pos): - main() # Restart the game + main() elif exit_rectangle.collidepoint(event.pos): sys.exit() # Handle board clicks (select the cell) - if event.pos[1] <= 630: # If user clicks inside the board area - clicked_row, clicked_col = display_board.click(event.pos[1], event.pos[0]) + if 0 <= event.pos[0] < 540 and 0 <= event.pos[1] < 540: + row, col = display_board.click(event.pos[0], event.pos[1]) + if display_board.cells[row][col].editable: + clicked_row, clicked_col = row, col + else: + clicked_row, clicked_col = -1, -1 - # Keyboard input (handling number placement) if event.type == pygame.KEYDOWN: - input_val = None - if event.key == pygame.K_RETURN: # enter key - input_val = 0 - elif event.key == pygame.K_1: # "1" - input_val = 1 - elif event.key == pygame.K_2: # "2" - input_val = 2 - elif event.key == pygame.K_3: # "3" - input_val = 3 - elif event.key == pygame.K_4: # "4" - input_val = 4 - elif event.key == pygame.K_5: # "5" - input_val = 5 - elif event.key == pygame.K_6: # "6" - input_val = 6 - elif event.key == pygame.K_7: # "7" - input_val = 7 - elif event.key == pygame.K_8: # "8" - input_val = 8 - elif event.key == pygame.K_9: # "9" - input_val = 9 - # Move selected red square with arrow keys - elif event.key == pygame.K_UP: # Up arrow - if clicked_row - 1 >= 0: - clicked_row -= 1 - elif event.key == pygame.K_DOWN: # Down arrow - if clicked_row + 1 <= 8: - clicked_row += 1 - elif event.key == pygame.K_LEFT: # Left arrow - if clicked_col - 1 >= 0: - clicked_col -= 1 - elif event.key == pygame.K_RIGHT: # Right arrow - if clicked_col + 1 <= 8: - clicked_col += 1 - - try: - # Sketch input val onto screen - if 1 <= input_val <= 9: - display_board.sketch(input_val) - - # Turn sketch value into actual val (place number) - elif input_val == 0: - if display_board.current.editable and display_board.current.value: - display_board.current.value = 0 - else: - display_board.place_number() - - except: - pass # If a user enters a number not 1-9 it will do nothing - - pygame.display.update() # Update the display each frame + if clicked_row != -1 and clicked_col != -1: + if event.key in (pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4, pygame.K_5, + pygame.K_6, pygame.K_7, pygame.K_8, pygame.K_9): + value = int(event.unicode) + if display_board.cells[clicked_row][clicked_col].editable: + display_board.cells[clicked_row][clicked_col].value = value + elif event.key == pygame.K_UP: + clicked_row = (clicked_row - 1) % 9 + elif event.key == pygame.K_DOWN: + clicked_row = (clicked_row + 1) % 9 + elif event.key == pygame.K_LEFT: + clicked_col = (clicked_col - 1) % 9 + elif event.key == pygame.K_RIGHT: + clicked_col = (clicked_col + 1) % 9 + + # Skip non-editable cells when navigating + while not display_board.cells[clicked_row][clicked_col].editable: + # Logic to prevent getting stuck on non-editable cells + if event.key in (pygame.K_UP, pygame.K_DOWN): + clicked_row = (clicked_row - 1) % 9 if event.key == pygame.K_UP else (clicked_row + 1) % 9 + if event.key in (pygame.K_LEFT, pygame.K_RIGHT): + clicked_col = (clicked_col - 1) % 9 if event.key == pygame.K_LEFT else (clicked_col + 1) % 9 + + pygame.display.update() def draw_game_win(screen): win_font = pygame.font.Font(None, 120) From cca3fc56c46fb7e1d2772438bde28c4890db2152 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Thu, 5 Dec 2024 00:17:07 -0500 Subject: [PATCH 24/30] Cleanup + Add checker and win and lose screen --- board.py | 18 ++++++++++++++++-- cell.py | 6 ------ sudoku.py | 44 ++++++++++++-------------------------------- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/board.py b/board.py index 05a5bbcd..444a16cb 100644 --- a/board.py +++ b/board.py @@ -1,6 +1,5 @@ import pygame from cell import Cell -from constants import * class Board: def __init__(self, width, height, screen, difficulty): @@ -78,4 +77,19 @@ def find_empty(self): return None def check_board(self): - pass + for row in self.cells: + if not self._is_valid_group([cell.value for cell in row]): + return False + for col in range(9): + if not self._is_valid_group([self.cells[row][col].value for row in range(9)]): + return False + for i in range(0, 9, 3): + for j in range(0, 9, 3): + subgrid = [self.cells[x][y].value for x in range(i, i + 3) for y in range(j, j + 3)] + if not self._is_valid_group(subgrid): + return False + return True + + def _is_valid_group(self, values): + nums = [v for v in values if v != 0] + return len(nums) == len(set(nums)) diff --git a/cell.py b/cell.py index f87a09b5..a295e312 100644 --- a/cell.py +++ b/cell.py @@ -19,20 +19,14 @@ def set_sketched_value(self, value): def draw(self): font_num = pygame.font.Font(None, 80) - - # Only display number if the cell value is not 0 if self.value != 0: num_surface = font_num.render(str(self.value), True, TEXT) num_rectangle = num_surface.get_rect( center=(60 * self.col + 30, 60 * self.row + 30)) self.screen.blit(num_surface, num_rectangle) - - # Highlight the cell if it's selected if self.selected: red_square = pygame.Rect(self.col * 60, self.row * 60, 60, 60) pygame.draw.rect(self.screen, (255, 0, 0), red_square, 3) # Red outline with 3 px thickness - - # If the cell has a sketch value, display it if self.sketched_val is not None: font_sketch = pygame.font.Font(None, 40) sketch_surface = font_sketch.render(str(self.sketched_val), True, TEXT) diff --git a/sudoku.py b/sudoku.py index 29aecfad..20bd77c4 100644 --- a/sudoku.py +++ b/sudoku.py @@ -6,12 +6,11 @@ def game_start(screen): - # Initialize title, subtitle, and button fonts + start_title_font = pygame.font.Font(None, 120) subtitle_font = pygame.font.Font(None, 90) button_font = pygame.font.Font(None, 70) - # Color background and display title screen.fill(BG_COLOR_1) main_title_surface = start_title_font.render("Welcome to Sudoku", True, TITLE_TEXT) main_title_rectangle = main_title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 300)) @@ -21,7 +20,6 @@ def game_start(screen): subtitle_rectangle = subtitle_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) screen.blit(subtitle_surface, subtitle_rectangle) - # Define buttons button_data = [("Easy", WIDTH // 2 + 200), ("Medium", WIDTH // 2), ("Hard", WIDTH // 2 - 200)] buttons = [] for text, x_pos in button_data: @@ -33,7 +31,6 @@ def game_start(screen): buttons.append((button_surface, button_rectangle, text.lower())) screen.blit(button_surface, button_rectangle) - # Wait for user to select difficulty while True: for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -44,18 +41,15 @@ def game_start(screen): return difficulty pygame.display.update() - def during_game(screen, display_board, difficulty): - # Init Fonts + bottom_button_font = pygame.font.Font(None, 50) small_msg_font = pygame.font.Font(None, 30) - # Init small message that displays the difficulty small_msg_surface = small_msg_font.render(difficulty, 0, TEXT) small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) screen.blit(small_msg_surface, small_msg_rectangle) - # Text displays for the RESET/RESTART/EXIT buttons reset_text = bottom_button_font.render("RESET", 0, TEXT) restart_text = bottom_button_font.render("RESTART", 0, TEXT) exit_text = bottom_button_font.render("EXIT", 0, TEXT) @@ -81,13 +75,13 @@ def during_game(screen, display_board, difficulty): while True: screen.fill(BG_COLOR_1) display_board.draw() + if clicked_row != -1 and clicked_col != -1: display_board.select(clicked_row, clicked_col) screen.blit(reset_surface, reset_rectangle) screen.blit(restart_surface, restart_rectangle) screen.blit(exit_surface, exit_rectangle) - # Event handling for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() @@ -101,7 +95,6 @@ def during_game(screen, display_board, difficulty): elif exit_rectangle.collidepoint(event.pos): sys.exit() - # Handle board clicks (select the cell) if 0 <= event.pos[0] < 540 and 0 <= event.pos[1] < 540: row, col = display_board.click(event.pos[0], event.pos[1]) if display_board.cells[row][col].editable: @@ -124,28 +117,27 @@ def during_game(screen, display_board, difficulty): clicked_col = (clicked_col - 1) % 9 elif event.key == pygame.K_RIGHT: clicked_col = (clicked_col + 1) % 9 - - # Skip non-editable cells when navigating while not display_board.cells[clicked_row][clicked_col].editable: - # Logic to prevent getting stuck on non-editable cells if event.key in (pygame.K_UP, pygame.K_DOWN): clicked_row = (clicked_row - 1) % 9 if event.key == pygame.K_UP else (clicked_row + 1) % 9 if event.key in (pygame.K_LEFT, pygame.K_RIGHT): clicked_col = (clicked_col - 1) % 9 if event.key == pygame.K_LEFT else (clicked_col + 1) % 9 - + if display_board.is_full(): + if display_board.check_board(): + draw_game_win(screen) + else: + draw_game_lose(screen) pygame.display.update() def draw_game_win(screen): win_font = pygame.font.Font(None, 120) button_font = pygame.font.Font(None, 50) - # Set background and text screen.fill(BG_COLOR_1) win_surface = win_font.render("Game Won!", True, WIN_BG) win_rectangle = win_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) screen.blit(win_surface, win_rectangle) - # Display exit button exit_text = button_font.render("EXIT", True, (255, 255, 255)) exit_surface = pygame.Surface((exit_text.get_width() + 20, exit_text.get_height() + 20)) exit_surface.fill(LINE_COLOR) @@ -154,7 +146,6 @@ def draw_game_win(screen): screen.blit(exit_surface, exit_rectangle) - # Handle button clicks for exit while True: for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -168,23 +159,19 @@ def draw_game_win(screen): def draw_game_lose(screen): lose_font = pygame.font.Font(None, 120) button_font = pygame.font.Font(None, 50) - - # Set background and text screen.fill(BG_COLOR_1) + lose_surface = lose_font.render("Game Over :(", True, LOSE_BG) lose_rectangle = lose_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) screen.blit(lose_surface, lose_rectangle) - # Display restart button restart_text = button_font.render("RESTART", True, (255, 255, 255)) restart_surface = pygame.Surface((restart_text.get_width() + 20, restart_text.get_height() + 20)) restart_surface.fill(LINE_COLOR) restart_surface.blit(restart_text, (10, 10)) restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) - screen.blit(restart_surface, restart_rectangle) - # Handle button clicks for restart while True: for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -199,31 +186,24 @@ def main(): pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Sudoku") - - # Get the difficulty from the game start screen difficulty = game_start(screen) - # Board generation based on difficulty removed_cells = {"easy": 30, "medium": 40, "hard": 50} sudoku = SudokuGenerator(9, removed_cells[difficulty]) sudoku.fill_values() sudoku.remove_cells() board_state = sudoku.get_board() - - # Fill the screen with background color to clear the starting screen screen.fill(BG_COLOR_1) - # Initialize board display (this is where we create the display_board) - display_board = Board(630, 630, screen, removed_cells[difficulty]) # Ensure Board is initialized here + display_board = Board(630, 630, screen, removed_cells[difficulty]) for i in range(9): for j in range(9): display_board.cells[i][j].value = board_state[i][j] if board_state[i][j] != 0: display_board.cells[i][j].editable = False - # Start the game - display_board.draw() # Draw the board initially - during_game(screen, display_board, difficulty) # Pass display_board to during_game + display_board.draw() + during_game(screen, display_board, difficulty) if __name__ == "__main__": main() \ No newline at end of file From c7d331022b961ad88a5744a636cacdeeab6ffe26 Mon Sep 17 00:00:00 2001 From: Derek Camilo Date: Fri, 6 Dec 2024 02:45:02 -0500 Subject: [PATCH 25/30] Finished up the final touches on the UI and other game based visual issues. --- board.py | 79 ++++--- cell.py | 34 +-- constants.py | 16 +- sudoku.py | 525 +++++++++++++++++++++++++------------------- sudoku_generator.py | 37 ++-- 5 files changed, 390 insertions(+), 301 deletions(-) diff --git a/board.py b/board.py index d8ec1143..691e0513 100644 --- a/board.py +++ b/board.py @@ -1,4 +1,6 @@ import pygame +from pygame.examples.moveit import WIDTH + from cell import Cell class Board: @@ -7,60 +9,56 @@ def __init__(self, width, height, screen, difficulty): self.height = height self.screen = screen self.difficulty = difficulty - self.cells = [] - self.selected_cell = None - self.generate_board() - - def generate_board(self): - board_values = [[0 for _ in range(9)] for _ in range(9)] - for row in range(9): - cell_row = [] - for col in range(9): - cell_row.append(Cell(board_values[row][col], row, col, self.screen)) - self.cells.append(cell_row) + self.cells = [[Cell(0, i, j, screen) for j in range(9)] for i in range(9)] + self.current = None + self.original_values = [[cell.value for cell in row] for row in self.cells] def draw(self): for row in range(10): - thickness = 2 if row % 3 == 0 else 1 - pygame.draw.line(self.screen, (0, 0, 0), (0, row * 60), (540, row * 60), thickness) - pygame.draw.line(self.screen, (0, 0, 0), (row * 60, 0), (row * 60, 540), thickness) - + thickness = 3 if row % 3 == 0 else 1 + pygame.draw.line(self.screen, (0, 0, 0), (0, row * 100), (900, row * 100), thickness) + pygame.draw.line(self.screen, (0, 0, 0), (row * 100, 0), (row * 100, 900), thickness) for row in self.cells: for cell in row: cell.draw() def select(self, row, col): - if self.selected_cell: - self.selected_cell.selected = False - self.selected_cell = self.cells[row][col] - self.selected_cell.selected = True + if self.current: + self.current.selected = False + + if self.cells[row][col].editable: + self.cells[row][col].selected = True + self.current = self.cells[row][col] + else: + self.current = None def click(self, x, y): if x < self.width and y < self.height: - row, col = y // 60, x // 60 + row = y // 100 + col = x // 100 self.select(row, col) return row, col return None def clear(self): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_sketched_value(0) + if self.current and self.current.value == 0: + self.current.set_sketched_value(0) def sketch(self, value): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_sketched_value(value) + if self.current and self.current.value == 0: + self.current.set_sketched_value(value) def place_number(self, value): - if self.selected_cell and self.selected_cell.value == 0: - self.selected_cell.set_cell_value(value) - self.selected_cell.set_sketched_value(0) + if self.current and self.current.value == 0: + self.current.set_cell_value(value) + self.current.set_sketched_value(0) def reset_to_original(self): - for row in self.cells: - for cell in row: - if cell.value == 0: - cell.set_cell_value(0) - cell.set_sketched_value(0) + for i in range(9): + for j in range(9): + if self.cells[i][j].editable: + self.cells[i][j].set_cell_value(self.original_values[i][j]) + self.cells[i][j].set_sketched_value(0) def is_full(self): for row in self.cells: @@ -81,4 +79,19 @@ def find_empty(self): return None def check_board(self): - pass + for row in self.cells: + if not self._is_valid_group([cell.value for cell in row]): + return False + for col in range(9): + if not self._is_valid_group([self.cells[row][col].value for row in range(9)]): + return False + for i in range(0, 9, 3): + for j in range(0, 9, 3): + subgrid = [self.cells[x][y].value for x in range(i, i + 3) for y in range(j, j + 3)] + if not self._is_valid_group(subgrid): + return False + return True + + def _is_valid_group(self, values): + nums = [v for v in values if v != 0] + return len(nums) == len(set(nums)) \ No newline at end of file diff --git a/cell.py b/cell.py index cda8da58..e5ee4b40 100644 --- a/cell.py +++ b/cell.py @@ -1,14 +1,15 @@ import pygame +from constants import * class Cell: - def __init__(self, value, row, col, screen, size=60): + def __init__(self, value, row, col, screen): self.value = value - self.sketched_value = 0 self.row = row self.col = col self.screen = screen - self.size = size self.selected = False + self.sketched_val = None + self.editable = True def set_cell_value(self, value): self.value = value @@ -17,17 +18,18 @@ def set_sketched_value(self, value): self.sketched_value = value def draw(self): - x = self.col * self.size - y = self.row * self.size - - color = (255, 0, 0) if self.selected else (0, 0, 0) - pygame.draw.rect(self.screen, color, (x, y, self.size, self.size), 2) - - font = pygame.font.Font(None, 40) - + font_num = pygame.font.Font(None, 80) if self.value != 0: - text = font.render(str(self.value), True, (0, 0, 0)) - self.screen.blit(text, (x + self.size // 3, y + self.size // 4)) - elif self.sketched_value != 0: - text = font.render(str(self.sketched_value), True, (128, 128, 128)) - self.screen.blit(text, (x + 5, y + 5)) + num_surface = font_num.render(str(self.value), True, BLACK) + num_rectangle = num_surface.get_rect( + center=(100 * self.col + 50, 100 * self.row + 50)) + self.screen.blit(num_surface, num_rectangle) + if self.selected: + red_square = pygame.Rect(self.col * 100, self.row * 100, 100, 100) + pygame.draw.rect(self.screen, (255, 0, 0), red_square, 3) # Red outline with 3 px thickness + if self.sketched_val is not None: + font_sketch = pygame.font.Font(None, 40) + sketch_surface = font_sketch.render(str(self.sketched_val), True, BLACK) + sketch_rectangle = sketch_surface.get_rect( + center=(100 * self.col + 50, 100 * self.row + 50)) + self.screen.blit(sketch_surface, sketch_rectangle) \ No newline at end of file diff --git a/constants.py b/constants.py index 063064cd..1fca8516 100644 --- a/constants.py +++ b/constants.py @@ -1,14 +1,14 @@ #All of these values are subject to change -WIDTH = 850 # Window Width -HEIGHT = 1000 # Window Height -LIGHT_BLUE = (125, 248, 255) #Light Blue -PURPLE = (150, 10, 255) #Purple +WIDTH = 900 +HEIGHT = 1000 +LIGHT_BLUE = (0, 47, 255) #Light Blue +PURPLE = (200, 0, 255) #Purple GREEN = (125, 255, 125) # Green RED = (250, 52, 52) # Red BLACK = (0, 0, 0) #Black PINK = (255, 10, 200) #Pink -WHITE = (255, 255, 255) #White -EASY = 30 # Easy difficulty squares unfilled -MEDIUM = 40 # Medium difficulty squares unfilled -HARD = 50 # Hard difficulty squares unfilled +WHITE = (255, 255, 255) +EASY = 30 +MEDIUM = 40 +HARD = 50 diff --git a/sudoku.py b/sudoku.py index 44f3c910..6eab77ed 100644 --- a/sudoku.py +++ b/sudoku.py @@ -1,131 +1,118 @@ -from idlelib.pyshell import restart_line -from sys import displayhook - -import pygame, sys -from pygame.display import update +import pygame +import sys from board import Board -from cell import Cell from constants import * -from sudoku_generator import * +from sudoku_generator import SudokuGenerator + def game_start(screen): - #Title/Button font init - start_title_font = pygame.font.Font(None, 120) - subtitle_font = pygame.font.Font(None, 90) - button_font = pygame.font.Font(None, 70) - - #Background coloring - screen.fill(LIGHT_BLUE) - - #Creating title text - main_title_surface = start_title_font.render("Welcome to Sudoku", 0, PINK) - main_title_rectangle = main_title_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 - 300)) - #Create outline - main_title_outline = start_title_font.render("Welcome to Sudoku", 0, BLACK) - for i in range (-4, 5): + #Initialize Font + start_title_font = pygame.font.Font(None, 130) + subtitle_font = pygame.font.Font(None, 100) + button_font = pygame.font.Font(None, 90) + + title_board = SudokuGenerator(9,35) + title_board.fill_values() + title_board.remove_cells() + disp = title_board.get_board() + + display_board = Board(100, 100, screen, 0) + for i in range(9): + for j in range(9): + display_board.cells[i][j].value = disp[i][j] + if disp[i][j] != 0: + display_board.cells[i][j].editable = False + + + + + #Main title text + screen.fill(PINK) + display_board.draw() + main_title_surface = start_title_font.render("Welcome to Sudoku", True, PURPLE) + main_title_rectangle = main_title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 300)) + screen.blit(main_title_surface, main_title_rectangle) + + #Subtitle text + subtitle_surface = subtitle_font.render("Select Game Mode", True, PURPLE) + subtitle_rectangle = subtitle_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) + screen.blit(subtitle_surface, subtitle_rectangle) + + #Outline setup + main_title_outline = start_title_font.render("Welcome to Sudoku", 0, WHITE) + for i in range(-4, 5): for j in range(-4, 5): - screen.blit(main_title_outline, main_title_surface.get_rect(center = (WIDTH //2 + i, HEIGHT // 2 - 300 + j))) + screen.blit(main_title_outline, main_title_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 300 + j))) screen.blit(main_title_surface, main_title_rectangle) - #Creating Subtitle - subtitle_surface = subtitle_font.render("Select Game Mode:", 0, PINK) - subtitle_rectangle = subtitle_surface.get_rect(center = (WIDTH // 2 , HEIGHT // 2 - 50)) - subtitle_outline = subtitle_font.render("Select Game Mode:", 0, BLACK) + subtitle_outline = subtitle_font.render("Select Game Mode", 0, WHITE) for i in range(-4, 5): for j in range(-4, 5): screen.blit(subtitle_outline, subtitle_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 50 + j))) screen.blit(subtitle_surface, subtitle_rectangle) - #Init Buttons - easy_text = button_font.render("Easy", 0, BLACK) - medium_text = button_font.render("Medium", 0, BLACK) - hard_text = button_font.render("Hard", 0, BLACK) - - #Init Easy/Medium/Hard Button Text Box Background - easy_surface = pygame.Surface((easy_text.get_size()[0] + 20, easy_text.get_size()[1] + 20)) - easy_surface.fill(PINK) - easy_surface.blit(easy_text, (10, 10)) - medium_surface = pygame.Surface((medium_text.get_size()[0] + 20, medium_text.get_size()[1] + 20)) - medium_surface.fill(PINK) - medium_surface.blit(medium_text, (10, 10)) - hard_surface = pygame.Surface((hard_text.get_size()[0] + 20, hard_text.get_size()[1] + 20)) - hard_surface.fill(PINK) - hard_surface.blit(hard_text, (10, 10)) - - - #Init Button Rectangle - easy_rectangle = easy_surface.get_rect(center = (WIDTH // 2 + 200 , HEIGHT // 2 + 150)) - medium_rectangle = medium_surface.get_rect(center = (WIDTH // 2 , HEIGHT // 2 + 150)) - hard_rectangle = hard_surface.get_rect(center = (WIDTH // 2 - 200, HEIGHT // 2 + 150)) - - #Init Button Outlines - easy_ot_surface = pygame.Surface((easy_text.get_size()[0] + 30, easy_text.get_size()[1] + 30)) - easy_ot_surface.fill(BLACK) - medium_ot_surface = pygame.Surface((medium_text.get_size()[0] + 30, medium_text.get_size()[1] + 30)) - medium_ot_surface.fill(BLACK) - hard_ot_surface = pygame.Surface((hard_text.get_size()[0] + 30, hard_text.get_size()[1] + 30)) - hard_ot_surface.fill(BLACK) - - easy_ot_rectangle = easy_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT // 2 + 150)) - medium_ot_rectangle = medium_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) - hard_ot_rectangle = hard_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT // 2 + 150)) - - - #Draw Buttons - screen.blit(easy_ot_surface, easy_ot_rectangle) - screen.blit(medium_ot_surface, medium_ot_rectangle) - screen.blit(hard_ot_surface, hard_ot_rectangle) - screen.blit(easy_surface, easy_rectangle) - screen.blit(medium_surface, medium_rectangle) - screen.blit(hard_surface, hard_rectangle) + #Main menu buttons + button_data = [("Easy", WIDTH // 2 + 270), ("Medium", WIDTH // 2), ("Hard", WIDTH // 2 - 270)] + buttons = [] + + for text, x_pos in button_data: + button_text = button_font.render(text, True, WHITE) + button_surface = pygame.Surface((button_text.get_width() + 20, button_text.get_height() + 20)) + button_surface.fill(PURPLE) + button_surface.blit(button_text, (10, 10)) + button_rectangle = button_surface.get_rect(center=(x_pos, HEIGHT // 2 + 150)) + buttons.append((button_surface, button_rectangle, text.lower())) + button_ot_surface = pygame.Surface((button_text.get_width() + 30, button_text.get_height() + 30)) + button_ot_surface.fill(BLACK) + screen.blit(button_ot_surface, button_rectangle) + screen.blit(button_surface, button_rectangle) + while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: - if easy_rectangle.collidepoint(event.pos): - return EASY - elif medium_rectangle.collidepoint(event.pos): - return MEDIUM - elif hard_rectangle.collidepoint(event.pos): - return HARD + for _, button_rect, difficulty in buttons: + if button_rect.collidepoint(event.pos): + return difficulty pygame.display.update() -def during_game(screen, difficulty): - #Init Fonts +def during_game(screen, display_board, difficulty): + + #Font bottom_button_font = pygame.font.Font(None, 50) - small_msg_font = pygame.font.Font(None, 30) + small_msg_font = pygame.font.Font(None, 40) - # BG color - screen.fill(PURPLE) - - #Init small message that displays the difficulty + #Difficulty text + difficulty = difficulty.upper() small_msg_surface = small_msg_font.render(difficulty, 0, BLACK) - small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2, HEIGHT - 50)) - screen.blit(small_msg_surface, small_msg_rectangle) - + small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2 - 370, HEIGHT // 2 + 420)) - #Text displays for the RESET/RESTART/EXIT buttons + #Init text reset_text = bottom_button_font.render("RESET", 0, BLACK) restart_text = bottom_button_font.render("RESTART", 0, BLACK) exit_text = bottom_button_font.render("EXIT", 0, BLACK) - #Init Text Box for Buttons + #Init reset button reset_surface = pygame.Surface((reset_text.get_size()[0] + 20, reset_text.get_size()[1] + 20)) reset_surface.fill(PINK) reset_surface.blit(reset_text, (10, 10)) + + #Init restart button restart_surface = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) restart_surface.fill(PINK) restart_surface.blit(restart_text, (10, 10)) + + #Init exit button exit_surface = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) exit_surface.fill(PINK) exit_surface.blit(exit_text, (10, 10)) - #Init Rectangles for Buttons - reset_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 150)) - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 150)) - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 150)) + #Set button locations + reset_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 50)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 50)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 50)) - #Init Outlines + #Outline setup reset_ot_surface = pygame.Surface((reset_text.get_size()[0] + 30, reset_text.get_size()[1] + 30)) reset_ot_surface.fill(BLACK) restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 30, restart_text.get_size()[1] + 30)) @@ -133,183 +120,265 @@ def during_game(screen, difficulty): exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 30, exit_text.get_size()[1] + 30)) exit_ot_surface.fill(BLACK) - #Init Outline Rectangles - reset_ot_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 150)) - restart_ot_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 150)) - exit_ot_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 150)) - # - screen.blit(reset_ot_surface, reset_ot_rectangle) - screen.blit(restart_ot_surface, restart_ot_rectangle) - screen.blit(exit_ot_surface, exit_ot_rectangle) - screen.blit(reset_surface, reset_rectangle) - screen.blit(restart_surface, restart_rectangle) - screen.blit(exit_surface, exit_rectangle) + + clicked_row, clicked_col = -1, -1 while True: + screen.fill(PURPLE) + display_board.draw() + + if clicked_row != -1 and clicked_col != -1: + display_board.select(clicked_row, clicked_col) + screen.blit(reset_ot_surface, reset_rectangle) + screen.blit(restart_ot_surface, restart_rectangle) + screen.blit(exit_ot_surface, exit_rectangle) + screen.blit(reset_surface, reset_rectangle) + screen.blit(restart_surface, restart_rectangle) + screen.blit(exit_surface, exit_rectangle) + screen.blit(small_msg_surface, small_msg_rectangle) + for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() + if event.type == pygame.MOUSEBUTTONDOWN: if reset_rectangle.collidepoint(event.pos): - return + display_board.reset_to_original() + display_board.draw() elif restart_rectangle.collidepoint(event.pos): - return + main() elif exit_rectangle.collidepoint(event.pos): sys.exit() - pygame.display.update() - -def win_screen(screen): - # Title/Button font init - title_font = pygame.font.Font(None, 150) - button_font = pygame.font.Font(None, 100) - - # Background coloring - screen.fill(GREEN) - - # Creating title text - title_surface = title_font.render("YOU WON!!!", 0, BLACK) - title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 250)) - screen.blit(title_surface, title_rectangle) - - # Init Exit Button - exit_text = button_font.render("EXIT", 0, BLACK) - - # Init Exit Button Text Box Background - exit_surface = pygame.Surface((exit_text.get_size()[0] + 40, exit_text.get_size()[1] + 40)) - exit_surface.fill(PURPLE) - exit_surface.blit(exit_text, (20, 20)) - # Init Button Rectangle - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) - - # Init Restart Button - restart_text = button_font.render("RESTART", 0, BLACK) - - # Init Restart Button Text Box Background - restart_surface = pygame.Surface((restart_text.get_size()[0] + 40, restart_text.get_size()[1] + 40)) - restart_surface.fill(PURPLE) - restart_surface.blit(restart_text, (20, 20)) - - # Init Button Rectangle - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 300)) - - #Init Restart Button Outline - restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 50, restart_text.get_size()[1] + 50)) - restart_ot_surface.fill(BLACK) - restart_ot_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 300)) - - #Init Exit Button Outline - exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 50, exit_text.get_size()[1] + 50)) - exit_ot_surface.fill(BLACK) - exit_ot_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) + if 0 <= event.pos[0] < WIDTH and 0 <= event.pos[1] < WIDTH: + row, col = display_board.click(event.pos[0], event.pos[1]) + if display_board.cells[row][col].editable: + clicked_row, clicked_col = row, col + else: + clicked_row, clicked_col = -1, -1 + + if event.type == pygame.KEYDOWN: + if clicked_row != -1 and clicked_col != -1: + if event.key in (pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4, pygame.K_5, + pygame.K_6, pygame.K_7, pygame.K_8, pygame.K_9): + value = int(event.unicode) + if display_board.cells[clicked_row][clicked_col].editable: + display_board.cells[clicked_row][clicked_col].value = value + elif event.key == pygame.K_UP: + clicked_row = (clicked_row - 1) % 9 + elif event.key == pygame.K_DOWN: + clicked_row = (clicked_row + 1) % 9 + elif event.key == pygame.K_LEFT: + clicked_col = (clicked_col - 1) % 9 + elif event.key == pygame.K_RIGHT: + clicked_col = (clicked_col + 1) % 9 + while not display_board.cells[clicked_row][clicked_col].editable: + if event.key in (pygame.K_UP, pygame.K_DOWN): + clicked_row = (clicked_row - 1) % 9 if event.key == pygame.K_UP else (clicked_row + 1) % 9 + if event.key in (pygame.K_LEFT, pygame.K_RIGHT): + clicked_col = (clicked_col - 1) % 9 if event.key == pygame.K_LEFT else (clicked_col + 1) % 9 + if display_board.is_full(): + if display_board.check_board(): + draw_game_win(screen) + else: + draw_game_lose(screen) + pygame.display.update() - # Draw Buttons - screen.blit(restart_ot_surface, restart_ot_rectangle) - screen.blit(exit_ot_surface, exit_ot_rectangle) - screen.blit(restart_surface, restart_rectangle) - screen.blit(exit_surface, exit_rectangle) +def draw_game_win(screen): + win_font = pygame.font.Font(None, 200) + try_font = pygame.font.Font(None, 70) + button_font = pygame.font.Font(None, 80) + screen.fill(BLACK) + color = WHITE + b_color = WHITE + b_color2 = b_color + x_pos1 = 200 + x_pos2 = 70 + b_size = 50 + + for i in range(5): + if i == 0: + color = GREEN + b_color = WHITE + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + elif i == 1: + color = PURPLE + b_color = WHITE + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + elif i == 2: + color = PINK + b_color = BLACK + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + elif i == 3: + color = RED + b_color = BLACK + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + elif i == 4: + b_color = RED + b_color2 = GREEN + color = WHITE + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + + win_surface = win_font.render("YOU", True, color) + win_rectangle = win_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - x_pos1)) + screen.blit(win_surface, win_rectangle) + + yw_surface = win_font.render("WIN!", 0, color) + yw_rectangle = yw_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - x_pos2)) + screen.blit(yw_surface, yw_rectangle) + + try_surface = try_font.render("PLAY AGAIN?", True, GREEN) + try_rectangle = try_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) + screen.blit(try_surface, try_rectangle) + + restart_text = button_font.render("YES", True, BLACK) + restart_surface = pygame.Surface((restart_text.get_width() + b_size, restart_text.get_height() + b_size)) + restart_surface.fill(b_color2) + restart_surface.blit(restart_text, (10, 10)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2 - 100, HEIGHT // 2 + 200)) + exit_text = button_font.render("NO", True, BLACK) + exit_surface = pygame.Surface((exit_text.get_width() + b_size, exit_text.get_height() + b_size)) + exit_surface.fill(b_color) + exit_surface.blit(exit_text, (10, 10)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 + 100, HEIGHT // 2 + 200)) + screen.blit(restart_surface, restart_rectangle) + screen.blit(exit_surface, exit_rectangle) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: - if exit_rectangle.collidepoint(event.pos): + if restart_rectangle.collidepoint(event.pos): + main() + elif exit_rectangle.collidepoint(event.pos): sys.exit() - elif restart_rectangle.collidepoint(event.pos): - return pygame.display.update() -def lose_screen(screen): - # Title/Button font init - title_font = pygame.font.Font(None, 150) - button_font = pygame.font.Font(None, 100) - - # Background coloring - screen.fill(RED) - - # Creating title text - title_surface = title_font.render("YOU LOST :<(", 0, BLACK) - title_rectangle = title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 250)) - screen.blit(title_surface, title_rectangle) - - # Init Restart Button - restart_text = button_font.render("RESTART", 0, BLACK) - # Init Restart Button Text Box Background - restart_surface = pygame.Surface((restart_text.get_size()[0] + 40, restart_text.get_size()[1] + 40)) - restart_surface.fill(LIGHT_BLUE) - restart_surface.blit(restart_text, (20, 20)) +def draw_game_lose(screen): + lose_font = pygame.font.Font(None, 200) + try_font = pygame.font.Font(None, 70) + button_font = pygame.font.Font(None, 80) + screen.fill(BLACK) + color = WHITE + b_color = WHITE + b_color2 = b_color + x_pos1 = 200 + x_pos2 = 70 + b_size = 50 + + for i in range(5): + if i == 0: + color = GREEN + b_color = WHITE + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + elif i == 1: + color = PURPLE + b_color = WHITE + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + elif i == 2: + color = PINK + b_color = BLACK + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + elif i == 3: + color = RED + b_color = BLACK + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + elif i == 4: + b_color = RED + b_color2 = GREEN + color = WHITE + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + + lose_surface = lose_font.render("YOU", True, color) + lose_rectangle = lose_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - x_pos1)) + screen.blit(lose_surface, lose_rectangle) + + yl_surface = lose_font.render("LOSE!", 0, color) + yl_rectangle = yl_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - x_pos2)) + screen.blit(yl_surface, yl_rectangle) + + try_surface = try_font.render("TRY AGAIN?", True, RED) + try_rectangle = try_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 + 100)) + screen.blit(try_surface, try_rectangle) + + restart_text = button_font.render("YES", True, BLACK) + restart_surface = pygame.Surface((restart_text.get_width() + b_size, restart_text.get_height() + b_size)) + restart_surface.fill(b_color2) + restart_surface.blit(restart_text, (10, 10)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2 - 100, HEIGHT // 2 + 200)) + exit_text = button_font.render("NO", True, BLACK) + exit_surface = pygame.Surface((exit_text.get_width() + b_size, exit_text.get_height() + b_size)) + exit_surface.fill(b_color) + exit_surface.blit(exit_text, (10, 10)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 + 100, HEIGHT // 2 + 200)) + screen.blit(restart_surface, restart_rectangle) + screen.blit(exit_surface, exit_rectangle) - # Init Button Rectangle - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2 , HEIGHT // 2 + 300)) - - # Init Exit Button - exit_text = button_font.render("EXIT", 0, BLACK) - - # Init Exit Button Text Box Background - exit_surface = pygame.Surface((exit_text.get_size()[0] + 40, exit_text.get_size()[1] + 40)) - exit_surface.fill(LIGHT_BLUE) - exit_surface.blit(exit_text, (20, 20)) - - # Init Button Rectangle - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) - - # Init Restart Button Outline - restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 50, restart_text.get_size()[1] + 50)) - restart_ot_surface.fill(BLACK) - restart_ot_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 300)) - - # Init Exit Button Outline - exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 50, exit_text.get_size()[1] + 50)) - exit_ot_surface.fill(BLACK) - exit_ot_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 150)) - - # Draw Buttons - screen.blit(restart_ot_surface, restart_ot_rectangle) - screen.blit(exit_ot_surface, exit_ot_rectangle) - screen.blit(restart_surface, restart_rectangle) - screen.blit(exit_surface, exit_rectangle) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: - if exit_rectangle.collidepoint(event.pos): + if restart_rectangle.collidepoint(event.pos): + main() + elif exit_rectangle.collidepoint(event.pos): sys.exit() - elif restart_rectangle.collidepoint(event.pos): - return pygame.display.update() -def main (): - game_over = False - dif = "" + + +def main(): pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) - pygame.display.set_caption("Prog 1 Sudoku") - while True: - difficulty = game_start(screen) - board = SudokuGenerator(9, difficulty) - if difficulty == 30: - dif = "EASY" - elif difficulty == 40: - dif = "MEDIUM" - elif difficulty == 50: - dif = "HARD" - screen.fill(LIGHT_BLUE) - during_game(screen, dif) - # lose_screen(screen) - # win_screen(screen) - # board.print_board() - # For debugging ^ + pygame.display.set_caption("Sudoku") + difficulty = game_start(screen) + removed_cells = {"easy": 30, "medium": 40, "hard": 50} + sudoku = SudokuGenerator(9, removed_cells[difficulty]) + sudoku.fill_values() + sudoku.remove_cells() + board_state = sudoku.get_board() + display_board = Board(WIDTH, WIDTH, screen, removed_cells[difficulty]) + for i in range(9): + for j in range(9): + display_board.cells[i][j].value = board_state[i][j] + if board_state[i][j] != 0: + display_board.cells[i][j].editable = False + display_board.draw() + during_game(screen, display_board, difficulty) if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/sudoku_generator.py b/sudoku_generator.py index 846e9195..74871779 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -1,5 +1,6 @@ import random + class SudokuGenerator: ''' create a sudoku board - initialize class variables and set up the 2D board @@ -15,10 +16,11 @@ class SudokuGenerator: Return: None ''' + def __init__(self, row_length, removed_cells): self.row_length = row_length self.removed_cells = removed_cells - self.board = [[0 for i in range(row_length)] for j in range(row_length)] + self.board = [[0 for row in range(row_length)] for col in range(row_length)] self.box_length = int(row_length ** 0.5) ''' @@ -42,7 +44,7 @@ def get_board(self): def print_board(self): for row in self.board: for col in row: - print(col, end = " ") + print(col, end=" ") print() ''' @@ -52,7 +54,7 @@ def print_board(self): Parameters: row is the index of the row we are checking num is the value we are looking for in the row - + Return: boolean ''' @@ -68,7 +70,7 @@ def valid_in_row(self, row, num): Parameters: col is the index of the column we are checking num is the value we are looking for in the column - + Return: boolean ''' @@ -92,12 +94,12 @@ def valid_in_col(self, col, num): ''' def valid_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): + 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 - + ''' 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 @@ -134,10 +136,12 @@ def fill_box(self, row_start, col_start): nums_list = [1, 2, 3, 4, 5, 6, 7, 8, 9] random.shuffle(nums_list) - for row in range(row_start, row_start+3): - for col in range(col_start, col_start+3): + for row in range(row_start, row_start + 3): + for col in range(col_start, col_start + 3): for num in nums_list: - if self.valid_in_box(row_start, col_start, num) and self.valid_in_col(col, num) and self.valid_in_row(row, num): + if self.valid_in_box(row_start, col_start, num) and self.valid_in_col(col, + num) and self.valid_in_row( + row, num): self.board[row][col] = num nums_list.remove(num) break @@ -159,7 +163,7 @@ def fill_diagonal(self): 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 @@ -185,7 +189,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 @@ -212,7 +216,7 @@ def fill_values(self): 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 @@ -223,8 +227,8 @@ def fill_values(self): def remove_cells(self): removed = 0 while removed < self.removed_cells: - row = random.randint(0, self.row_length-1) - col = random.randint(0, self.row_length-1) + row = random.randint(0, self.row_length - 1) + col = random.randint(0, self.row_length - 1) if self.board[row][col] == 0: continue @@ -232,6 +236,7 @@ def remove_cells(self): self.board[row][col] = 0 removed += 1 + ''' DO NOT CHANGE Provided for students @@ -248,6 +253,7 @@ def remove_cells(self): Return: list[list] (a 2D Python list to represent the board) ''' + def generate_sudoku(size, removed): sudoku = SudokuGenerator(size, removed) sudoku.fill_values() @@ -255,4 +261,3 @@ def generate_sudoku(size, removed): sudoku.remove_cells() board = sudoku.get_board() return board - From ba10574733a362e9233beea69242177aa4ea3279 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Fri, 6 Dec 2024 22:50:40 -0500 Subject: [PATCH 26/30] Revert "Merge pull request #4 from DerekCamilo/main" This reverts commit 4cda2b2458996d557cbe64f5f5ecb648a9902efb, reversing changes made to cca3fc56c46fb7e1d2772438bde28c4890db2152. --- board.py | 12 ++++------ cell.py | 12 +++++----- constants.py | 18 +++++++------- sudoku.py | 57 ++++++++++++--------------------------------- sudoku_generator.py | 35 ++++++++++++---------------- 5 files changed, 51 insertions(+), 83 deletions(-) diff --git a/board.py b/board.py index 6b53936b..444a16cb 100644 --- a/board.py +++ b/board.py @@ -1,6 +1,4 @@ import pygame -from pygame.examples.moveit import WIDTH - from cell import Cell class Board: @@ -15,9 +13,9 @@ def __init__(self, width, height, screen, difficulty): def draw(self): for row in range(10): - thickness = 3 if row % 3 == 0 else 1 - pygame.draw.line(self.screen, (0, 0, 0), (0, row * 100), (900, row * 100), thickness) - pygame.draw.line(self.screen, (0, 0, 0), (row * 100, 0), (row * 100, 900), thickness) + thickness = 2 if row % 3 == 0 else 1 + pygame.draw.line(self.screen, (0, 0, 0), (0, row * 60), (540, row * 60), thickness) + pygame.draw.line(self.screen, (0, 0, 0), (row * 60, 0), (row * 60, 540), thickness) for row in self.cells: for cell in row: cell.draw() @@ -34,8 +32,8 @@ def select(self, row, col): def click(self, x, y): if x < self.width and y < self.height: - row = y // 100 - col = x // 100 + row = y // 60 + col = x // 60 self.select(row, col) return row, col return None diff --git a/cell.py b/cell.py index e5ee4b40..a295e312 100644 --- a/cell.py +++ b/cell.py @@ -1,5 +1,5 @@ import pygame -from constants import * +from constants import TEXT class Cell: def __init__(self, value, row, col, screen): @@ -20,16 +20,16 @@ def set_sketched_value(self, value): def draw(self): font_num = pygame.font.Font(None, 80) if self.value != 0: - num_surface = font_num.render(str(self.value), True, BLACK) + num_surface = font_num.render(str(self.value), True, TEXT) num_rectangle = num_surface.get_rect( - center=(100 * self.col + 50, 100 * self.row + 50)) + center=(60 * self.col + 30, 60 * self.row + 30)) self.screen.blit(num_surface, num_rectangle) if self.selected: - red_square = pygame.Rect(self.col * 100, self.row * 100, 100, 100) + red_square = pygame.Rect(self.col * 60, self.row * 60, 60, 60) pygame.draw.rect(self.screen, (255, 0, 0), red_square, 3) # Red outline with 3 px thickness if self.sketched_val is not None: font_sketch = pygame.font.Font(None, 40) - sketch_surface = font_sketch.render(str(self.sketched_val), True, BLACK) + sketch_surface = font_sketch.render(str(self.sketched_val), True, TEXT) sketch_rectangle = sketch_surface.get_rect( - center=(100 * self.col + 50, 100 * self.row + 50)) + center=(60 * self.col + 30, 60 * self.row + 30)) self.screen.blit(sketch_surface, sketch_rectangle) \ No newline at end of file diff --git a/constants.py b/constants.py index a7ed750a..cc3adf6a 100644 --- a/constants.py +++ b/constants.py @@ -1,14 +1,16 @@ #All of these values are subject to change -WIDTH = 900 +WIDTH = 850 HEIGHT = 1000 -LIGHT_BLUE = (0, 47, 255) #Light Blue -PURPLE = (200, 0, 255) #Purple -GREEN = (125, 255, 125) # Green -RED = (250, 52, 52) # Red -BLACK = (0, 0, 0) #Black -PINK = (255, 10, 200) #Pink -WHITE = (255, 255, 255) +BG_COLOR_1 = (125, 248, 255) #Light Blue +BG_COLOR_2 = (150, 10, 255) #Purple *IF NECCESSARY* +WIN_BG = (125, 255, 125) # Green +LOSE_BG = (250, 52, 52) # Red +TEXT = (0, 0, 0) #Black +TITLE_TEXT = (255, 10, 200) #Pink +BUTTON_COLOR = (255, 10, 200) #Pink +BUTTON_COLOR_2 = (255, 255, 255) +BUTTON_TEXT = (125, 248, 255) #Light Blue EASY = 30 MEDIUM = 40 HARD = 50 diff --git a/sudoku.py b/sudoku.py index 9fdddf16..20bd77c4 100644 --- a/sudoku.py +++ b/sudoku.py @@ -6,6 +6,7 @@ def game_start(screen): + start_title_font = pygame.font.Font(None, 120) subtitle_font = pygame.font.Font(None, 90) button_font = pygame.font.Font(None, 70) @@ -15,23 +16,19 @@ def game_start(screen): main_title_rectangle = main_title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 300)) screen.blit(main_title_surface, main_title_rectangle) - #Subtitle text - subtitle_surface = subtitle_font.render("Select Game Mode", True, PURPLE) + subtitle_surface = subtitle_font.render("Select Game Mode:", True, TITLE_TEXT) subtitle_rectangle = subtitle_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) screen.blit(subtitle_surface, subtitle_rectangle) + button_data = [("Easy", WIDTH // 2 + 200), ("Medium", WIDTH // 2), ("Hard", WIDTH // 2 - 200)] buttons = [] - for text, x_pos in button_data: - button_text = button_font.render(text, True, WHITE) + button_text = button_font.render(text, True, TEXT) button_surface = pygame.Surface((button_text.get_width() + 20, button_text.get_height() + 20)) - button_surface.fill(PURPLE) + button_surface.fill(BUTTON_COLOR) button_surface.blit(button_text, (10, 10)) button_rectangle = button_surface.get_rect(center=(x_pos, HEIGHT // 2 + 150)) buttons.append((button_surface, button_rectangle, text.lower())) - button_ot_surface = pygame.Surface((button_text.get_width() + 30, button_text.get_height() + 30)) - button_ot_surface.fill(BLACK) - screen.blit(button_ot_surface, button_rectangle) screen.blit(button_surface, button_rectangle) while True: @@ -45,8 +42,9 @@ def game_start(screen): pygame.display.update() def during_game(screen, display_board, difficulty): + bottom_button_font = pygame.font.Font(None, 50) - small_msg_font = pygame.font.Font(None, 40) + small_msg_font = pygame.font.Font(None, 30) small_msg_surface = small_msg_font.render(difficulty, 0, TEXT) small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) @@ -56,34 +54,21 @@ def during_game(screen, display_board, difficulty): restart_text = bottom_button_font.render("RESTART", 0, TEXT) exit_text = bottom_button_font.render("EXIT", 0, TEXT) - #Init reset button reset_surface = pygame.Surface((reset_text.get_size()[0] + 20, reset_text.get_size()[1] + 20)) - reset_surface.fill(PINK) + reset_surface.fill(BUTTON_COLOR) reset_surface.blit(reset_text, (10, 10)) - #Init restart button restart_surface = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) - restart_surface.fill(PINK) + restart_surface.fill(BUTTON_COLOR) restart_surface.blit(restart_text, (10, 10)) - #Init exit button exit_surface = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) - exit_surface.fill(PINK) + exit_surface.fill(BUTTON_COLOR) exit_surface.blit(exit_text, (10, 10)) - #Set button locations - reset_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 50)) - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 50)) - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 50)) - - #Outline setup - reset_ot_surface = pygame.Surface((reset_text.get_size()[0] + 30, reset_text.get_size()[1] + 30)) - reset_ot_surface.fill(BLACK) - restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 30, restart_text.get_size()[1] + 30)) - restart_ot_surface.fill(BLACK) - exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 30, exit_text.get_size()[1] + 30)) - exit_ot_surface.fill(BLACK) - + reset_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 150)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 150)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 150)) clicked_row, clicked_col = -1, -1 @@ -93,11 +78,9 @@ def during_game(screen, display_board, difficulty): if clicked_row != -1 and clicked_col != -1: display_board.select(clicked_row, clicked_col) - screen.blit(reset_surface, reset_rectangle) screen.blit(restart_surface, restart_rectangle) screen.blit(exit_surface, exit_rectangle) - screen.blit(small_msg_surface, small_msg_rectangle) for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -112,7 +95,6 @@ def during_game(screen, display_board, difficulty): elif exit_rectangle.collidepoint(event.pos): sys.exit() - if 0 <= event.pos[0] < 540 and 0 <= event.pos[1] < 540: row, col = display_board.click(event.pos[0], event.pos[1]) if display_board.cells[row][col].editable: @@ -169,9 +151,7 @@ def draw_game_win(screen): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: - if restart_rectangle.collidepoint(event.pos): - main() - elif exit_rectangle.collidepoint(event.pos): + if exit_rectangle.collidepoint(event.pos): sys.exit() pygame.display.update() @@ -192,7 +172,6 @@ def draw_game_lose(screen): restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) screen.blit(restart_surface, restart_rectangle) - while True: for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -200,15 +179,9 @@ def draw_game_lose(screen): if event.type == pygame.MOUSEBUTTONDOWN: if restart_rectangle.collidepoint(event.pos): main() - elif exit_rectangle.collidepoint(event.pos): - sys.exit() pygame.display.update() - - - - def main(): pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) @@ -221,8 +194,8 @@ def main(): sudoku.remove_cells() board_state = sudoku.get_board() screen.fill(BG_COLOR_1) - display_board = Board(630, 630, screen, removed_cells[difficulty]) + display_board = Board(630, 630, screen, removed_cells[difficulty]) for i in range(9): for j in range(9): display_board.cells[i][j].value = board_state[i][j] diff --git a/sudoku_generator.py b/sudoku_generator.py index 74871779..d12f33b1 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -1,6 +1,5 @@ import random - class SudokuGenerator: ''' create a sudoku board - initialize class variables and set up the 2D board @@ -16,7 +15,6 @@ class SudokuGenerator: Return: None ''' - def __init__(self, row_length, removed_cells): self.row_length = row_length self.removed_cells = removed_cells @@ -44,7 +42,7 @@ def get_board(self): def print_board(self): for row in self.board: for col in row: - print(col, end=" ") + print(col, end = " ") print() ''' @@ -54,7 +52,7 @@ def print_board(self): Parameters: row is the index of the row we are checking num is the value we are looking for in the row - + Return: boolean ''' @@ -70,7 +68,7 @@ def valid_in_row(self, row, num): Parameters: col is the index of the column we are checking num is the value we are looking for in the column - + Return: boolean ''' @@ -94,12 +92,12 @@ def valid_in_col(self, col, num): ''' def valid_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): + 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 - + ''' 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 @@ -136,12 +134,10 @@ def fill_box(self, row_start, col_start): nums_list = [1, 2, 3, 4, 5, 6, 7, 8, 9] random.shuffle(nums_list) - for row in range(row_start, row_start + 3): - for col in range(col_start, col_start + 3): + for row in range(row_start, row_start+3): + for col in range(col_start, col_start+3): for num in nums_list: - if self.valid_in_box(row_start, col_start, num) and self.valid_in_col(col, - num) and self.valid_in_row( - row, num): + if self.valid_in_box(row_start, col_start, num) and self.valid_in_col(col, num) and self.valid_in_row(row, num): self.board[row][col] = num nums_list.remove(num) break @@ -163,7 +159,7 @@ def fill_diagonal(self): 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 @@ -189,7 +185,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 @@ -216,7 +212,7 @@ def fill_values(self): 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 @@ -227,8 +223,8 @@ def fill_values(self): def remove_cells(self): removed = 0 while removed < self.removed_cells: - row = random.randint(0, self.row_length - 1) - col = random.randint(0, self.row_length - 1) + row = random.randint(0, self.row_length-1) + col = random.randint(0, self.row_length-1) if self.board[row][col] == 0: continue @@ -236,7 +232,6 @@ def remove_cells(self): self.board[row][col] = 0 removed += 1 - ''' DO NOT CHANGE Provided for students @@ -253,7 +248,6 @@ def remove_cells(self): Return: list[list] (a 2D Python list to represent the board) ''' - def generate_sudoku(size, removed): sudoku = SudokuGenerator(size, removed) sudoku.fill_values() @@ -261,3 +255,4 @@ def generate_sudoku(size, removed): sudoku.remove_cells() board = sudoku.get_board() return board + From eff859f05d5c29e0391b50097cdef7af8e1af96b Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Fri, 6 Dec 2024 23:13:28 -0500 Subject: [PATCH 27/30] test --- sudoku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sudoku.py b/sudoku.py index 20bd77c4..2d525ccc 100644 --- a/sudoku.py +++ b/sudoku.py @@ -206,4 +206,4 @@ def main(): during_game(screen, display_board, difficulty) if __name__ == "__main__": - main() \ No newline at end of file + main() From 67a6a549aa1b6e5d8ad0d06fbccf011376db8b62 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Fri, 6 Dec 2024 23:18:51 -0500 Subject: [PATCH 28/30] Correct version --- board.py | 14 ++- cell.py | 12 +- constants.py | 21 ++-- sudoku.py | 289 +++++++++++++++++++++++++++++++++++--------- sudoku_generator.py | 37 +++--- 5 files changed, 276 insertions(+), 97 deletions(-) diff --git a/board.py b/board.py index 444a16cb..691e0513 100644 --- a/board.py +++ b/board.py @@ -1,4 +1,6 @@ import pygame +from pygame.examples.moveit import WIDTH + from cell import Cell class Board: @@ -13,9 +15,9 @@ def __init__(self, width, height, screen, difficulty): def draw(self): for row in range(10): - thickness = 2 if row % 3 == 0 else 1 - pygame.draw.line(self.screen, (0, 0, 0), (0, row * 60), (540, row * 60), thickness) - pygame.draw.line(self.screen, (0, 0, 0), (row * 60, 0), (row * 60, 540), thickness) + thickness = 3 if row % 3 == 0 else 1 + pygame.draw.line(self.screen, (0, 0, 0), (0, row * 100), (900, row * 100), thickness) + pygame.draw.line(self.screen, (0, 0, 0), (row * 100, 0), (row * 100, 900), thickness) for row in self.cells: for cell in row: cell.draw() @@ -32,8 +34,8 @@ def select(self, row, col): def click(self, x, y): if x < self.width and y < self.height: - row = y // 60 - col = x // 60 + row = y // 100 + col = x // 100 self.select(row, col) return row, col return None @@ -92,4 +94,4 @@ def check_board(self): def _is_valid_group(self, values): nums = [v for v in values if v != 0] - return len(nums) == len(set(nums)) + return len(nums) == len(set(nums)) \ No newline at end of file diff --git a/cell.py b/cell.py index a295e312..e5ee4b40 100644 --- a/cell.py +++ b/cell.py @@ -1,5 +1,5 @@ import pygame -from constants import TEXT +from constants import * class Cell: def __init__(self, value, row, col, screen): @@ -20,16 +20,16 @@ def set_sketched_value(self, value): def draw(self): font_num = pygame.font.Font(None, 80) if self.value != 0: - num_surface = font_num.render(str(self.value), True, TEXT) + num_surface = font_num.render(str(self.value), True, BLACK) num_rectangle = num_surface.get_rect( - center=(60 * self.col + 30, 60 * self.row + 30)) + center=(100 * self.col + 50, 100 * self.row + 50)) self.screen.blit(num_surface, num_rectangle) if self.selected: - red_square = pygame.Rect(self.col * 60, self.row * 60, 60, 60) + red_square = pygame.Rect(self.col * 100, self.row * 100, 100, 100) pygame.draw.rect(self.screen, (255, 0, 0), red_square, 3) # Red outline with 3 px thickness if self.sketched_val is not None: font_sketch = pygame.font.Font(None, 40) - sketch_surface = font_sketch.render(str(self.sketched_val), True, TEXT) + sketch_surface = font_sketch.render(str(self.sketched_val), True, BLACK) sketch_rectangle = sketch_surface.get_rect( - center=(60 * self.col + 30, 60 * self.row + 30)) + center=(100 * self.col + 50, 100 * self.row + 50)) self.screen.blit(sketch_surface, sketch_rectangle) \ No newline at end of file diff --git a/constants.py b/constants.py index cc3adf6a..a6f40130 100644 --- a/constants.py +++ b/constants.py @@ -1,17 +1,14 @@ #All of these values are subject to change -WIDTH = 850 +WIDTH = 900 HEIGHT = 1000 -BG_COLOR_1 = (125, 248, 255) #Light Blue -BG_COLOR_2 = (150, 10, 255) #Purple *IF NECCESSARY* -WIN_BG = (125, 255, 125) # Green -LOSE_BG = (250, 52, 52) # Red -TEXT = (0, 0, 0) #Black -TITLE_TEXT = (255, 10, 200) #Pink -BUTTON_COLOR = (255, 10, 200) #Pink -BUTTON_COLOR_2 = (255, 255, 255) -BUTTON_TEXT = (125, 248, 255) #Light Blue +LIGHT_BLUE = (0, 47, 255) #Light Blue +PURPLE = (200, 0, 255) #Purple +GREEN = (125, 255, 125) # Green +RED = (250, 52, 52) # Red +BLACK = (0, 0, 0) #Black +PINK = (255, 10, 200) #Pink +WHITE = (255, 255, 255) EASY = 30 MEDIUM = 40 -HARD = 50 -LINE_COLOR = (245, 152, 66) +HARD = 50 \ No newline at end of file diff --git a/sudoku.py b/sudoku.py index 2d525ccc..6eab77ed 100644 --- a/sudoku.py +++ b/sudoku.py @@ -6,29 +6,64 @@ def game_start(screen): + #Initialize Font + start_title_font = pygame.font.Font(None, 130) + subtitle_font = pygame.font.Font(None, 100) + button_font = pygame.font.Font(None, 90) - start_title_font = pygame.font.Font(None, 120) - subtitle_font = pygame.font.Font(None, 90) - button_font = pygame.font.Font(None, 70) + title_board = SudokuGenerator(9,35) + title_board.fill_values() + title_board.remove_cells() + disp = title_board.get_board() - screen.fill(BG_COLOR_1) - main_title_surface = start_title_font.render("Welcome to Sudoku", True, TITLE_TEXT) + display_board = Board(100, 100, screen, 0) + for i in range(9): + for j in range(9): + display_board.cells[i][j].value = disp[i][j] + if disp[i][j] != 0: + display_board.cells[i][j].editable = False + + + + + #Main title text + screen.fill(PINK) + display_board.draw() + main_title_surface = start_title_font.render("Welcome to Sudoku", True, PURPLE) main_title_rectangle = main_title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 300)) screen.blit(main_title_surface, main_title_rectangle) - subtitle_surface = subtitle_font.render("Select Game Mode:", True, TITLE_TEXT) + #Subtitle text + subtitle_surface = subtitle_font.render("Select Game Mode", True, PURPLE) subtitle_rectangle = subtitle_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) screen.blit(subtitle_surface, subtitle_rectangle) - button_data = [("Easy", WIDTH // 2 + 200), ("Medium", WIDTH // 2), ("Hard", WIDTH // 2 - 200)] + #Outline setup + main_title_outline = start_title_font.render("Welcome to Sudoku", 0, WHITE) + for i in range(-4, 5): + for j in range(-4, 5): + screen.blit(main_title_outline, main_title_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 300 + j))) + screen.blit(main_title_surface, main_title_rectangle) + subtitle_outline = subtitle_font.render("Select Game Mode", 0, WHITE) + for i in range(-4, 5): + for j in range(-4, 5): + screen.blit(subtitle_outline, subtitle_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 50 + j))) + screen.blit(subtitle_surface, subtitle_rectangle) + + #Main menu buttons + button_data = [("Easy", WIDTH // 2 + 270), ("Medium", WIDTH // 2), ("Hard", WIDTH // 2 - 270)] buttons = [] + for text, x_pos in button_data: - button_text = button_font.render(text, True, TEXT) + button_text = button_font.render(text, True, WHITE) button_surface = pygame.Surface((button_text.get_width() + 20, button_text.get_height() + 20)) - button_surface.fill(BUTTON_COLOR) + button_surface.fill(PURPLE) button_surface.blit(button_text, (10, 10)) button_rectangle = button_surface.get_rect(center=(x_pos, HEIGHT // 2 + 150)) buttons.append((button_surface, button_rectangle, text.lower())) + button_ot_surface = pygame.Surface((button_text.get_width() + 30, button_text.get_height() + 30)) + button_ot_surface.fill(BLACK) + screen.blit(button_ot_surface, button_rectangle) screen.blit(button_surface, button_rectangle) while True: @@ -43,44 +78,65 @@ def game_start(screen): def during_game(screen, display_board, difficulty): + #Font bottom_button_font = pygame.font.Font(None, 50) - small_msg_font = pygame.font.Font(None, 30) + small_msg_font = pygame.font.Font(None, 40) - small_msg_surface = small_msg_font.render(difficulty, 0, TEXT) - small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) - screen.blit(small_msg_surface, small_msg_rectangle) + #Difficulty text + difficulty = difficulty.upper() + small_msg_surface = small_msg_font.render(difficulty, 0, BLACK) + small_msg_rectangle = small_msg_surface.get_rect(center=(WIDTH // 2 - 370, HEIGHT // 2 + 420)) - reset_text = bottom_button_font.render("RESET", 0, TEXT) - restart_text = bottom_button_font.render("RESTART", 0, TEXT) - exit_text = bottom_button_font.render("EXIT", 0, TEXT) + #Init text + reset_text = bottom_button_font.render("RESET", 0, BLACK) + restart_text = bottom_button_font.render("RESTART", 0, BLACK) + exit_text = bottom_button_font.render("EXIT", 0, BLACK) + #Init reset button reset_surface = pygame.Surface((reset_text.get_size()[0] + 20, reset_text.get_size()[1] + 20)) - reset_surface.fill(BUTTON_COLOR) + reset_surface.fill(PINK) reset_surface.blit(reset_text, (10, 10)) + #Init restart button restart_surface = pygame.Surface((restart_text.get_size()[0] + 20, restart_text.get_size()[1] + 20)) - restart_surface.fill(BUTTON_COLOR) + restart_surface.fill(PINK) restart_surface.blit(restart_text, (10, 10)) + #Init exit button exit_surface = pygame.Surface((exit_text.get_size()[0] + 20, exit_text.get_size()[1] + 20)) - exit_surface.fill(BUTTON_COLOR) + exit_surface.fill(PINK) exit_surface.blit(exit_text, (10, 10)) - reset_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 150)) - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 150)) - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 150)) + #Set button locations + reset_rectangle = reset_surface.get_rect(center=(WIDTH // 2 + 200, HEIGHT - 50)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT - 50)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 - 200, HEIGHT - 50)) + + #Outline setup + reset_ot_surface = pygame.Surface((reset_text.get_size()[0] + 30, reset_text.get_size()[1] + 30)) + reset_ot_surface.fill(BLACK) + restart_ot_surface = pygame.Surface((restart_text.get_size()[0] + 30, restart_text.get_size()[1] + 30)) + restart_ot_surface.fill(BLACK) + exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 30, exit_text.get_size()[1] + 30)) + exit_ot_surface.fill(BLACK) + + clicked_row, clicked_col = -1, -1 while True: - screen.fill(BG_COLOR_1) + screen.fill(PURPLE) display_board.draw() if clicked_row != -1 and clicked_col != -1: display_board.select(clicked_row, clicked_col) + screen.blit(reset_ot_surface, reset_rectangle) + screen.blit(restart_ot_surface, restart_rectangle) + screen.blit(exit_ot_surface, exit_rectangle) screen.blit(reset_surface, reset_rectangle) screen.blit(restart_surface, restart_rectangle) screen.blit(exit_surface, exit_rectangle) + screen.blit(small_msg_surface, small_msg_rectangle) for event in pygame.event.get(): if event.type == pygame.QUIT: @@ -95,7 +151,7 @@ def during_game(screen, display_board, difficulty): elif exit_rectangle.collidepoint(event.pos): sys.exit() - if 0 <= event.pos[0] < 540 and 0 <= event.pos[1] < 540: + if 0 <= event.pos[0] < WIDTH and 0 <= event.pos[1] < WIDTH: row, col = display_board.click(event.pos[0], event.pos[1]) if display_board.cells[row][col].editable: clicked_row, clicked_col = row, col @@ -130,47 +186,160 @@ def during_game(screen, display_board, difficulty): pygame.display.update() def draw_game_win(screen): - win_font = pygame.font.Font(None, 120) - button_font = pygame.font.Font(None, 50) - - screen.fill(BG_COLOR_1) - win_surface = win_font.render("Game Won!", True, WIN_BG) - win_rectangle = win_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) - screen.blit(win_surface, win_rectangle) - - exit_text = button_font.render("EXIT", True, (255, 255, 255)) - exit_surface = pygame.Surface((exit_text.get_width() + 20, exit_text.get_height() + 20)) - exit_surface.fill(LINE_COLOR) - exit_surface.blit(exit_text, (10, 10)) - exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) - - screen.blit(exit_surface, exit_rectangle) + win_font = pygame.font.Font(None, 200) + try_font = pygame.font.Font(None, 70) + button_font = pygame.font.Font(None, 80) + screen.fill(BLACK) + color = WHITE + b_color = WHITE + b_color2 = b_color + x_pos1 = 200 + x_pos2 = 70 + b_size = 50 + + for i in range(5): + if i == 0: + color = GREEN + b_color = WHITE + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + elif i == 1: + color = PURPLE + b_color = WHITE + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + elif i == 2: + color = PINK + b_color = BLACK + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + elif i == 3: + color = RED + b_color = BLACK + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + elif i == 4: + b_color = RED + b_color2 = GREEN + color = WHITE + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + + win_surface = win_font.render("YOU", True, color) + win_rectangle = win_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - x_pos1)) + screen.blit(win_surface, win_rectangle) + + yw_surface = win_font.render("WIN!", 0, color) + yw_rectangle = yw_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - x_pos2)) + screen.blit(yw_surface, yw_rectangle) + + try_surface = try_font.render("PLAY AGAIN?", True, GREEN) + try_rectangle = try_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) + screen.blit(try_surface, try_rectangle) + + restart_text = button_font.render("YES", True, BLACK) + restart_surface = pygame.Surface((restart_text.get_width() + b_size, restart_text.get_height() + b_size)) + restart_surface.fill(b_color2) + restart_surface.blit(restart_text, (10, 10)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2 - 100, HEIGHT // 2 + 200)) + exit_text = button_font.render("NO", True, BLACK) + exit_surface = pygame.Surface((exit_text.get_width() + b_size, exit_text.get_height() + b_size)) + exit_surface.fill(b_color) + exit_surface.blit(exit_text, (10, 10)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 + 100, HEIGHT // 2 + 200)) + screen.blit(restart_surface, restart_rectangle) + screen.blit(exit_surface, exit_rectangle) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: - if exit_rectangle.collidepoint(event.pos): + if restart_rectangle.collidepoint(event.pos): + main() + elif exit_rectangle.collidepoint(event.pos): sys.exit() pygame.display.update() def draw_game_lose(screen): - lose_font = pygame.font.Font(None, 120) - button_font = pygame.font.Font(None, 50) - screen.fill(BG_COLOR_1) - - lose_surface = lose_font.render("Game Over :(", True, LOSE_BG) - lose_rectangle = lose_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) - screen.blit(lose_surface, lose_rectangle) - - restart_text = button_font.render("RESTART", True, (255, 255, 255)) - restart_surface = pygame.Surface((restart_text.get_width() + 20, restart_text.get_height() + 20)) - restart_surface.fill(LINE_COLOR) - restart_surface.blit(restart_text, (10, 10)) - restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100)) - screen.blit(restart_surface, restart_rectangle) + lose_font = pygame.font.Font(None, 200) + try_font = pygame.font.Font(None, 70) + button_font = pygame.font.Font(None, 80) + screen.fill(BLACK) + color = WHITE + b_color = WHITE + b_color2 = b_color + x_pos1 = 200 + x_pos2 = 70 + b_size = 50 + + for i in range(5): + if i == 0: + color = GREEN + b_color = WHITE + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + elif i == 1: + color = PURPLE + b_color = WHITE + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + elif i == 2: + color = PINK + b_color = BLACK + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + elif i == 3: + color = RED + b_color = BLACK + b_color2 = b_color + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + elif i == 4: + b_color = RED + b_color2 = GREEN + color = WHITE + x_pos1 += 5 + x_pos2 += 5 + b_size -= 10 + + lose_surface = lose_font.render("YOU", True, color) + lose_rectangle = lose_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - x_pos1)) + screen.blit(lose_surface, lose_rectangle) + + yl_surface = lose_font.render("LOSE!", 0, color) + yl_rectangle = yl_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - x_pos2)) + screen.blit(yl_surface, yl_rectangle) + + try_surface = try_font.render("TRY AGAIN?", True, RED) + try_rectangle = try_surface.get_rect(center = (WIDTH // 2, HEIGHT // 2 + 100)) + screen.blit(try_surface, try_rectangle) + + restart_text = button_font.render("YES", True, BLACK) + restart_surface = pygame.Surface((restart_text.get_width() + b_size, restart_text.get_height() + b_size)) + restart_surface.fill(b_color2) + restart_surface.blit(restart_text, (10, 10)) + restart_rectangle = restart_surface.get_rect(center=(WIDTH // 2 - 100, HEIGHT // 2 + 200)) + exit_text = button_font.render("NO", True, BLACK) + exit_surface = pygame.Surface((exit_text.get_width() + b_size, exit_text.get_height() + b_size)) + exit_surface.fill(b_color) + exit_surface.blit(exit_text, (10, 10)) + exit_rectangle = exit_surface.get_rect(center=(WIDTH // 2 + 100, HEIGHT // 2 + 200)) + screen.blit(restart_surface, restart_rectangle) + screen.blit(exit_surface, exit_rectangle) while True: for event in pygame.event.get(): @@ -179,23 +348,29 @@ def draw_game_lose(screen): if event.type == pygame.MOUSEBUTTONDOWN: if restart_rectangle.collidepoint(event.pos): main() + elif exit_rectangle.collidepoint(event.pos): + sys.exit() pygame.display.update() + + + + def main(): pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Sudoku") difficulty = game_start(screen) + removed_cells = {"easy": 30, "medium": 40, "hard": 50} sudoku = SudokuGenerator(9, removed_cells[difficulty]) sudoku.fill_values() sudoku.remove_cells() board_state = sudoku.get_board() - screen.fill(BG_COLOR_1) - display_board = Board(630, 630, screen, removed_cells[difficulty]) + display_board = Board(WIDTH, WIDTH, screen, removed_cells[difficulty]) for i in range(9): for j in range(9): display_board.cells[i][j].value = board_state[i][j] @@ -206,4 +381,4 @@ def main(): during_game(screen, display_board, difficulty) if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/sudoku_generator.py b/sudoku_generator.py index d12f33b1..168fa289 100644 --- a/sudoku_generator.py +++ b/sudoku_generator.py @@ -1,5 +1,6 @@ import random + class SudokuGenerator: ''' create a sudoku board - initialize class variables and set up the 2D board @@ -15,6 +16,7 @@ class SudokuGenerator: Return: None ''' + def __init__(self, row_length, removed_cells): self.row_length = row_length self.removed_cells = removed_cells @@ -42,7 +44,7 @@ def get_board(self): def print_board(self): for row in self.board: for col in row: - print(col, end = " ") + print(col, end=" ") print() ''' @@ -52,7 +54,7 @@ def print_board(self): Parameters: row is the index of the row we are checking num is the value we are looking for in the row - + Return: boolean ''' @@ -68,7 +70,7 @@ def valid_in_row(self, row, num): Parameters: col is the index of the column we are checking num is the value we are looking for in the column - + Return: boolean ''' @@ -92,12 +94,12 @@ def valid_in_col(self, col, num): ''' def valid_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): + 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 - + ''' 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 @@ -134,10 +136,12 @@ def fill_box(self, row_start, col_start): nums_list = [1, 2, 3, 4, 5, 6, 7, 8, 9] random.shuffle(nums_list) - for row in range(row_start, row_start+3): - for col in range(col_start, col_start+3): + for row in range(row_start, row_start + 3): + for col in range(col_start, col_start + 3): for num in nums_list: - if self.valid_in_box(row_start, col_start, num) and self.valid_in_col(col, num) and self.valid_in_row(row, num): + if self.valid_in_box(row_start, col_start, num) and self.valid_in_col(col, + num) and self.valid_in_row( + row, num): self.board[row][col] = num nums_list.remove(num) break @@ -159,7 +163,7 @@ def fill_diagonal(self): 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 @@ -185,7 +189,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 @@ -212,7 +216,7 @@ def fill_values(self): 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 @@ -223,8 +227,8 @@ def fill_values(self): def remove_cells(self): removed = 0 while removed < self.removed_cells: - row = random.randint(0, self.row_length-1) - col = random.randint(0, self.row_length-1) + row = random.randint(0, self.row_length - 1) + col = random.randint(0, self.row_length - 1) if self.board[row][col] == 0: continue @@ -232,6 +236,7 @@ def remove_cells(self): self.board[row][col] = 0 removed += 1 + ''' DO NOT CHANGE Provided for students @@ -248,11 +253,11 @@ def remove_cells(self): 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 - + return board \ No newline at end of file From 777cee36374fc1471f5c33eb5f6f3f78a5f547b4 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Sat, 7 Dec 2024 13:09:20 -0500 Subject: [PATCH 29/30] Scale down --- board.py | 9 +++++---- cell.py | 10 +++++----- constants.py | 7 ++++--- sudoku.py | 32 +++++++++++++++++--------------- 4 files changed, 31 insertions(+), 27 deletions(-) diff --git a/board.py b/board.py index 691e0513..a4843342 100644 --- a/board.py +++ b/board.py @@ -1,5 +1,6 @@ import pygame from pygame.examples.moveit import WIDTH +from constants import * from cell import Cell @@ -16,8 +17,8 @@ def __init__(self, width, height, screen, difficulty): def draw(self): for row in range(10): thickness = 3 if row % 3 == 0 else 1 - pygame.draw.line(self.screen, (0, 0, 0), (0, row * 100), (900, row * 100), thickness) - pygame.draw.line(self.screen, (0, 0, 0), (row * 100, 0), (row * 100, 900), thickness) + pygame.draw.line(self.screen, (0, 0, 0), (0, row * cell_size), (WIDTH, row * cell_size), thickness) + pygame.draw.line(self.screen, (0, 0, 0), (row * cell_size, 0), (row * cell_size, WIDTH), thickness) for row in self.cells: for cell in row: cell.draw() @@ -34,8 +35,8 @@ def select(self, row, col): def click(self, x, y): if x < self.width and y < self.height: - row = y // 100 - col = x // 100 + row = y // cell_size + col = x // cell_size self.select(row, col) return row, col return None diff --git a/cell.py b/cell.py index e5ee4b40..132f797a 100644 --- a/cell.py +++ b/cell.py @@ -18,17 +18,17 @@ def set_sketched_value(self, value): self.sketched_value = value def draw(self): - font_num = pygame.font.Font(None, 80) + cell_size = 70 + font_num = pygame.font.Font(None, 56) if self.value != 0: num_surface = font_num.render(str(self.value), True, BLACK) - num_rectangle = num_surface.get_rect( - center=(100 * self.col + 50, 100 * self.row + 50)) + num_rectangle = num_surface.get_rect(center=(self.col * cell_size + cell_size // 2, self.row * cell_size + cell_size // 2)) self.screen.blit(num_surface, num_rectangle) if self.selected: - red_square = pygame.Rect(self.col * 100, self.row * 100, 100, 100) + red_square = pygame.Rect(self.col * cell_size, self.row * cell_size, cell_size, cell_size) pygame.draw.rect(self.screen, (255, 0, 0), red_square, 3) # Red outline with 3 px thickness if self.sketched_val is not None: - font_sketch = pygame.font.Font(None, 40) + font_sketch = pygame.font.Font(None, 28) sketch_surface = font_sketch.render(str(self.sketched_val), True, BLACK) sketch_rectangle = sketch_surface.get_rect( center=(100 * self.col + 50, 100 * self.row + 50)) diff --git a/constants.py b/constants.py index a6f40130..5c3f1e75 100644 --- a/constants.py +++ b/constants.py @@ -1,7 +1,7 @@ #All of these values are subject to change -WIDTH = 900 -HEIGHT = 1000 +WIDTH = 630 +HEIGHT = 750 LIGHT_BLUE = (0, 47, 255) #Light Blue PURPLE = (200, 0, 255) #Purple GREEN = (125, 255, 125) # Green @@ -11,4 +11,5 @@ WHITE = (255, 255, 255) EASY = 30 MEDIUM = 40 -HARD = 50 \ No newline at end of file +HARD = 50 +cell_size = 70 \ No newline at end of file diff --git a/sudoku.py b/sudoku.py index 6eab77ed..aee7785b 100644 --- a/sudoku.py +++ b/sudoku.py @@ -7,62 +7,64 @@ def game_start(screen): #Initialize Font - start_title_font = pygame.font.Font(None, 130) - subtitle_font = pygame.font.Font(None, 100) - button_font = pygame.font.Font(None, 90) + start_title_font = pygame.font.Font(None, 85) + subtitle_font = pygame.font.Font(None, 65) + button_font = pygame.font.Font(None, 63) title_board = SudokuGenerator(9,35) title_board.fill_values() title_board.remove_cells() disp = title_board.get_board() - display_board = Board(100, 100, screen, 0) + display_board = Board(70, 70, screen, 0) for i in range(9): for j in range(9): display_board.cells[i][j].value = disp[i][j] if disp[i][j] != 0: display_board.cells[i][j].editable = False - - - #Main title text screen.fill(PINK) display_board.draw() main_title_surface = start_title_font.render("Welcome to Sudoku", True, PURPLE) - main_title_rectangle = main_title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 300)) + main_title_rectangle = main_title_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100)) screen.blit(main_title_surface, main_title_rectangle) #Subtitle text subtitle_surface = subtitle_font.render("Select Game Mode", True, PURPLE) - subtitle_rectangle = subtitle_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50)) + subtitle_rectangle = subtitle_surface.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 200)) screen.blit(subtitle_surface, subtitle_rectangle) #Outline setup main_title_outline = start_title_font.render("Welcome to Sudoku", 0, WHITE) for i in range(-4, 5): for j in range(-4, 5): - screen.blit(main_title_outline, main_title_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 300 + j))) + screen.blit(main_title_outline, main_title_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 100 + j))) screen.blit(main_title_surface, main_title_rectangle) subtitle_outline = subtitle_font.render("Select Game Mode", 0, WHITE) for i in range(-4, 5): for j in range(-4, 5): - screen.blit(subtitle_outline, subtitle_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 - 50 + j))) + screen.blit(subtitle_outline, subtitle_surface.get_rect(center=(WIDTH // 2 + i, HEIGHT // 2 + 200 + j))) screen.blit(subtitle_surface, subtitle_rectangle) #Main menu buttons - button_data = [("Easy", WIDTH // 2 + 270), ("Medium", WIDTH // 2), ("Hard", WIDTH // 2 - 270)] + button_data = [("Easy", WIDTH // 2+200), ("Medium", WIDTH // 2), ("Hard", WIDTH // 2 - 200)] buttons = [] for text, x_pos in button_data: button_text = button_font.render(text, True, WHITE) - button_surface = pygame.Surface((button_text.get_width() + 20, button_text.get_height() + 20)) + + button_surface = pygame.Surface((button_text.get_width() + 14, button_text.get_height() + 14)) + button_surface.fill(PURPLE) button_surface.blit(button_text, (10, 10)) - button_rectangle = button_surface.get_rect(center=(x_pos, HEIGHT // 2 + 150)) + button_rectangle = button_surface.get_rect(center=(x_pos, HEIGHT // 2 + 300)) + buttons.append((button_surface, button_rectangle, text.lower())) - button_ot_surface = pygame.Surface((button_text.get_width() + 30, button_text.get_height() + 30)) + + button_ot_surface = pygame.Surface((button_text.get_width() + 21, button_text.get_height() + 21)) button_ot_surface.fill(BLACK) + screen.blit(button_ot_surface, button_rectangle) screen.blit(button_surface, button_rectangle) From ea12739dcd09a08583e954fdb2bf4e120dec7967 Mon Sep 17 00:00:00 2001 From: BTYWAR <24jdai@woodward.edu> Date: Sat, 7 Dec 2024 13:11:31 -0500 Subject: [PATCH 30/30] Cleanup --- sudoku.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/sudoku.py b/sudoku.py index aee7785b..ff0fe0e2 100644 --- a/sudoku.py +++ b/sudoku.py @@ -53,18 +53,13 @@ def game_start(screen): for text, x_pos in button_data: button_text = button_font.render(text, True, WHITE) - button_surface = pygame.Surface((button_text.get_width() + 14, button_text.get_height() + 14)) - button_surface.fill(PURPLE) button_surface.blit(button_text, (10, 10)) button_rectangle = button_surface.get_rect(center=(x_pos, HEIGHT // 2 + 300)) - buttons.append((button_surface, button_rectangle, text.lower())) - button_ot_surface = pygame.Surface((button_text.get_width() + 21, button_text.get_height() + 21)) button_ot_surface.fill(BLACK) - screen.blit(button_ot_surface, button_rectangle) screen.blit(button_surface, button_rectangle) @@ -121,9 +116,6 @@ def during_game(screen, display_board, difficulty): restart_ot_surface.fill(BLACK) exit_ot_surface = pygame.Surface((exit_text.get_size()[0] + 30, exit_text.get_size()[1] + 30)) exit_ot_surface.fill(BLACK) - - - clicked_row, clicked_col = -1, -1 while True: @@ -354,18 +346,12 @@ def draw_game_lose(screen): sys.exit() pygame.display.update() - - - - - def main(): pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Sudoku") difficulty = game_start(screen) - removed_cells = {"easy": 30, "medium": 40, "hard": 50} sudoku = SudokuGenerator(9, removed_cells[difficulty]) sudoku.fill_values()