1
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?

pythonで数独アプリ作成-Part1.マスに数字を入力する-

Posted at

概要

pythonで数独アプリを作成することにしました。
一般的な数独アプリとは異なり、
マス目に何もない状態から既存のヒントの数字を埋めるところから始めることにします。

実行環境

・macOS:Ventura 13.2.1
・python:3.11.3

デザイン

スクリーンショット 2025-01-08 17.07.57.png

機能

①マス目を選択して右端の数字ボタンから選択できる
②マス目を選択して"Lock"ボタンを押下すると数字を削除できないようにする
 →既存のヒントの数字にすることができる

モジュール

今回はゲーム開発に特化したPyGameを使用しました。

ソースコード

sudoku.py
import pygame
from icecream import ic

# 画面の設定
SCREEN_WIDTH = 450
SCREEN_HEIGHT = 550  # 数字ボタン分高さを増やす
CELL_SIZE = 50
BUTTON_SIZE = 30
BUTTON_POS = (SCREEN_WIDTH + 50, 50)

# 色の設定
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (200, 200, 200)  # 選択中のマスをハイライトする色
RED = (255, 0, 0)

# フォントの設定
pygame.font.init()
FONT = pygame.font.SysFont('Arial', 36)

# 数独の盤面を格納する2次元配列
board = [[0 for _ in range(9)] for _ in range(9)]
locked_board = [[False for _ in range(9)] for _ in range(9)]  # 各マスのロック状態を管理する配列

# 選択中のマスの座標
selected_row = -1
selected_col = -1

# 数字削除ボタンの座標とサイズ
DELETE_BUTTON_POS = (SCREEN_WIDTH + 50, BUTTON_POS[1] + 9 * BUTTON_SIZE + 20)
DELETE_BUTTON_SIZE = BUTTON_SIZE

# ロックボタンの座標とサイズ
LOCK_BUTTON_POS = (SCREEN_WIDTH + 50, DELETE_BUTTON_POS[1] + BUTTON_SIZE + 20)
LOCK_BUTTON_SIZE = BUTTON_SIZE

# マス目を描画する関数
def draw_board():
    for x in range(0, SCREEN_WIDTH, CELL_SIZE):
        for y in range(0, 9 * CELL_SIZE, CELL_SIZE):  # yの範囲を9行分に変更
            pygame.draw.rect(screen, BLACK, (x, y, CELL_SIZE, CELL_SIZE), 1)

    # 太い線で3x3のブロックを区切る
    for x in range(0, SCREEN_WIDTH, CELL_SIZE * 3):
        pygame.draw.line(screen, BLACK, (x, 0), (x, SCREEN_HEIGHT), 3)
    for y in range(0, SCREEN_HEIGHT, CELL_SIZE * 3):
        pygame.draw.line(screen, BLACK, (0, y), (SCREEN_WIDTH, y), 3)

# 数字を描画する関数
def draw_number(row, col, num):
    text = FONT.render(str(num), True, BLACK)
    text_rect = text.get_rect(center=(col * CELL_SIZE + CELL_SIZE // 2, row * CELL_SIZE + CELL_SIZE // 2))
    screen.blit(text, text_rect)


# 数字ボタンを描画する関数
def draw_number_buttons():
    for i in range(1, 10):
        button_rect = pygame.Rect(BUTTON_POS[0], BUTTON_POS[1] + (i-1) * BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE)
        pygame.draw.rect(screen, BLACK, button_rect, 1)
        text = FONT.render(str(i), True, BLACK)
        text_rect = text.get_rect(center=button_rect.center)
        screen.blit(text, text_rect)

# 選択中のマスをハイライトする関数
def draw_selected_cell():
    if selected_row != -1 and selected_col != -1:
        pygame.draw.rect(screen, GRAY, (selected_col * CELL_SIZE, selected_row * CELL_SIZE, CELL_SIZE, CELL_SIZE), 2)

# 数字削除ボタンを描画する関数
def draw_delete_button():
    button_rect = pygame.Rect(DELETE_BUTTON_POS[0], DELETE_BUTTON_POS[1], DELETE_BUTTON_SIZE, DELETE_BUTTON_SIZE)
    pygame.draw.rect(screen, BLACK, button_rect, 1)
    text = FONT.render("X", True, BLACK)
    text_rect = text.get_rect(center=button_rect.center)
    screen.blit(text, text_rect)

# ロックボタンを描画する関数
def draw_lock_button():
    button_rect = pygame.Rect(LOCK_BUTTON_POS[0], LOCK_BUTTON_POS[1], LOCK_BUTTON_SIZE, LOCK_BUTTON_SIZE)
    pygame.draw.rect(screen, BLACK, button_rect, 1)
    text = FONT.render("Lock", True, BLACK)
    text_rect = text.get_rect(center=button_rect.center)
    screen.blit(text, text_rect)

# メインループ
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH + 100, 9 * CELL_SIZE + 50))  # 画面の高さを調整
pygame.display.set_caption("数独")

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            x, y = pygame.mouse.get_pos()
            # マスの選択
            if x < SCREEN_WIDTH and y < SCREEN_HEIGHT:
                selected_row = y // CELL_SIZE
                selected_col = x // CELL_SIZE
            # 数字ボタンのクリック
            elif BUTTON_POS[0] <= x <= BUTTON_POS[0] + BUTTON_SIZE and BUTTON_POS[1] <= y <= BUTTON_POS[1] + 9 * BUTTON_SIZE:
                for i in range(1, 10):
                    button_rect = pygame.Rect(BUTTON_POS[0], BUTTON_POS[1] + (i-1) * BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE)
                    if button_rect.collidepoint(x, y):
                        if not locked_board[selected_row][selected_col]:
                            board[selected_row][selected_col] = i
            # 数字削除かロックボタンのクリック
            else:
                # 数字削除ボタンのクリック
                delete_button_rect = pygame.Rect(DELETE_BUTTON_POS[0], DELETE_BUTTON_POS[1], DELETE_BUTTON_SIZE, DELETE_BUTTON_SIZE)
                if delete_button_rect.collidepoint(x, y):
                    if selected_row != -1 and selected_col != -1:
                        if not locked_board[selected_row][selected_col]:
                            board[selected_row][selected_col] = 0
                # ロックボタンのクリック
                lock_button_rect = pygame.Rect(LOCK_BUTTON_POS[0], LOCK_BUTTON_POS[1], LOCK_BUTTON_SIZE, LOCK_BUTTON_SIZE)
                if lock_button_rect.collidepoint(x, y):
                    if selected_row != -1 and selected_col != -1:
                        locked_board[selected_row][selected_col] = True
                        # ic(selected_row,selected_col,x,y)
                        # ic(selected_col * CELL_SIZE, selected_row * CELL_SIZE, CELL_SIZE, CELL_SIZE)
                        

    # 画面をクリア
    screen.fill(WHITE)

    # マス目を描画
    draw_board()

    # 数字を描画
    for i in range(9):
        for j in range(9):
            if board[i][j] != 0:
                draw_number(i, j, board[i][j])

            if locked_board[i][j] == True:
                # ロックボタンが押下されたマスをハイライト
                pygame.draw.rect(screen, RED, (j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE),2)

    
    draw_selected_cell()# 選択中のマスをハイライト
    draw_number_buttons()# 数字ボタンを描画
    draw_delete_button()  # 数字削除ボタンを描画
    draw_lock_button()  # ロックボタンを描画
    pygame.display.update()

pygame.quit()

1
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
1
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?