数独作ってみた
GW中に判定と難易度設定も追加したい!
import pygame
import random
import sys
# --- 盤面生成用関数(追加)---
def is_valid(board, num, pos):
row, col = pos
if num in board[row]:
return False
if num in [board[i][col] for i in range(9)]:
return False
start_row, start_col = 3 * (row // 3), 3 * (col // 3)
for i in range(3):
for j in range(3):
if board[start_row + i][start_col + j] == num:
return False
return True
def find_empty(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0:
return (row, col)
return None
def solve(board):
empty = find_empty(board)
if not empty:
return True
row, col = empty
numbers = list(range(1, 10))
random.shuffle(numbers)
for num in numbers:
if is_valid(board, num, (row, col)):
board[row][col] = num
if solve(board):
return True
board[row][col] = 0
return False
def generate_full_board():
board = [[0 for _ in range(9)] for _ in range(9)]
solve(board)
return board
def make_puzzle(board, holes=40):
puzzle = [row[:] for row in board]
count = 0
while count < holes:
row = random.randint(0, 8)
col = random.randint(0, 8)
if puzzle[row][col] != 0:
puzzle[row][col] = 0
count += 1
return puzzle
# --- Pygame設定 ---
pygame.init()
WIDTH, HEIGHT = 540, 600
ROWS, COLS = 9, 9
CELL_SIZE = WIDTH // COLS
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("数独 - Sudoku")
FONT = pygame.font.SysFont("arial", 40)
SMALL_FONT = pygame.font.SysFont("arial", 20)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
BLUE = (50, 50, 255)
# --- ここでランダムな盤面を作る! ---
full_board = generate_full_board()
board = make_puzzle(full_board, holes=40) # 空白40個の盤面
selected = None
user_inputs = [[False for _ in range(COLS)] for _ in range(ROWS)]
def draw_grid():
for i in range(ROWS + 1):
line_width = 3 if i % 3 == 0 else 1
pygame.draw.line(SCREEN, BLACK, (0, i * CELL_SIZE), (WIDTH, i * CELL_SIZE), line_width)
pygame.draw.line(SCREEN, BLACK, (i * CELL_SIZE, 0), (i * CELL_SIZE, WIDTH), line_width)
def draw_reset_button():
reset_rect = pygame.Rect(WIDTH // 2 - 50, WIDTH + 20, 100, 40) # ボタンの四角
pygame.draw.rect(SCREEN, GRAY, reset_rect)
text = SMALL_FONT.render("Reset", True, BLACK)
text_rect = text.get_rect(center=reset_rect.center)
SCREEN.blit(text, text_rect)
return reset_rect
def draw_numbers():
for row in range(ROWS):
for col in range(COLS):
num = board[row][col]
if num != 0:
color = BLUE if user_inputs[row][col] else BLACK
text = FONT.render(str(num), True, color)
SCREEN.blit(text, (col * CELL_SIZE + 20, row * CELL_SIZE + 10))
def draw_selected():
if selected:
row, col = selected
pygame.draw.rect(SCREEN, BLUE, (col * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE), 3)
def place_number(key):
global user_inputs
if selected:
row, col = selected
if board[row][col] == 0:
board[row][col] = key
user_inputs[row][col] = True
def get_cell_pos(pos):
x, y = pos
if x < WIDTH and y < WIDTH:
return y // CELL_SIZE, x // CELL_SIZE
return None
def reset_game():
global full_board, board, user_inputs
full_board = generate_full_board()
board = make_puzzle(full_board, holes=40)
user_inputs = [[False for _ in range(COLS)] for _ in range(ROWS)]
def main():
global selected, user_inputs
clock = pygame.time.Clock()
running = True
while running:
SCREEN.fill(WHITE)
draw_grid()
draw_numbers()
draw_selected()
reset_button = draw_reset_button() # ボタンも描く!
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
if reset_button.collidepoint(pos):
reset_game() # リセットボタン押されたらリセット!
selected = None # 選択解除も忘れずに
else:
selected = get_cell_pos(pos)
if event.type == pygame.KEYDOWN:
if pygame.K_1 <= event.key <= pygame.K_9:
place_number(event.key - pygame.K_0)
elif event.key == pygame.K_DELETE or event.key == pygame.K_BACKSPACE:
if selected:
row, col = selected
if board[row][col] != 0:
board[row][col] = 0
user_inputs[row][col] = False
clock.tick(30)
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()