0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

数独作ってみた #100日チャレンジに感化されて

Posted at

数独作ってみた

GW中に判定と難易度設定も追加したい!

タイトルなし.gif

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()

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?