Wrap around the board, backspace center pms, difficulty arg

This commit is contained in:
Joseph Ferano 2023-11-01 11:23:05 +07:00
parent d4e5be4a7d
commit 913e4b8858
3 changed files with 115 additions and 97 deletions

199
pydoku.py
View File

@ -5,14 +5,15 @@ from enum import Enum
from typing import Set from typing import Set
import threading import threading
import sys
import os import os
from websudoku import * from websudoku import *
@dataclass @dataclass
class Cursor: class Cursor:
row: int = 5 row: int = 4
col: int = 5 col: int = 4
@dataclass @dataclass
class Cell: class Cell:
@ -51,7 +52,6 @@ pg.display.set_caption("Pydoku")
pg.key.set_repeat(200, 35) pg.key.set_repeat(200, 35)
clock = pg.time.Clock() clock = pg.time.Clock()
running = True
################## ##################
# FONTS # FONTS
@ -74,7 +74,6 @@ GRID_Y = screen.get_height() / 2 - 9 * CELL_SIZE // 2
cursorSurface = pg.Surface((CURSOR_SIZE, CURSOR_SIZE), pg.SRCALPHA) cursorSurface = pg.Surface((CURSOR_SIZE, CURSOR_SIZE), pg.SRCALPHA)
cursor = Cursor() cursor = Cursor()
input_method = InputMethod.FILL
board = [] board = []
pencil_marks = [] pencil_marks = []
@ -99,7 +98,11 @@ def data_callback(sudoku_data):
def http_request_thread(): def http_request_thread():
data = get_sudoku_puzzle(Difficulty.EVIL) if len(sys.argv) > 1:
difficulty = Difficulty[sys.argv[1].upper()]
else:
difficulty = Difficulty.MEDIUM
data = get_sudoku_puzzle(difficulty)
data_callback(data) data_callback(data)
http_thread = threading.Thread(target=http_request_thread) http_thread = threading.Thread(target=http_request_thread)
@ -132,8 +135,8 @@ def draw_grid():
def draw_cursor(): def draw_cursor():
pad_diff = (CURSOR_SIZE - CELL_SIZE) // 2 pad_diff = (CURSOR_SIZE - CELL_SIZE) // 2
pg.draw.rect(cursorSurface, (100, 0, 155, 100), [0, 0, CURSOR_SIZE, CURSOR_SIZE]) pg.draw.rect(cursorSurface, (100, 0, 155, 100), [0, 0, CURSOR_SIZE, CURSOR_SIZE])
rect = Rect(CELL_SIZE * (cursor.col - 1) + GRID_X - pad_diff, rect = Rect(CELL_SIZE * cursor.col + GRID_X - pad_diff,
CELL_SIZE * (cursor.row - 1) + GRID_Y - pad_diff, CELL_SIZE * cursor.row + GRID_Y - pad_diff,
CURSOR_SIZE, CURSOR_SIZE) CURSOR_SIZE, CURSOR_SIZE)
screen.blit(cursorSurface, rect) screen.blit(cursorSurface, rect)
@ -206,103 +209,113 @@ def check_board():
return return
print("You completed it!") print("You completed it!")
while running: def main():
for event in pg.event.get(): running = True
if event.type == pg.QUIT: input_method = InputMethod.FILL
running = False
if event.type == pg.MOUSEBUTTONDOWN:
if event.button == 1:
grid_max_x = GRID_X + CELL_SIZE * 9
grid_max_y = GRID_Y + CELL_SIZE * 9
mx = event.pos[0]
my = event.pos[1]
if (mx >= GRID_X
and mx <= grid_max_x
and my >= GRID_Y
and my <= grid_max_y):
cursor.row = int((my - GRID_Y) // CELL_SIZE + 1)
cursor.col = int((mx - GRID_X) // CELL_SIZE + 1)
for btn in buttons: while running:
if btn_rect.collidepoint(event.pos): for event in pg.event.get():
match btn_rect.id: if event.type == pg.QUIT:
case "check": running = False
check_board() if event.type == pg.MOUSEBUTTONDOWN:
case "load": if event.button == 1:
pass grid_max_x = GRID_X + CELL_SIZE * 9
grid_max_y = GRID_Y + CELL_SIZE * 9
mx = event.pos[0]
my = event.pos[1]
if (mx >= GRID_X
and mx <= grid_max_x
and my >= GRID_Y
and my <= grid_max_y):
cursor.row = int((my - GRID_Y) // CELL_SIZE)
cursor.col = int((mx - GRID_X) // CELL_SIZE)
for btn in buttons:
if btn.rect.collidepoint(event.pos):
match btn.id:
case "check":
check_board()
case "load":
pass
if event.type == pg.KEYDOWN: if event.type == pg.KEYDOWN:
# keys = pg.key.get_pressed() # keys = pg.key.get_pressed()
if (event.key == pg.K_h or event.key == pg.K_a) and cursor.col > 1: if (event.key == pg.K_h or event.key == pg.K_a):
cursor.col -= 1 cursor.col = (cursor.col - 1) % 9
if (event.key == pg.K_k or event.key == pg.K_w) and cursor.row > 1: if (event.key == pg.K_k or event.key == pg.K_w):
cursor.row -= 1 cursor.row = (cursor.row - 1) % 9
if (event.key == pg.K_j or event.key == pg.K_s) and cursor.row < 9: if (event.key == pg.K_j or event.key == pg.K_s):
cursor.row += 1 cursor.row = (cursor.row + 1) % 9
if (event.key == pg.K_l or event.key == pg.K_d) and cursor.col < 9: if (event.key == pg.K_l or event.key == pg.K_d):
cursor.col += 1 cursor.col = (cursor.col + 1) % 9
num = pg.key.name(event.key) num = pg.key.name(event.key)
if num.isdigit() and num != '0': if num.isdigit() and num != '0':
num = int(num) num = int(num)
idx = (cursor.row - 1) * 9 + cursor.col - 1 idx = cursor.row * 9 + cursor.col
if board and not board[idx].given: if board and not board[idx].given:
match input_method: match input_method:
case InputMethod.FILL: case InputMethod.FILL:
board[idx].value = num board[idx].value = num
case InputMethod.CENTER: case InputMethod.CENTER:
if num in pencil_marks[idx].center: if num in pencil_marks[idx].center:
pencil_marks[idx].center.remove(num) pencil_marks[idx].center.remove(num)
# Max 3 center pencil marks # Max 3 center pencil marks
elif len(pencil_marks[idx].center) < 3: elif len(pencil_marks[idx].center) < 3:
pencil_marks[idx].center.add(num) pencil_marks[idx].center.add(num)
case InputMethod.BORDER: case InputMethod.BORDER:
if num in pencil_marks[idx].border: if num in pencil_marks[idx].border:
pencil_marks[idx].border.remove(num) pencil_marks[idx].border.remove(num)
else: else:
pencil_marks[idx].border.add(num) pencil_marks[idx].border.add(num)
if event.key == pg.K_BACKSPACE: if event.key == pg.K_BACKSPACE:
idx = (cursor.row - 1) * 9 + cursor.col - 1 idx = cursor.row * 9 + cursor.col
if not board[idx].given: if not board[idx].given:
board[idx].value = 0 if board[idx].value > 0:
board[idx].value = 0
elif pencil_marks[idx].center:
pencil_marks[idx].center.pop()
match event.key: match event.key:
case pg.K_f: case pg.K_f:
input_method = InputMethod.FILL input_method = InputMethod.FILL
case pg.K_c: case pg.K_c:
input_method = InputMethod.CENTER input_method = InputMethod.CENTER
case pg.K_b: case pg.K_b:
input_method = InputMethod.BORDER input_method = InputMethod.BORDER
############## ##############
# Debug stuff # Debug stuff
############## ##############
if event.key == pg.K_F1: if event.key == pg.K_F1:
print(sudoku) print(sudoku)
if event.key == pg.K_F2: if event.key == pg.K_F2:
idx = (cursor.row - 1) * 9 + cursor.col - 1 idx = cursor.row * 9 + cursor.col
if not board[idx].given: if not board[idx].given:
pencil_marks[idx].border = {i for i in range(1, 10)} pencil_marks[idx].border = {i for i in range(1, 10)}
if event.key == pg.K_F3: if event.key == pg.K_F3:
for i,cell in enumerate(board): for i,cell in enumerate(board):
cell.value = sudoku.solution[i] cell.value = sudoku.solution[i]
screen.fill('cornflower blue') screen.fill('cornflower blue')
draw_grid() draw_grid()
with data_lock: with data_lock:
if sudoku is not None: if sudoku is not None:
draw_numbers() draw_numbers()
draw_cursor() draw_cursor()
draw_hud() draw_hud()
draw_buttons() draw_buttons()
pg.display.flip() pg.display.flip()
dt = clock.tick(60) / 1000 dt = clock.tick(60) / 1000
pg.quit() pg.quit()
if __name__ == "__main__":
main()

View File

@ -15,11 +15,12 @@
* DONE Improve pencil mark colors * DONE Improve pencil mark colors
* DONE Async http request * DONE Async http request
* DONE Generalized button code * DONE Generalized button code
* DONE Wrap around the board
* DONE Delete center pencil marks 1 num at a time
* DONE Pass difficulty through command line
* TODO Button to load a new puzzle * TODO Button to load a new puzzle
* TODO Show errors * TODO Show errors
* TODO Pass difficulty through command line
* TODO Choose difficulty buttons * TODO Choose difficulty buttons
* TODO Delete center pencil marks 1 num at a time
* TODO Toast on valid solve * TODO Toast on valid solve
* TODO Show the time it took * TODO Show the time it took
* TODO Save current game * TODO Save current game
@ -27,4 +28,7 @@
* TODO Show current input method * TODO Show current input method
* TODO Show keybindings somehow * TODO Show keybindings somehow
* TODO Pause button * TODO Pause button
* TODO Support undo * TODO Support undo?
* TODO Sudoku generator
* TODO Sudoku solver
* TODO Sudoku difficulty generator

View File

@ -48,7 +48,8 @@ def get_sudoku_puzzle(difficulty: Difficulty) -> Sudoku:
Returns: Returns:
A Sudoku object which contains the cheat and the editmask A Sudoku object which contains the cheat and the editmask
""" """
response = urlopen("https://five.websudoku.com/?level=4") d = str(difficulty.value)
response = urlopen("https://six.websudoku.com/?level="+d, timeout=5)
if response.status == 200: if response.status == 200:
html_content = response.read().decode('utf-8') html_content = response.read().decode('utf-8')