Python で 2✕2の数字パズルをつくってみました。Geminiとの合作です。
tkinterライブラリーのボタンを使用しています。コードはこんな感じです。
# number-puzzle
# 2x2 数字パズル
# Version: 0.3.0
# シャッフル機能を追加
import tkinter as tk
from tkinter import messagebox
import random
class NumberPuzzle:
def __init__(self, master):
self.master = master
self.master.title("数字パズル 2x2")
# 内部状態の定義
self.goal = {1:1, 2:2, 3:3, 4:4} # ゴール状態
self.board = self.goal.copy()
self.empty = 4
# ボードの初期状態: 位置番号(1-4)をキー、表示数字を値とする
self.board = {1:1, 2:2, 3:3, 4:4}
# ピースの色: 空白はシアン
self.bg = {1: "white", 2: "white", 3: "white", 4: "cyan"}
self.fg = {1: "black", 2: "black", 3: "black", 4: "#00eeee"}
# 押下時のピースの色
self.abg = {1: "#eeeeee", 2: "#eeeeee", 3: "#eeeeee", 4: "#00eeee"}
self.afg = {1: "black", 2: "black", 3: "black", 4: "#00dddd"}
# 隣接リスト: 各位置に隣接する位置
self.adj = {1: [2, 3], 2: [1, 4], 3: [1, 4], 4: [2, 3]}
self.buttons = {}
self.create_widgets()
def create_widgets(self):
# パズル本体のグリッド
self.frame = tk.Frame(self.master)
self.frame.pack(padx=10, pady=10)
for i in range(1, 5):
row, col = (i - 1) // 2, (i - 1) % 2
btn = tk.Button(self.frame, text=str(self.board[i]), font=("Consolas", 40),
width=3, height=1,
command=lambda pos=i: self.click_tile(pos))
btn.grid(row=row, column=col, padx=2, pady=2)
self.buttons[i] = btn
# 操作用ボタン
self.shuffle_btn = tk.Button(self.master, text="スタート", font=("Arial", 12, "bold"),
command=self.shuffle_board, bg="#f0f0f0")
self.shuffle_btn.pack(fill=tk.X, padx=12, pady=5)
self.update_buttons()
def click_tile(self, pos, is_shuffling=False):
if self.empty in self.adj[pos]:
# ピースの移動(データ更新)
self.board[self.empty] = self.board[pos]
self.board[pos] = 4
self.empty = pos
if not is_shuffling:
self.update_buttons()
self.check_clear()
def shuffle_board(self):
# グラフ上のランダムウォークによるシャッフル(必ず解ける)
steps = 10
for _ in range(steps):
possible_moves = self.adj[self.empty]
move_to = random.choice(possible_moves)
self.click_tile(move_to, is_shuffling=True)
if self.board == self.goal:
self.shuffle_board() # ゴール状態なら再シャッフル
self.update_buttons()
def update_buttons(self):
for i in range(1, 5):
val = self.board[i]
# ボタンの外観を現在の状態(val)に合わせて更新
self.buttons[i].config(text=str(val),
bg=self.bg[val], fg=self.fg[val],
activebackground=self.abg[val],
activeforeground=self.afg[val])
def check_clear(self):
if self.board == self.goal:
messagebox.showinfo("数字パズル", "クリア!\n元の並びに戻りました。")
if __name__ == "__main__":
root = tk.Tk()
game = NumberPuzzle(root)
root.mainloop()
実行するとこんな感じ。[スタート]ボタンでシャッフルします。



“” への1件の返信