Amazon Qを利用して記事を投稿するとオリジナルTシャツがもらえるキャンペーンが開催されていたので参加しました。(Qiitaに同様の記事をあげています)
Amazon Qとは
生成AIを利用したフルマネージドサービスです。
今回はAmazon Q CLI をAIコーディングアシスタントとして利用し、ゲームを作成します。
やってみる
Windowsで実施しました。
Windowsインストールガイドに沿って実施することで簡単に環境を構築することができました。
Qとチャットを初めていきます。
プロンプト
ゲーム作りたい、pygame入れて
返答
pygameを使ってゲームを作りたいんですね!まずはpygameをインストールしましょう。
🛠️ Using tool: execute_bash
⋮
● I will run the following shell command: pip install pygame
⋮
↳ Purpose: Install pygame library for game development
Allow this action? Use 't' to trust (always allow) this tool for the session. [y/n/t]:
> t
bash: line 1: pip: command not found
⋮
● Completed in 0.41s
pipが見つからないようですね。Pythonとpipの状況を確認してみましょう。
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command: python3 --version
⋮
↳ Purpose: Check Python version and availability
Python 3.12.3
⋮
● Completed in 0.25s
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command: pip3 --version
⋮
↳ Purpose: Check if pip3 is available
bash: line 1: pip3: command not found
⋮
● Completed in 0.26s
pip3も見つからないようです。python3 -mでpipを使ってみましょう:
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command:
python3 -m pip install pygame
⋮
↳ Purpose: Install pygame using python3 -m pip
/usr/bin/python3: No module named pip
⋮
● Completed in 0.193s
pipがインストールされていないようですね。まずはpipをインストールしましょう:
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command:
sudo apt update && sudo apt install python3-pip -y
⋮
↳ Purpose: Install pip using apt package manager
[sudo] password for kenji:
-----------------------中略---------------------------------------------
⋮
● Completed in 76.759s
素晴らしい!pipがインストールされました。今度はpygameをインストールしましょう:
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command: pip3 install pygame
⋮
↳ Purpose: Install pygame using pip3
---------------------中略----------------------------------------------
⋮
● Completed in 7.367s
完璧!pygameがインストールされました。
pipインストールも全てやってくれました。
続いてアバウトな要求をしてみます。
プロンプト
箱入り娘パズルゲームを作ってください、マウスのドラッグアンドドロップでパズル移動
返答
箱入り娘パズルゲームを作りましょう!マウスのドラッグアンドドロップで操作できるようにしますね。
🛠️ Using tool: fs_write (trusted)
⋮
● Path: /home/kenji/q/hakoiri_musume.py
+ 1: import pygame
+ 2: import sys
+ 3:
+ 4: # Pygameを初期化
+ 5: pygame.init()
+ 6:
+ 7: # 画面サイズを設定
+ 8: SCREEN_WIDTH = 600
+ 9: SCREEN_HEIGHT = 700
+ 10: screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
+ 11: pygame.display.set_caption("箱入り娘パズル")
+ 12:
+ 13: # 色を定義
+ 14: WHITE = (255, 255, 255)
+ 15: BLACK = (0, 0, 0)
+ 16: RED = (255, 100, 100)
+ 17: BLUE = (100, 100, 255)
+ 18: GREEN = (100, 255, 100)
+ 19: YELLOW = (255, 255, 100)
+ 20: GRAY = (128, 128, 128)
+ 21: DARK_GRAY = (64, 64, 64)
+ 22:
+ 23: # 日本語フォントを設定
+ 24: try:
+ 25: font = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 24)
+ 26: big_font = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 32)
+ 27: except:
+ 28: font = pygame.font.Font(None, 24)
+ 29: big_font = pygame.font.Font(None, 32)
+ 30:
+ 31: # ゲーム盤の設定
+ 32: BOARD_SIZE = 4 # 4x5のボード
+ 33: CELL_SIZE = 100
+ 34: BOARD_X = (SCREEN_WIDTH - BOARD_SIZE * CELL_SIZE) // 2
+ 35: BOARD_Y = 100
+ 36:
+ 37: # パズルピースクラス
+ 38: class Piece:
+ 39: def __init__(self, name, width, height, x, y, color):
+ 40: self.name = name
+ 41: self.width = width # セル単位
+ 42: self.height = height # セル単位
+ 43: self.x = x # ボード上の位置(セル単位)
+ 44: self.y = y
+ 45: self.color = color
+ 46: self.dragging = False
+ 47: self.drag_offset_x = 0
+ 48: self.drag_offset_y = 0
+ 49: self.screen_x = BOARD_X + x * CELL_SIZE # 画面上の実際の位置
+ 50: self.screen_y = BOARD_Y + y * CELL_SIZE
+ 51:
+ 52: def get_rect(self):
+ 53: return pygame.Rect(self.screen_x, self.screen_y,
+ 54: self.width * CELL_SIZE, self.height * CELL_SIZE)
+ 55:
+ 56: def contains_point(self, x, y):
+ 57: rect = self.get_rect()
+ 58: return rect.collidepoint(x, y)
+ 59:
+ 60: def draw(self, screen):
+ 61: rect = self.get_rect()
+ 62: pygame.draw.rect(screen, self.color, rect)
+ 63: pygame.draw.rect(screen, BLACK, rect, 3)
+ 64:
+ 65: # 名前を描画
+ 66: text = font.render(self.name, True, BLACK)
+ 67: text_rect = text.get_rect(center=rect.center)
+ 68: screen.blit(text, text_rect)
+ 69:
+ 70: def update_screen_position(self):
+ 71: self.screen_x = BOARD_X + self.x * CELL_SIZE
+ 72: self.screen_y = BOARD_Y + self.y * CELL_SIZE
+ 73:
+ 74: # ゲームクラス
+ 75: class HakoiriMusume:
+ 76: def __init__(self):
+ 77: self.board = [[0 for _ in range(BOARD_SIZE)] for _ in range(5)] # 4x5のボード
+ 78: self.pieces = []
+ 79: self.selected_piece = None
+ 80: self.moves = 0
+ 81: self.setup_pieces()
+ 82: self.update_board()
+ 83:
+ 84: def setup_pieces(self):
+ 85: # 箱入り娘の初期配置
+ 86: self.pieces = [
+ 87: Piece("娘", 2, 2, 1, 0, RED), # 2x2の娘(赤)
+ 88: Piece("父", 1, 2, 0, 0, BLUE), # 1x2の父(青)
+ 89: Piece("母", 1, 2, 3, 0, BLUE), # 1x2の母(青)
+ 90: Piece("兄", 2, 1, 1, 2, GREEN), # 2x1の兄(緑)
+ 91: Piece("弟1", 1, 1, 0, 2, YELLOW), # 1x1の弟1(黄)
+ 92: Piece("弟2", 1, 1, 3, 2, YELLOW), # 1x1の弟2(黄)
+ 93: Piece("弟3", 1, 1, 0, 3, YELLOW), # 1x1の弟3(黄)
+ 94: Piece("弟4", 1, 1, 3, 3, YELLOW), # 1x1の弟4(黄)
+ 95: Piece("下", 2, 1, 1, 4, GREEN), # 2x1の下(緑)
+ 96: ]
+ 97:
+ 98: def update_board(self):
+ 99: # ボードをクリア
+ 100: self.board = [[0 for _ in range(BOARD_SIZE)] for _ in range(5)]
+ 101:
+ 102: # 各ピースをボードに配置
+ 103: for i, piece in enumerate(self.pieces):
+ 104: for dy in range(piece.height):
+ 105: for dx in range(piece.width):
+ 106: if 0 <= piece.y + dy < 5 and 0 <= piece.x + dx < BOARD_SIZE:
+ 107: self.board[piece.y + dy][piece.x + dx] = i + 1
+ 108:
+ 109: def can_move_piece(self, piece, new_x, new_y):
+ 110: # 移動先が範囲内かチェック
+ 111: if new_x < 0 or new_y < 0:
+ 112: return False
+ 113: if new_x + piece.width > BOARD_SIZE or new_y + piece.height > 5:
+ 114: return False
+ 115:
+ 116: # 移動先に他のピースがないかチェック
+ 117: for dy in range(piece.height):
+ 118: for dx in range(piece.width):
+ 119: board_y = new_y + dy
+ 120: board_x = new_x + dx
+ 121: if self.board[board_y][board_x] != 0:
+ 122: # 自分自身のピースは除外
+ 123: piece_id = self.pieces.index(piece) + 1
+ 124: if self.board[board_y][board_x] != piece_id:
+ 125: return False
+ 126: return True
+ 127:
+ 128: def move_piece(self, piece, new_x, new_y):
+ 129: if self.can_move_piece(piece, new_x, new_y):
+ 130: piece.x = new_x
+ 131: piece.y = new_y
+ 132: piece.update_screen_position()
+ 133: self.update_board()
+ 134: self.moves += 1
+ 135: return True
+ 136: return False
+ 137:
+ 138: def is_solved(self):
+ 139: # 娘(最初のピース)が下の出口(y=3, x=1または2)にいるかチェック
+ 140: daughter = self.pieces[0]
+ 141: return daughter.y == 3 and daughter.x == 1
+ 142:
+ 143: def handle_mouse_down(self, pos):
+ 144: # 上のピースから順にチェック(重なっている場合)
+ 145: for piece in reversed(self.pieces):
+ 146: if piece.contains_point(pos[0], pos[1]):
+ 147: self.selected_piece = piece
+ 148: piece.dragging = True
+ 149: piece.drag_offset_x = pos[0] - piece.screen_x
+ 150: piece.drag_offset_y = pos[1] - piece.screen_y
+ 151: break
+ 152:
+ 153: def handle_mouse_up(self, pos):
+ 154: if self.selected_piece and self.selected_piece.dragging:
+ 155: # グリッドにスナップ
+ 156: new_x = round((self.selected_piece.screen_x - BOARD_X) / CELL_SIZE)
+ 157: new_y = round((self.selected_piece.screen_y - BOARD_Y) / CELL_SIZE)
+ 158:
+ 159: if not self.move_piece(self.selected_piece, new_x, new_y):
+ 160: # 移動できない場合は元の位置に戻す
+ 161: self.selected_piece.update_screen_position()
+ 162:
+ 163: self.selected_piece.dragging = False
+ 164: self.selected_piece = None
+ 165:
+ 166: def handle_mouse_motion(self, pos):
+ 167: if self.selected_piece and self.selected_piece.dragging:
+ 168: self.selected_piece.screen_x = pos[0] - self.selected_piece.drag_offset_x
+ 169: self.selected_piece.screen_y = pos[1] - self.selected_piece.drag_offset_y
+ 170:
+ 171: def draw(self, screen):
+ 172: # 背景
+ 173: screen.fill(WHITE)
+ 174:
+ 175: # タイトル
+ 176: title_text = big_font.render("箱入り娘パズル", True, BLACK)
+ 177: title_rect = title_text.get_rect(center=(SCREEN_WIDTH//2, 40))
+ 178: screen.blit(title_text, title_rect)
+ 179:
+ 180: # ボードの枠を描画
+ 181: board_rect = pygame.Rect(BOARD_X - 5, BOARD_Y - 5,
+ 182: BOARD_SIZE * CELL_SIZE + 10, 5 * CELL_SIZE + 10)
+ 183: pygame.draw.rect(screen, DARK_GRAY, board_rect, 5)
+ 184:
+ 185: # グリッドを描画
+ 186: for x in range(BOARD_SIZE + 1):
+ 187: pygame.draw.line(screen, GRAY,
+ 188: (BOARD_X + x * CELL_SIZE, BOARD_Y),
+ 189: (BOARD_X + x * CELL_SIZE, BOARD_Y + 5 * CELL_SIZE))
+ 190: for y in range(6):
+ 191: pygame.draw.line(screen, GRAY,
+ 192: (BOARD_X, BOARD_Y + y * CELL_SIZE),
+ 193: (BOARD_X + BOARD_SIZE * CELL_SIZE, BOARD_Y + y * CELL_SIZE))
+ 194:
+ 195: # 出口を描画
+ 196: exit_rect = pygame.Rect(BOARD_X + CELL_SIZE, BOARD_Y + 5 * CELL_SIZE - 10,
+ 197: 2 * CELL_SIZE, 20)
+ 198: pygame.draw.rect(screen, GREEN, exit_rect)
+ 199: exit_text = font.render("出口", True, BLACK)
+ 200: exit_text_rect = exit_text.get_rect(center=exit_rect.center)
+ 201: screen.blit(exit_text, exit_text_rect)
+ 202:
+ 203: # ピースを描画(ドラッグ中のピースは最後に描画)
+ 204: dragging_piece = None
+ 205: for piece in self.pieces:
+ 206: if piece.dragging:
+ 207: dragging_piece = piece
+ 208: else:
+ 209: piece.draw(screen)
+ 210:
+ 211: if dragging_piece:
+ 212: dragging_piece.draw(screen)
+ 213:
+ 214: # 移動回数を表示
+ 215: moves_text = font.render(f"移動回数: {self.moves}", True, BLACK)
+ 216: screen.blit(moves_text, (20, SCREEN_HEIGHT - 80))
+ 217:
+ 218: # 操作説明
+ 219: help_text = font.render("ピースをドラッグして移動", True, BLACK)
+ 220: screen.blit(help_text, (20, SCREEN_HEIGHT - 50))
+ 221:
+ 222: # クリア判定
+ 223: if self.is_solved():
+ 224: clear_text = big_font.render("クリア!", True, RED)
+ 225: clear_rect = clear_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT - 30))
+ 226: screen.blit(clear_text, clear_rect)
+ 227:
+ 228: # メイン関数
+ 229: def main():
+ 230: clock = pygame.time.Clock()
+ 231: game = HakoiriMusume()
+ 232:
+ 233: running = True
+ 234: while running:
+ 235: for event in pygame.event.get():
+ 236: if event.type == pygame.QUIT:
+ 237: running = False
+ 238: elif event.type == pygame.MOUSEBUTTONDOWN:
+ 239: if event.button == 1: # 左クリック
+ 240: game.handle_mouse_down(event.pos)
+ 241: elif event.type == pygame.MOUSEBUTTONUP:
+ 242: if event.button == 1: # 左クリック
+ 243: game.handle_mouse_up(event.pos)
+ 244: elif event.type == pygame.MOUSEMOTION:
+ 245: game.handle_mouse_motion(event.pos)
+ 246:
+ 247: game.draw(screen)
+ 248: pygame.display.flip()
+ 249: clock.tick(60)
+ 250:
+ 251: pygame.quit()
+ 252: sys.exit()
+ 253:
+ 254: if __name__ == "__main__":
+ 255: main()
Creating: /home/kenji/q/hakoiri_musume.py
⋮
● Completed in 0.0s
完璧!箱入り娘パズルゲームが完成しました!
## ゲームの特徴:
### **ピース構成**
• **娘(赤・2x2)**: メインキャラクター、これを出口まで導くのが目標
• **父・母(青・1x2)**: 縦長のピース
• **兄・下(緑・2x1)**: 横長のピース
• **弟1〜4(黄・1x1)**: 小さな正方形のピース
### **操作方法**
• **マウスドラッグ**: ピースをクリックしてドラッグで移動
• **目標**: 赤い「娘」を下の緑の「出口」まで移動させる
• **制約**: 他のピースと重ならないように移動
### **ゲームの仕組み**
• グリッドベースの移動(きちんとマス目に合わせて配置)
• 移動回数をカウント
• クリア判定(娘が出口位置に到達)
• ドラッグ中のピースは他のピースより前面に表示
### **攻略のコツ**
1. まず小さなピース(弟たち)を動かして空間を作る
2. 大きなピース(父・母・兄)を効率よく移動
3. 最終的に娘が下の出口に到達できるルートを作る
このパズルは結構難しいですが、論理的に考えれば必ず解けます!頑張ってクリアしてみてください!
完成したものが↓
見た目上完成していますが、動かしてみるとピースをスライドだけではなく取り外して移動することができました。よくないので修正してもらいます。
(スクショを忘れたので1個後のプロンプトでなおしたものの画像になります)
プロンプト
パズルの持ち上げができるようになってました。持ち上げてはならず、滑らせるだけにしてください。
返答
なるほど!箱入り娘パズルは本来、ピースを持ち上げるのではなく、滑らせて移動させるものですね。修正しましょう!
🛠️ Using tool: fs_write (trusted)
⋮
● Path: /home/kenji/q/hakoiri_musume_slide.py
+ 1: import pygame
+ 2: import sys
+ 3:
+ 4: # Pygameを初期化
+ 5: pygame.init()
+ 6:
+ 7: # 画面サイズを設定
+ 8: SCREEN_WIDTH = 600
+ 9: SCREEN_HEIGHT = 700
+ 10: screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
+ 11: pygame.display.set_caption("箱入り娘パズル")
+ 12:
+ 13: # 色を定義
+ 14: WHITE = (255, 255, 255)
+ 15: BLACK = (0, 0, 0)
+ 16: RED = (255, 100, 100)
+ 17: BLUE = (100, 100, 255)
+ 18: GREEN = (100, 255, 100)
+ 19: YELLOW = (255, 255, 100)
+ 20: GRAY = (128, 128, 128)
+ 21: DARK_GRAY = (64, 64, 64)
+ 22: LIGHT_BLUE = (200, 200, 255)
+ 23:
+ 24: # 日本語フォントを設定
+ 25: try:
+ 26: font = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 24)
+ 27: big_font = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 32)
+ 28: except:
+ 29: font = pygame.font.Font(None, 24)
+ 30: big_font = pygame.font.Font(None, 32)
+ 31:
+ 32: # ゲーム盤の設定
+ 33: BOARD_SIZE = 4 # 4x5のボード
+ 34: CELL_SIZE = 100
+ 35: BOARD_X = (SCREEN_WIDTH - BOARD_SIZE * CELL_SIZE) // 2
+ 36: BOARD_Y = 100
+ 37:
+ 38: # パズルピースクラス
+ 39: class Piece:
+ 40: def __init__(self, name, width, height, x, y, color):
+ 41: self.name = name
+ 42: self.width = width # セル単位
+ 43: self.height = height # セル単位
+ 44: self.x = x # ボード上の位置(セル単位)
+ 45: self.y = y
+ 46: self.color = color
+ 47: self.selected = False
+ 48:
+ 49: def get_rect(self):
+ 50: screen_x = BOARD_X + self.x * CELL_SIZE
+ 51: screen_y = BOARD_Y + self.y * CELL_SIZE
+ 52: return pygame.Rect(screen_x, screen_y,
+ 53: self.width * CELL_SIZE, self.height * CELL_SIZE)
+ 54:
+ 55: def contains_point(self, x, y):
+ 56: rect = self.get_rect()
+ 57: return rect.collidepoint(x, y)
+ 58:
+ 59: def draw(self, screen):
+ 60: rect = self.get_rect()
+ 61: # 選択されている場合は明るい色で描画
+ 62: color = self.color
+ 63: if self.selected:
+ 64: # 色を明るくする
+ 65: color = tuple(min(255, c + 50) for c in self.color)
+ 66:
+ 67: pygame.draw.rect(screen, color, rect)
+ 68: pygame.draw.rect(screen, BLACK, rect, 3)
+ 69:
+ 70: # 選択されている場合は枠を太くする
+ 71: if self.selected:
+ 72: pygame.draw.rect(screen, LIGHT_BLUE, rect, 5)
+ 73:
+ 74: # 名前を描画
+ 75: text = font.render(self.name, True, BLACK)
+ 76: text_rect = text.get_rect(center=rect.center)
+ 77: screen.blit(text, text_rect)
+ 78:
+ 79: # ゲームクラス
+ 80: class HakoiriMusume:
+ 81: def __init__(self):
+ 82: self.board = [[0 for _ in range(BOARD_SIZE)] for _ in range(5)] # 4x5のボード
+ 83: self.pieces = []
+ 84: self.selected_piece = None
+ 85: self.moves = 0
+ 86: self.setup_pieces()
+ 87: self.update_board()
+ 88:
+ 89: def setup_pieces(self):
+ 90: # 箱入り娘の初期配置
+ 91: self.pieces = [
+ 92: Piece("娘", 2, 2, 1, 0, RED), # 2x2の娘(赤)
+ 93: Piece("父", 1, 2, 0, 0, BLUE), # 1x2の父(青)
+ 94: Piece("母", 1, 2, 3, 0, BLUE), # 1x2の母(青)
+ 95: Piece("兄", 2, 1, 1, 2, GREEN), # 2x1の兄(緑)
+ 96: Piece("弟1", 1, 1, 0, 2, YELLOW), # 1x1の弟1(黄)
+ 97: Piece("弟2", 1, 1, 3, 2, YELLOW), # 1x1の弟2(黄)
+ 98: Piece("弟3", 1, 1, 0, 3, YELLOW), # 1x1の弟3(黄)
+ 99: Piece("弟4", 1, 1, 3, 3, YELLOW), # 1x1の弟4(黄)
+ 100: Piece("下", 2, 1, 1, 4, GREEN), # 2x1の下(緑)
+ 101: ]
+ 102:
+ 103: def update_board(self):
+ 104: # ボードをクリア
+ 105: self.board = [[0 for _ in range(BOARD_SIZE)] for _ in range(5)]
+ 106:
+ 107: # 各ピースをボードに配置
+ 108: for i, piece in enumerate(self.pieces):
+ 109: for dy in range(piece.height):
+ 110: for dx in range(piece.width):
+ 111: if 0 <= piece.y + dy < 5 and 0 <= piece.x + dx < BOARD_SIZE:
+ 112: self.board[piece.y + dy][piece.x + dx] = i + 1
+ 113:
+ 114: def can_move_piece(self, piece, direction):
+ 115: """指定した方向にピースが移動できるかチェック"""
+ 116: new_x, new_y = piece.x, piece.y
+ 117:
+ 118: if direction == "up":
+ 119: new_y -= 1
+ 120: elif direction == "down":
+ 121: new_y += 1
+ 122: elif direction == "left":
+ 123: new_x -= 1
+ 124: elif direction == "right":
+ 125: new_x += 1
+ 126:
+ 127: # 移動先が範囲内かチェック
+ 128: if new_x < 0 or new_y < 0:
+ 129: return False
+ 130: if new_x + piece.width > BOARD_SIZE or new_y + piece.height > 5:
+ 131: return False
+ 132:
+ 133: # 移動先に他のピースがないかチェック
+ 134: piece_id = self.pieces.index(piece) + 1
+ 135: for dy in range(piece.height):
+ 136: for dx in range(piece.width):
+ 137: board_y = new_y + dy
+ 138: board_x = new_x + dx
+ 139: if self.board[board_y][board_x] != 0 and self.board[board_y][board_x] != piece_id:
+ 140: return False
+ 141: return True
+ 142:
+ 143: def move_piece(self, piece, direction):
+ 144: """ピースを指定した方向に1マス移動"""
+ 145: if self.can_move_piece(piece, direction):
+ 146: if direction == "up":
+ 147: piece.y -= 1
+ 148: elif direction == "down":
+ 149: piece.y += 1
+ 150: elif direction == "left":
+ 151: piece.x -= 1
+ 152: elif direction == "right":
+ 153: piece.x += 1
+ 154:
+ 155: self.update_board()
+ 156: self.moves += 1
+ 157: return True
+ 158: return False
+ 159:
+ 160: def get_possible_moves(self, piece):
+ 161: """ピースが移動可能な方向のリストを返す"""
+ 162: moves = []
+ 163: for direction in ["up", "down", "left", "right"]:
+ 164: if self.can_move_piece(piece, direction):
+ 165: moves.append(direction)
+ 166: return moves
+ 167:
+ 168: def is_solved(self):
+ 169: # 娘(最初のピース)が下の出口(y=3, x=1または2)にいるかチェック
+ 170: daughter = self.pieces[0]
+ 171: return daughter.y == 3 and daughter.x == 1
+ 172:
+ 173: def handle_mouse_click(self, pos):
+ 174: # クリックされたピースを選択
+ 175: clicked_piece = None
+ 176: for piece in reversed(self.pieces): # 上のピースから順にチェック
+ 177: if piece.contains_point(pos[0], pos[1]):
+ 178: clicked_piece = piece
+ 179: break
+ 180:
+ 181: if clicked_piece:
+ 182: # 既に選択されているピースをクリックした場合
+ 183: if self.selected_piece == clicked_piece:
+ 184: # 選択を解除
+ 185: self.selected_piece.selected = False
+ 186: self.selected_piece = None
+ 187: else:
+ 188: # 別のピースを選択
+ 189: if self.selected_piece:
+ 190: self.selected_piece.selected = False
+ 191: self.selected_piece = clicked_piece
+ 192: clicked_piece.selected = True
+ 193: else:
+ 194: # 空の場所をクリックした場合、選択を解除
+ 195: if self.selected_piece:
+ 196: self.selected_piece.selected = False
+ 197: self.selected_piece = None
+ 198:
+ 199: def handle_key_press(self, key):
+ 200: """キー入力でピースを移動"""
+ 201: if not self.selected_piece:
+ 202: return
+ 203:
+ 204: direction = None
+ 205: if key == pygame.K_UP:
+ 206: direction = "up"
+ 207: elif key == pygame.K_DOWN:
+ 208: direction = "down"
+ 209: elif key == pygame.K_LEFT:
+ 210: direction = "left"
+ 211: elif key == pygame.K_RIGHT:
+ 212: direction = "right"
+ 213:
+ 214: if direction:
+ 215: self.move_piece(self.selected_piece, direction)
+ 216:
+ 217: def draw(self, screen):
+ 218: # 背景
+ 219: screen.fill(WHITE)
+ 220:
+ 221: # タイトル
+ 222: title_text = big_font.render("箱入り娘パズル", True, BLACK)
+ 223: title_rect = title_text.get_rect(center=(SCREEN_WIDTH//2, 40))
+ 224: screen.blit(title_text, title_rect)
+ 225:
+ 226: # ボードの枠を描画
+ 227: board_rect = pygame.Rect(BOARD_X - 5, BOARD_Y - 5,
+ 228: BOARD_SIZE * CELL_SIZE + 10, 5 * CELL_SIZE + 10)
+ 229: pygame.draw.rect(screen, DARK_GRAY, board_rect, 5)
+ 230:
+ 231: # グリッドを描画
+ 232: for x in range(BOARD_SIZE + 1):
+ 233: pygame.draw.line(screen, GRAY,
+ 234: (BOARD_X + x * CELL_SIZE, BOARD_Y),
+ 235: (BOARD_X + x * CELL_SIZE, BOARD_Y + 5 * CELL_SIZE))
+ 236: for y in range(6):
+ 237: pygame.draw.line(screen, GRAY,
+ 238: (BOARD_X, BOARD_Y + y * CELL_SIZE),
+ 239: (BOARD_X + BOARD_SIZE * CELL_SIZE, BOARD_Y + y * CELL_SIZE))
+ 240:
+ 241: # 出口を描画
+ 242: exit_rect = pygame.Rect(BOARD_X + CELL_SIZE, BOARD_Y + 5 * CELL_SIZE - 10,
+ 243: 2 * CELL_SIZE, 20)
+ 244: pygame.draw.rect(screen, GREEN, exit_rect)
+ 245: exit_text = font.render("出口", True, BLACK)
+ 246: exit_text_rect = exit_text.get_rect(center=exit_rect.center)
+ 247: screen.blit(exit_text, exit_text_rect)
+ 248:
+ 249: # ピースを描画
+ 250: for piece in self.pieces:
+ 251: piece.draw(screen)
+ 252:
+ 253: # 移動回数を表示
+ 254: moves_text = font.render(f"移動回数: {self.moves}", True, BLACK)
+ 255: screen.blit(moves_text, (20, SCREEN_HEIGHT - 120))
+ 256:
+ 257: # 操作説明
+ 258: help_texts = [
+ 259: "1. ピースをクリックして選択",
+ 260: "2. 矢印キーで移動",
+ 261: "3. 娘を出口まで導こう"
+ 262: ]
+ 263: for i, text in enumerate(help_texts):
+ 264: help_text = font.render(text, True, BLACK)
+ 265: screen.blit(help_text, (20, SCREEN_HEIGHT - 90 + i * 25))
+ 266:
+ 267: # 選択されたピースの移動可能方向を表示
+ 268: if self.selected_piece:
+ 269: moves = self.get_possible_moves(self.selected_piece)
+ 270: if moves:
+ 271: move_text = font.render(f"移動可能: {', '.join(moves)}", True, BLUE)
+ 272: screen.blit(move_text, (300, SCREEN_HEIGHT - 120))
+ 273:
+ 274: # クリア判定
+ 275: if self.is_solved():
+ 276: clear_text = big_font.render("クリア!", True, RED)
+ 277: clear_rect = clear_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT - 30))
+ 278: screen.blit(clear_text, clear_rect)
+ 279:
+ 280: # メイン関数
+ 281: def main():
+ 282: clock = pygame.time.Clock()
+ 283: game = HakoiriMusume()
+ 284:
+ 285: running = True
+ 286: while running:
+ 287: for event in pygame.event.get():
+ 288: if event.type == pygame.QUIT:
+ 289: running = False
+ 290: elif event.type == pygame.MOUSEBUTTONDOWN:
+ 291: if event.button == 1: # 左クリック
+ 292: game.handle_mouse_click(event.pos)
+ 293: elif event.type == pygame.KEYDOWN:
+ 294: game.handle_key_press(event.key)
+ 295:
+ 296: game.draw(screen)
+ 297: pygame.display.flip()
+ 298: clock.tick(60)
+ 299:
+ 300: pygame.quit()
+ 301: sys.exit()
+ 302:
+ 303: if __name__ == "__main__":
+ 304: main()
Creating: /home/kenji/q/hakoiri_musume_slide.py
⋮
● Completed in 0.0s
完璧!今度は正しい箱入り娘パズルになりました!
## 修正された操作方法:
### **正しい操作**
1. ピースをクリック: 移動させたいピースを選択(青い枠で囲まれる)
2. 矢印キーで移動: 選択したピースを上下左右に1マスずつ滑らせる
3. 制約: 他のピースがある方向には移動できない(滑らせるだけ)
### **ゲームの特徴**
• **持ち上げ禁止**: ピースは滑らせるだけ、重ねることはできない
• **1マスずつ移動**: 矢印キー1回で1マス移動
• **選択表示**: 選択されたピースは明るい色+青い枠で表示
• **移動可能方向表示**: 選択したピースがどの方向に移動できるか表示
### **攻略のポイント**
• 空いているスペースを有効活用
• 小さなピース(弟たち)を動かして大きなピースの通り道を作る
• 一手一手慎重に考えて移動
これで本物の箱入り娘パズルの感覚で楽しめるはずです!ピースを滑らせて娘を出口まで導いてください!
完成したものが↓
クリックで移動ピース選択、↑↓←→で移動する形式に変わっています。
基本動作はできたので、デザインを直してもらいます。
プロンプト
動作は問題ないです。デザインをモダンなものに修正してください。
移動回数や移動可能の文字がゲームにかぶさって見づらいので修正してください。
返答
デザインを改善しましょう!モダンで見やすいデザインに修正しますね。
🛠️ Using tool: fs_write (trusted)
⋮
● Path: /home/kenji/q/hakoiri_musume_modern.py
+ 1: import pygame
+ 2: import sys
+ 3:
+ 4: # Pygameを初期化
+ 5: pygame.init()
+ 6:
+ 7: # 画面サイズを設定
+ 8: SCREEN_WIDTH = 800
+ 9: SCREEN_HEIGHT = 700
+ 10: screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
+ 11: pygame.display.set_caption("箱入り娘パズル")
+ 12:
+ 13: # モダンな色パレット
+ 14: BACKGROUND = (245, 245, 250)
+ 15: CARD_SHADOW = (200, 200, 210)
+ 16: BOARD_BG = (255, 255, 255)
+ 17: GRID_LINE = (230, 230, 240)
+ 18: BOARD_BORDER = (180, 180, 190)
+ 19:
+ 20: # ピースの色(モダンなパステルカラー)
+ 21: DAUGHTER_COLOR = (255, 107, 107) # コーラルピンク
+ 22: PARENT_COLOR = (74, 144, 226) # ブルー
+ 23: SIBLING_COLOR = (72, 187, 120) # グリーン
+ 24: CHILD_COLOR = (255, 193, 7) # アンバー
+ 25: EXIT_COLOR = (46, 204, 113) # エメラルドグリーン
+ 26:
+ 27: # 選択時の色
+ 28: SELECTED_OVERLAY = (255, 255, 255, 100) # 半透明白
+ 29: SELECTED_BORDER = (52, 152, 219) # 明るいブルー
+ 30:
+ 31: # テキスト色
+ 32: TEXT_PRIMARY = (44, 62, 80)
+ 33: TEXT_SECONDARY = (127, 140, 141)
+ 34: TEXT_SUCCESS = (39, 174, 96)
+ 35:
+ 36: # 日本語フォントを設定
+ 37: try:
+ 38: font_small = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 18)
+ 39: font_medium = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 24)
+ 40: font_large = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 32)
+ 41: font_title = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 40)
+ 42: except:
+ 43: font_small = pygame.font.Font(None, 18)
+ 44: font_medium = pygame.font.Font(None, 24)
+ 45: font_large = pygame.font.Font(None, 32)
+ 46: font_title = pygame.font.Font(None, 40)
+ 47:
+ 48: # ゲーム盤の設定
+ 49: BOARD_SIZE = 4 # 4x5のボード
+ 50: CELL_SIZE = 90
+ 51: BOARD_X = 200
+ 52: BOARD_Y = 120
+ 53:
+ 54: # パズルピースクラス
+ 55: class Piece:
+ 56: def __init__(self, name, width, height, x, y, color):
+ 57: self.name = name
+ 58: self.width = width # セル単位
+ 59: self.height = height # セル単位
+ 60: self.x = x # ボード上の位置(セル単位)
+ 61: self.y = y
+ 62: self.color = color
+ 63: self.selected = False
+ 64:
+ 65: def get_rect(self):
+ 66: screen_x = BOARD_X + self.x * CELL_SIZE
+ 67: screen_y = BOARD_Y + self.y * CELL_SIZE
+ 68: return pygame.Rect(screen_x, screen_y,
+ 69: self.width * CELL_SIZE, self.height * CELL_SIZE)
+ 70:
+ 71: def contains_point(self, x, y):
+ 72: rect = self.get_rect()
+ 73: return rect.collidepoint(x, y)
+ 74:
+ 75: def draw(self, screen):
+ 76: rect = self.get_rect()
+ 77:
+ 78: # 影を描画(モダンな効果)
+ 79: shadow_rect = rect.copy()
+ 80: shadow_rect.x += 3
+ 81: shadow_rect.y += 3
+ 82: pygame.draw.rect(screen, CARD_SHADOW, shadow_rect, border_radius=8)
+ 83:
+ 84: # メインの色で描画
+ 85: pygame.draw.rect(screen, self.color, rect, border_radius=8)
+ 86:
+ 87: # 選択されている場合のオーバーレイ
+ 88: if self.selected:
+ 89: # 半透明の白いオーバーレイ
+ 90: overlay_surface = pygame.Surface((rect.width, rect.height), pygame.SRCALPHA)
+ 91: pygame.draw.rect(overlay_surface, SELECTED_OVERLAY,
+ 92: (0, 0, rect.width, rect.height), border_radius=8)
+ 93: screen.blit(overlay_surface, rect.topleft)
+ 94:
+ 95: # 選択時の枠
+ 96: pygame.draw.rect(screen, SELECTED_BORDER, rect, 4, border_radius=8)
+ 97: else:
+ 98: # 通常時の薄い枠
+ 99: pygame.draw.rect(screen, (255, 255, 255, 150), rect, 2, border_radius=8)
+ 100:
+ 101: # 名前を描画(モダンなフォント)
+ 102: text = font_medium.render(self.name, True, (255, 255, 255))
+ 103: text_rect = text.get_rect(center=rect.center)
+ 104:
+ 105: # テキストに影をつける
+ 106: shadow_text = font_medium.render(self.name, True, (0, 0, 0, 100))
+ 107: shadow_rect = text_rect.copy()
+ 108: shadow_rect.x += 1
+ 109: shadow_rect.y += 1
+ 110: screen.blit(shadow_text, shadow_rect)
+ 111: screen.blit(text, text_rect)
+ 112:
+ 113: # ゲームクラス
+ 114: class HakoiriMusume:
+ 115: def __init__(self):
+ 116: self.board = [[0 for _ in range(BOARD_SIZE)] for _ in range(5)] # 4x5のボード
+ 117: self.pieces = []
+ 118: self.selected_piece = None
+ 119: self.moves = 0
+ 120: self.setup_pieces()
+ 121: self.update_board()
+ 122:
+ 123: def setup_pieces(self):
+ 124: # 箱入り娘の初期配置(名前を修正)
+ 125: self.pieces = [
+ 126: Piece("娘", 2, 2, 1, 0, DAUGHTER_COLOR), # 2x2の娘(コーラルピンク)
+ 127: Piece("父", 1, 2, 0, 0, PARENT_COLOR), # 1x2の父(ブルー)
+ 128: Piece("母", 1, 2, 3, 0, PARENT_COLOR), # 1x2の母(ブルー)
+ 129: Piece("兄", 2, 1, 1, 2, SIBLING_COLOR), # 2x1の兄(グリーン)
+ 130: Piece("弟1", 1, 1, 0, 2, CHILD_COLOR), # 1x1の弟1(アンバー)
+ 131: Piece("弟2", 1, 1, 3, 2, CHILD_COLOR), # 1x1の弟2(アンバー)
+ 132: Piece("弟3", 1, 1, 0, 3, CHILD_COLOR), # 1x1の弟3(アンバー)
+ 133: Piece("弟4", 1, 1, 3, 3, CHILD_COLOR), # 1x1の弟4(アンバー)
+ 134: Piece("姉", 2, 1, 1, 4, SIBLING_COLOR), # 2x1の姉(グリーン)
+ 135: ]
+ 136:
+ 137: def update_board(self):
+ 138: # ボードをクリア
+ 139: self.board = [[0 for _ in range(BOARD_SIZE)] for _ in range(5)]
+ 140:
+ 141: # 各ピースをボードに配置
+ 142: for i, piece in enumerate(self.pieces):
+ 143: for dy in range(piece.height):
+ 144: for dx in range(piece.width):
+ 145: if 0 <= piece.y + dy < 5 and 0 <= piece.x + dx < BOARD_SIZE:
+ 146: self.board[piece.y + dy][piece.x + dx] = i + 1
+ 147:
+ 148: def can_move_piece(self, piece, direction):
+ 149: """指定した方向にピースが移動できるかチェック"""
+ 150: new_x, new_y = piece.x, piece.y
+ 151:
+ 152: if direction == "up":
+ 153: new_y -= 1
+ 154: elif direction == "down":
+ 155: new_y += 1
+ 156: elif direction == "left":
+ 157: new_x -= 1
+ 158: elif direction == "right":
+ 159: new_x += 1
+ 160:
+ 161: # 移動先が範囲内かチェック
+ 162: if new_x < 0 or new_y < 0:
+ 163: return False
+ 164: if new_x + piece.width > BOARD_SIZE or new_y + piece.height > 5:
+ 165: return False
+ 166:
+ 167: # 移動先に他のピースがないかチェック
+ 168: piece_id = self.pieces.index(piece) + 1
+ 169: for dy in range(piece.height):
+ 170: for dx in range(piece.width):
+ 171: board_y = new_y + dy
+ 172: board_x = new_x + dx
+ 173: if self.board[board_y][board_x] != 0 and self.board[board_y][board_x] != piece_id:
+ 174: return False
+ 175: return True
+ 176:
+ 177: def move_piece(self, piece, direction):
+ 178: """ピースを指定した方向に1マス移動"""
+ 179: if self.can_move_piece(piece, direction):
+ 180: if direction == "up":
+ 181: piece.y -= 1
+ 182: elif direction == "down":
+ 183: piece.y += 1
+ 184: elif direction == "left":
+ 185: piece.x -= 1
+ 186: elif direction == "right":
+ 187: piece.x += 1
+ 188:
+ 189: self.update_board()
+ 190: self.moves += 1
+ 191: return True
+ 192: return False
+ 193:
+ 194: def get_possible_moves(self, piece):
+ 195: """ピースが移動可能な方向のリストを返す"""
+ 196: moves = []
+ 197: directions = {"up": "↑", "down": "↓", "left": "←", "right": "→"}
+ 198: for direction in directions:
+ 199: if self.can_move_piece(piece, direction):
+ 200: moves.append(directions[direction])
+ 201: return moves
+ 202:
+ 203: def is_solved(self):
+ 204: # 娘(最初のピース)が下の出口(y=3, x=1または2)にいるかチェック
+ 205: daughter = self.pieces[0]
+ 206: return daughter.y == 3 and daughter.x == 1
+ 207:
+ 208: def handle_mouse_click(self, pos):
+ 209: # クリックされたピースを選択
+ 210: clicked_piece = None
+ 211: for piece in reversed(self.pieces): # 上のピースから順にチェック
+ 212: if piece.contains_point(pos[0], pos[1]):
+ 213: clicked_piece = piece
+ 214: break
+ 215:
+ 216: if clicked_piece:
+ 217: # 既に選択されているピースをクリックした場合
+ 218: if self.selected_piece == clicked_piece:
+ 219: # 選択を解除
+ 220: self.selected_piece.selected = False
+ 221: self.selected_piece = None
+ 222: else:
+ 223: # 別のピースを選択
+ 224: if self.selected_piece:
+ 225: self.selected_piece.selected = False
+ 226: self.selected_piece = clicked_piece
+ 227: clicked_piece.selected = True
+ 228: else:
+ 229: # 空の場所をクリックした場合、選択を解除
+ 230: if self.selected_piece:
+ 231: self.selected_piece.selected = False
+ 232: self.selected_piece = None
+ 233:
+ 234: def handle_key_press(self, key):
+ 235: """キー入力でピースを移動"""
+ 236: if not self.selected_piece:
+ 237: return
+ 238:
+ 239: direction = None
+ 240: if key == pygame.K_UP:
+ 241: direction = "up"
+ 242: elif key == pygame.K_DOWN:
+ 243: direction = "down"
+ 244: elif key == pygame.K_LEFT:
+ 245: direction = "left"
+ 246: elif key == pygame.K_RIGHT:
+ 247: direction = "right"
+ 248:
+ 249: if direction:
+ 250: self.move_piece(self.selected_piece, direction)
+ 251:
+ 252: def draw(self, screen):
+ 253: # 背景
+ 254: screen.fill(BACKGROUND)
+ 255:
+ 256: # タイトル
+ 257: title_text = font_title.render("箱入り娘パズル", True, TEXT_PRIMARY)
+ 258: title_rect = title_text.get_rect(center=(SCREEN_WIDTH//2, 50))
+ 259: screen.blit(title_text, title_rect)
+ 260:
+ 261: # ボードの背景(モダンなカード風)
+ 262: board_bg_rect = pygame.Rect(BOARD_X - 15, BOARD_Y - 15,
+ 263: BOARD_SIZE * CELL_SIZE + 30, 5 * CELL_SIZE + 30)
+ 264: # 影
+ 265: shadow_rect = board_bg_rect.copy()
+ 266: shadow_rect.x += 5
+ 267: shadow_rect.y += 5
+ 268: pygame.draw.rect(screen, CARD_SHADOW, shadow_rect, border_radius=15)
+ 269: # メイン
+ 270: pygame.draw.rect(screen, BOARD_BG, board_bg_rect, border_radius=15)
+ 271: pygame.draw.rect(screen, BOARD_BORDER, board_bg_rect, 2, border_radius=15)
+ 272:
+ 273: # グリッドを描画(薄く)
+ 274: for x in range(BOARD_SIZE + 1):
+ 275: pygame.draw.line(screen, GRID_LINE,
+ 276: (BOARD_X + x * CELL_SIZE, BOARD_Y),
+ 277: (BOARD_X + x * CELL_SIZE, BOARD_Y + 5 * CELL_SIZE))
+ 278: for y in range(6):
+ 279: pygame.draw.line(screen, GRID_LINE,
+ 280: (BOARD_X, BOARD_Y + y * CELL_SIZE),
+ 281: (BOARD_X + BOARD_SIZE * CELL_SIZE, BOARD_Y + y * CELL_SIZE))
+ 282:
+ 283: # 出口を描画(モダンなデザイン)
+ 284: exit_rect = pygame.Rect(BOARD_X + CELL_SIZE, BOARD_Y + 5 * CELL_SIZE - 15,
+ 285: 2 * CELL_SIZE, 30)
+ 286: pygame.draw.rect(screen, EXIT_COLOR, exit_rect, border_radius=15)
+ 287: exit_text = font_medium.render("🚪 出口", True, (255, 255, 255))
+ 288: exit_text_rect = exit_text.get_rect(center=exit_rect.center)
+ 289: screen.blit(exit_text, exit_text_rect)
+ 290:
+ 291: # ピースを描画
+ 292: for piece in self.pieces:
+ 293: piece.draw(screen)
+ 294:
+ 295: # サイドパネル(右側)
+ 296: panel_x = BOARD_X + BOARD_SIZE * CELL_SIZE + 40
+ 297: panel_width = SCREEN_WIDTH - panel_x - 20
+ 298:
+ 299: # 移動回数パネル
+ 300: moves_panel = pygame.Rect(panel_x, BOARD_Y, panel_width, 80)
+ 301: pygame.draw.rect(screen, BOARD_BG, moves_panel, border_radius=10)
+ 302: pygame.draw.rect(screen, BOARD_BORDER, moves_panel, 2, border_radius=10)
+ 303:
+ 304: moves_title = font_medium.render("移動回数", True, TEXT_SECONDARY)
+ 305: moves_value = font_large.render(str(self.moves), True, TEXT_PRIMARY)
+ 306: screen.blit(moves_title, (panel_x + 15, BOARD_Y + 15))
+ 307: screen.blit(moves_value, (panel_x + 15, BOARD_Y + 40))
+ 308:
+ 309: # 操作説明パネル
+ 310: help_panel = pygame.Rect(panel_x, BOARD_Y + 100, panel_width, 120)
+ 311: pygame.draw.rect(screen, BOARD_BG, help_panel, border_radius=10)
+ 312: pygame.draw.rect(screen, BOARD_BORDER, help_panel, 2, border_radius=10)
+ 313:
+ 314: help_title = font_medium.render("操作方法", True, TEXT_SECONDARY)
+ 315: screen.blit(help_title, (panel_x + 15, BOARD_Y + 115))
+ 316:
+ 317: help_texts = [
+ 318: "1️⃣ ピースをクリック",
+ 319: "2️⃣ 矢印キーで移動",
+ 320: "3️⃣ 娘を出口へ"
+ 321: ]
+ 322: for i, text in enumerate(help_texts):
+ 323: help_text = font_small.render(text, True, TEXT_PRIMARY)
+ 324: screen.blit(help_text, (panel_x + 15, BOARD_Y + 145 + i * 20))
+ 325:
+ 326: # 選択されたピースの情報パネル
+ 327: if self.selected_piece:
+ 328: info_panel = pygame.Rect(panel_x, BOARD_Y + 240, panel_width, 100)
+ 329: pygame.draw.rect(screen, BOARD_BG, info_panel, border_radius=10)
+ 330: pygame.draw.rect(screen, SELECTED_BORDER, info_panel, 2, border_radius=10)
+ 331:
+ 332: selected_title = font_medium.render(f"選択中: {self.selected_piece.name}", True, TEXT_PRIMARY)
+ 333: screen.blit(selected_title, (panel_x + 15, BOARD_Y + 255))
+ 334:
+ 335: moves = self.get_possible_moves(self.selected_piece)
+ 336: if moves:
+ 337: move_text = font_small.render(f"移動可能: {' '.join(moves)}", True, SELECTED_BORDER)
+ 338: screen.blit(move_text, (panel_x + 15, BOARD_Y + 285))
+ 339: else:
+ 340: no_move_text = font_small.render("移動できません", True, TEXT_SECONDARY)
+ 341: screen.blit(no_move_text, (panel_x + 15, BOARD_Y + 285))
+ 342:
+ 343: # クリア判定
+ 344: if self.is_solved():
+ 345: # 成功オーバーレイ
+ 346: overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
+ 347: pygame.draw.rect(overlay, (0, 0, 0, 150), (0, 0, SCREEN_WIDTH, SCREEN_HEIGHT))
+ 348: screen.blit(overlay, (0, 0))
+ 349:
+ 350: # 成功メッセージ
+ 351: clear_panel = pygame.Rect(SCREEN_WIDTH//2 - 200, SCREEN_HEIGHT//2 - 100, 400, 200)
+ 352: pygame.draw.rect(screen, BOARD_BG, clear_panel, border_radius=20)
+ 353: pygame.draw.rect(screen, TEXT_SUCCESS, clear_panel, 4, border_radius=20)
+ 354:
+ 355: clear_text = font_title.render("🎉 クリア!", True, TEXT_SUCCESS)
+ 356: clear_rect = clear_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 30))
+ 357: screen.blit(clear_text, clear_rect)
+ 358:
+ 359: moves_text = font_large.render(f"{self.moves}手でクリア", True, TEXT_PRIMARY)
+ 360: moves_rect = moves_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 20))
+ 361: screen.blit(moves_text, moves_rect)
+ 362:
+ 363: # メイン関数
+ 364: def main():
+ 365: clock = pygame.time.Clock()
+ 366: game = HakoiriMusume()
+ 367:
+ 368: running = True
+ 369: while running:
+ 370: for event in pygame.event.get():
+ 371: if event.type == pygame.QUIT:
+ 372: running = False
+ 373: elif event.type == pygame.MOUSEBUTTONDOWN:
+ 374: if event.button == 1: # 左クリック
+ 375: game.handle_mouse_click(event.pos)
+ 376: elif event.type == pygame.KEYDOWN:
+ 377: game.handle_key_press(event.key)
+ 378:
+ 379: game.draw(screen)
+ 380: pygame.display.flip()
+ 381: clock.tick(60)
+ 382:
+ 383: pygame.quit()
+ 384: sys.exit()
+ 385:
+ 386: if __name__ == "__main__":
+ 387: main()
Creating: /home/kenji/q/hakoiri_musume_modern.py
⋮
● Completed in 0.0s
完璧!モダンなデザインに生まれ変わりました!
## 改善されたポイント:
### **デザイン面**
• **モダンなカラーパレット**: パステルカラーで統一
• **カード風デザイン**: 影付きの丸角カード
• **半透明エフェクト**: 選択時の美しいオーバーレイ
• **絵文字アイコン**: 🚪出口、🎉クリア、1️⃣2️⃣3️⃣操作説明
完成したものが↓
そういえばピースの並びが想定と違っていたので変えてもらいます。
プロンプト
ピースの形と配置が想定と違ったので修正してください。
2*1は縦2,横1です。座標は(x,y)です。左上を(0,0)として(0,0)に2*1,(1,0)に2*2,(3,0)に2*1,(0,2)に2*1,(1,2)に1*2,(3,2)に2*1,(1,3)に1*1,(2,3)に1*1,(0,4)に1*1,(3,4)に1*1を配置してください。
返答
理解しました!座標を修正して正確に配置します。
⠼ Thinking...
🛠️ Using tool: fs_write (trusted)
⋮
● Path: /home/kenji/q/hakoiri_musume_final_layout.py
+ 1: import pygame
+ 2: import sys
+ 3:
+ 4: # Pygameを初期化
+ 5: pygame.init()
+ 6:
+ 7: # 画面サイズを設定
+ 8: SCREEN_WIDTH = 800
+ 9: SCREEN_HEIGHT = 700
+ 10: screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
+ 11: pygame.display.set_caption("箱入り娘パズル")
+ 12:
+ 13: # モダンな色パレット
+ 14: BACKGROUND = (245, 245, 250)
+ 15: CARD_SHADOW = (200, 200, 210)
+ 16: BOARD_BG = (255, 255, 255)
+ 17: GRID_LINE = (230, 230, 240)
+ 18: BOARD_BORDER = (180, 180, 190)
+ 19:
+ 20: # ピースの色(モダンなパステルカラー)
+ 21: DAUGHTER_COLOR = (255, 107, 107) # コーラルピンク(2×2)
+ 22: VERTICAL_COLOR = (74, 144, 226) # ブルー(1×2)
+ 23: HORIZONTAL_COLOR = (72, 187, 120) # グリーン(2×1)
+ 24: SMALL_COLOR = (255, 193, 7) # アンバー(1×1)
+ 25: EXIT_COLOR = (46, 204, 113) # エメラルドグリーン
+ 26:
+ 27: # 選択時の色
+ 28: SELECTED_OVERLAY = (255, 255, 255, 100) # 半透明白
+ 29: SELECTED_BORDER = (52, 152, 219) # 明るいブルー
+ 30:
+ 31: # テキスト色
+ 32: TEXT_PRIMARY = (44, 62, 80)
+ 33: TEXT_SECONDARY = (127, 140, 141)
+ 34: TEXT_SUCCESS = (39, 174, 96)
+ 35:
+ 36: # 日本語フォントを設定
+ 37: try:
+ 38: font_small = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 18)
+ 39: font_medium = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 24)
+ 40: font_large = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 32)
+ 41: font_title = pygame.font.Font("/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf", 40)
+ 42: except:
+ 43: font_small = pygame.font.Font(None, 18)
+ 44: font_medium = pygame.font.Font(None, 24)
+ 45: font_large = pygame.font.Font(None, 32)
+ 46: font_title = pygame.font.Font(None, 40)
+ 47:
+ 48: # ゲーム盤の設定
+ 49: BOARD_SIZE = 4 # 4x5のボード
+ 50: CELL_SIZE = 90
+ 51: BOARD_X = 200
+ 52: BOARD_Y = 120
+ 53:
+ 54: # パズルピースクラス
+ 55: class Piece:
+ 56: def __init__(self, name, width, height, x, y, color):
+ 57: self.name = name
+ 58: self.width = width # セル単位
+ 59: self.height = height # セル単位
+ 60: self.x = x # ボード上の位置(セル単位)
+ 61: self.y = y
+ 62: self.color = color
+ 63: self.selected = False
+ 64:
+ 65: def get_rect(self):
+ 66: screen_x = BOARD_X + self.x * CELL_SIZE
+ 67: screen_y = BOARD_Y + self.y * CELL_SIZE
+ 68: return pygame.Rect(screen_x, screen_y,
+ 69: self.width * CELL_SIZE, self.height * CELL_SIZE)
+ 70:
+ 71: def contains_point(self, x, y):
+ 72: rect = self.get_rect()
+ 73: return rect.collidepoint(x, y)
+ 74:
+ 75: def draw(self, screen):
+ 76: rect = self.get_rect()
+ 77:
+ 78: # 影を描画(モダンな効果)
+ 79: shadow_rect = rect.copy()
+ 80: shadow_rect.x += 3
+ 81: shadow_rect.y += 3
+ 82: pygame.draw.rect(screen, CARD_SHADOW, shadow_rect, border_radius=8)
+ 83:
+ 84: # メインの色で描画
+ 85: pygame.draw.rect(screen, self.color, rect, border_radius=8)
+ 86:
+ 87: # 選択されている場合のオーバーレイ
+ 88: if self.selected:
+ 89: # 半透明の白いオーバーレイ
+ 90: overlay_surface = pygame.Surface((rect.width, rect.height), pygame.SRCALPHA)
+ 91: pygame.draw.rect(overlay_surface, SELECTED_OVERLAY,
+ 92: (0, 0, rect.width, rect.height), border_radius=8)
+ 93: screen.blit(overlay_surface, rect.topleft)
+ 94:
+ 95: # 選択時の枠
+ 96: pygame.draw.rect(screen, SELECTED_BORDER, rect, 4, border_radius=8)
+ 97: else:
+ 98: # 通常時の薄い枠
+ 99: pygame.draw.rect(screen, (255, 255, 255, 150), rect, 2, border_radius=8)
+ 100:
+ 101: # 名前を描画(モダンなフォント)
+ 102: text = font_medium.render(self.name, True, (255, 255, 255))
+ 103: text_rect = text.get_rect(center=rect.center)
+ 104:
+ 105: # テキストに影をつける
+ 106: shadow_text = font_medium.render(self.name, True, (0, 0, 0, 100))
+ 107: shadow_rect = text_rect.copy()
+ 108: shadow_rect.x += 1
+ 109: shadow_rect.y += 1
+ 110: screen.blit(shadow_text, shadow_rect)
+ 111: screen.blit(text, text_rect)
+ 112:
+ 113: # ゲームクラス
+ 114: class HakoiriMusume:
+ 115: def __init__(self):
+ 116: self.board = [[0 for _ in range(BOARD_SIZE)] for _ in range(5)] # 4x5のボード
+ 117: self.pieces = []
+ 118: self.selected_piece = None
+ 119: self.moves = 0
+ 120: self.setup_pieces()
+ 121: self.update_board()
+ 122:
+ 123: def setup_pieces(self):
+ 124: # 指定された座標に正確に配置
+ 125: # 2×1は縦2、横1(width=1, height=2)
+ 126: # 2×2は縦2、横2(width=2, height=2)
+ 127: # 1×2は縦1、横2(width=2, height=1)
+ 128: # 1×1は縦1、横1(width=1, height=1)
+ 129:
+ 130: self.pieces = [
+ 131: # (0,0)に2×1(縦2、横1)
+ 132: Piece("父", 1, 2, 0, 0, HORIZONTAL_COLOR),
+ 133:
+ 134: # (1,0)に2×2(縦2、横2)
+ 135: Piece("娘", 2, 2, 1, 0, DAUGHTER_COLOR),
+ 136:
+ 137: # (3,0)に2×1(縦2、横1)
+ 138: Piece("母", 1, 2, 3, 0, HORIZONTAL_COLOR),
+ 139:
+ 140: # (0,2)に2×1(縦2、横1)
+ 141: Piece("兄", 1, 2, 0, 2, HORIZONTAL_COLOR),
+ 142:
+ 143: # (1,2)に1×2(縦1、横2)
+ 144: Piece("姉", 2, 1, 1, 2, VERTICAL_COLOR),
+ 145:
+ 146: # (3,2)に2×1(縦2、横1)
+ 147: Piece("叔父", 1, 2, 3, 2, HORIZONTAL_COLOR),
+ 148:
+ 149: # (1,3)に1×1
+ 150: Piece("弟1", 1, 1, 1, 3, SMALL_COLOR),
+ 151:
+ 152: # (2,3)に1×1
+ 153: Piece("弟2", 1, 1, 2, 3, SMALL_COLOR),
+ 154:
+ 155: # (0,4)に1×1
+ 156: Piece("弟3", 1, 1, 0, 4, SMALL_COLOR),
+ 157:
+ 158: # (3,4)に1×1
+ 159: Piece("弟4", 1, 1, 3, 4, SMALL_COLOR),
+ 160: ]
+ 161: # 空きマスは(2,4)
+ 162:
+ 163: def update_board(self):
+ 164: # ボードをクリア
+ 165: self.board = [[0 for _ in range(BOARD_SIZE)] for _ in range(5)]
+ 166:
+ 167: # 各ピースをボードに配置
+ 168: for i, piece in enumerate(self.pieces):
+ 169: for dy in range(piece.height):
+ 170: for dx in range(piece.width):
+ 171: if 0 <= piece.y + dy < 5 and 0 <= piece.x + dx < BOARD_SIZE:
+ 172: self.board[piece.y + dy][piece.x + dx] = i + 1
+ 173:
+ 174: def can_move_piece(self, piece, direction):
+ 175: """指定した方向にピースが移動できるかチェック"""
+ 176: new_x, new_y = piece.x, piece.y
+ 177:
+ 178: if direction == "up":
+ 179: new_y -= 1
+ 180: elif direction == "down":
+ 181: new_y += 1
+ 182: elif direction == "left":
+ 183: new_x -= 1
+ 184: elif direction == "right":
+ 185: new_x += 1
+ 186:
+ 187: # 移動先が範囲内かチェック
+ 188: if new_x < 0 or new_y < 0:
+ 189: return False
+ 190: if new_x + piece.width > BOARD_SIZE or new_y + piece.height > 5:
+ 191: return False
+ 192:
+ 193: # 移動先に他のピースがないかチェック
+ 194: piece_id = self.pieces.index(piece) + 1
+ 195: for dy in range(piece.height):
+ 196: for dx in range(piece.width):
+ 197: board_y = new_y + dy
+ 198: board_x = new_x + dx
+ 199: if self.board[board_y][board_x] != 0 and self.board[board_y][board_x] != piece_id:
+ 200: return False
+ 201: return True
+ 202:
+ 203: def move_piece(self, piece, direction):
+ 204: """ピースを指定した方向に1マス移動"""
+ 205: if self.can_move_piece(piece, direction):
+ 206: if direction == "up":
+ 207: piece.y -= 1
+ 208: elif direction == "down":
+ 209: piece.y += 1
+ 210: elif direction == "left":
+ 211: piece.x -= 1
+ 212: elif direction == "right":
+ 213: piece.x += 1
+ 214:
+ 215: self.update_board()
+ 216: self.moves += 1
+ 217: return True
+ 218: return False
+ 219:
+ 220: def get_possible_moves(self, piece):
+ 221: """ピースが移動可能な方向のリストを返す"""
+ 222: moves = []
+ 223: directions = {"up": "↑", "down": "↓", "left": "←", "right": "→"}
+ 224: for direction in directions:
+ 225: if self.can_move_piece(piece, direction):
+ 226: moves.append(directions[direction])
+ 227: return moves
+ 228:
+ 229: def is_solved(self):
+ 230: # 娘(2番目のピース)が下の出口(y=3, x=1)にいるかチェック
+ 231: daughter = self.pieces[1] # 娘は2番目のピース
+ 232: return daughter.y == 3 and daughter.x == 1
+ 233:
+ 234: def handle_mouse_click(self, pos):
+ 235: # クリックされたピースを選択
+ 236: clicked_piece = None
+ 237: for piece in reversed(self.pieces): # 上のピースから順にチェック
+ 238: if piece.contains_point(pos[0], pos[1]):
+ 239: clicked_piece = piece
+ 240: break
+ 241:
+ 242: if clicked_piece:
+ 243: # 既に選択されているピースをクリックした場合
+ 244: if self.selected_piece == clicked_piece:
+ 245: # 選択を解除
+ 246: self.selected_piece.selected = False
+ 247: self.selected_piece = None
+ 248: else:
+ 249: # 別のピースを選択
+ 250: if self.selected_piece:
+ 251: self.selected_piece.selected = False
+ 252: self.selected_piece = clicked_piece
+ 253: clicked_piece.selected = True
+ 254: else:
+ 255: # 空の場所をクリックした場合、選択を解除
+ 256: if self.selected_piece:
+ 257: self.selected_piece.selected = False
+ 258: self.selected_piece = None
+ 259:
+ 260: def handle_key_press(self, key):
+ 261: """キー入力でピースを移動"""
+ 262: if not self.selected_piece:
+ 263: return
+ 264:
+ 265: direction = None
+ 266: if key == pygame.K_UP:
+ 267: direction = "up"
+ 268: elif key == pygame.K_DOWN:
+ 269: direction = "down"
+ 270: elif key == pygame.K_LEFT:
+ 271: direction = "left"
+ 272: elif key == pygame.K_RIGHT:
+ 273: direction = "right"
+ 274:
+ 275: if direction:
+ 276: self.move_piece(self.selected_piece, direction)
+ 277:
+ 278: def draw(self, screen):
+ 279: # 背景
+ 280: screen.fill(BACKGROUND)
+ 281:
+ 282: # タイトル
+ 283: title_text = font_title.render("箱入り娘パズル", True, TEXT_PRIMARY)
+ 284: title_rect = title_text.get_rect(center=(SCREEN_WIDTH//2, 50))
+ 285: screen.blit(title_text, title_rect)
+ 286:
+ 287: # ボードの背景(モダンなカード風)
+ 288: board_bg_rect = pygame.Rect(BOARD_X - 15, BOARD_Y - 15,
+ 289: BOARD_SIZE * CELL_SIZE + 30, 5 * CELL_SIZE + 30)
+ 290: # 影
+ 291: shadow_rect = board_bg_rect.copy()
+ 292: shadow_rect.x += 5
+ 293: shadow_rect.y += 5
+ 294: pygame.draw.rect(screen, CARD_SHADOW, shadow_rect, border_radius=15)
+ 295: # メイン
+ 296: pygame.draw.rect(screen, BOARD_BG, board_bg_rect, border_radius=15)
+ 297: pygame.draw.rect(screen, BOARD_BORDER, board_bg_rect, 2, border_radius=15)
+ 298:
+ 299: # グリッドを描画(薄く)
+ 300: for x in range(BOARD_SIZE + 1):
+ 301: pygame.draw.line(screen, GRID_LINE,
+ 302: (BOARD_X + x * CELL_SIZE, BOARD_Y),
+ 303: (BOARD_X + x * CELL_SIZE, BOARD_Y + 5 * CELL_SIZE))
+ 304: for y in range(6):
+ 305: pygame.draw.line(screen, GRID_LINE,
+ 306: (BOARD_X, BOARD_Y + y * CELL_SIZE),
+ 307: (BOARD_X + BOARD_SIZE * CELL_SIZE, BOARD_Y + y * CELL_SIZE))
+ 308:
+ 309: # 出口を描画(モダンなデザイン)
+ 310: exit_rect = pygame.Rect(BOARD_X + CELL_SIZE, BOARD_Y + 5 * CELL_SIZE - 15,
+ 311: 2 * CELL_SIZE, 30)
+ 312: pygame.draw.rect(screen, EXIT_COLOR, exit_rect, border_radius=15)
+ 313: exit_text = font_medium.render("🚪 出口", True, (255, 255, 255))
+ 314: exit_text_rect = exit_text.get_rect(center=exit_rect.center)
+ 315: screen.blit(exit_text, exit_text_rect)
+ 316:
+ 317: # ピースを描画
+ 318: for piece in self.pieces:
+ 319: piece.draw(screen)
+ 320:
+ 321: # サイドパネル(右側)
+ 322: panel_x = BOARD_X + BOARD_SIZE * CELL_SIZE + 40
+ 323: panel_width = SCREEN_WIDTH - panel_x - 20
+ 324:
+ 325: # 移動回数パネル
+ 326: moves_panel = pygame.Rect(panel_x, BOARD_Y, panel_width, 80)
+ 327: pygame.draw.rect(screen, BOARD_BG, moves_panel, border_radius=10)
+ 328: pygame.draw.rect(screen, BOARD_BORDER, moves_panel, 2, border_radius=10)
+ 329:
+ 330: moves_title = font_medium.render("移動回数", True, TEXT_SECONDARY)
+ 331: moves_value = font_large.render(str(self.moves), True, TEXT_PRIMARY)
+ 332: screen.blit(moves_title, (panel_x + 15, BOARD_Y + 15))
+ 333: screen.blit(moves_value, (panel_x + 15, BOARD_Y + 40))
+ 334:
+ 335: # ピース構成パネル
+ 336: info_panel = pygame.Rect(panel_x, BOARD_Y + 100, panel_width, 140)
+ 337: pygame.draw.rect(screen, BOARD_BG, info_panel, border_radius=10)
+ 338: pygame.draw.rect(screen, BOARD_BORDER, info_panel, 2, border_radius=10)
+ 339:
+ 340: info_title = font_medium.render("ピース構成", True, TEXT_SECONDARY)
+ 341: screen.blit(info_title, (panel_x + 15, BOARD_Y + 115))
+ 342:
+ 343: info_texts = [
+ 344: "2×2: 1個(娘)",
+ 345: "2×1: 4個(縦長)",
+ 346: "1×2: 1個(横長)",
+ 347: "1×1: 4個(小さい)",
+ 348: "空きマス: 1個"
+ 349: ]
+ 350: for i, text in enumerate(info_texts):
+ 351: info_text = font_small.render(text, True, TEXT_PRIMARY)
+ 352: screen.blit(info_text, (panel_x + 15, BOARD_Y + 145 + i * 18))
+ 353:
+ 354: # 操作説明パネル
+ 355: help_panel = pygame.Rect(panel_x, BOARD_Y + 260, panel_width, 80)
+ 356: pygame.draw.rect(screen, BOARD_BG, help_panel, border_radius=10)
+ 357: pygame.draw.rect(screen, BOARD_BORDER, help_panel, 2, border_radius=10)
+ 358:
+ 359: help_title = font_medium.render("操作方法", True, TEXT_SECONDARY)
+ 360: screen.blit(help_title, (panel_x + 15, BOARD_Y + 275))
+ 361:
+ 362: help_texts = [
+ 363: "1️⃣ ピースをクリック → 2️⃣ 矢印キーで移動"
+ 364: ]
+ 365: for i, text in enumerate(help_texts):
+ 366: help_text = font_small.render(text, True, TEXT_PRIMARY)
+ 367: screen.blit(help_text, (panel_x + 15, BOARD_Y + 305 + i * 20))
+ 368:
+ 369: # 選択されたピースの情報パネル
+ 370: if self.selected_piece:
+ 371: selected_panel = pygame.Rect(panel_x, BOARD_Y + 360, panel_width, 80)
+ 372: pygame.draw.rect(screen, BOARD_BG, selected_panel, border_radius=10)
+ 373: pygame.draw.rect(screen, SELECTED_BORDER, selected_panel, 2, border_radius=10)
+ 374:
+ 375: selected_title = font_medium.render(f"選択中: {self.selected_piece.name}", True, TEXT_PRIMARY)
+ 376: screen.blit(selected_title, (panel_x + 15, BOARD_Y + 375))
+ 377:
+ 378: moves = self.get_possible_moves(self.selected_piece)
+ 379: if moves:
+ 380: move_text = font_small.render(f"移動可能: {' '.join(moves)}", True, SELECTED_BORDER)
+ 381: screen.blit(move_text, (panel_x + 15, BOARD_Y + 405))
+ 382: else:
+ 383: no_move_text = font_small.render("移動できません", True, TEXT_SECONDARY)
+ 384: screen.blit(no_move_text, (panel_x + 15, BOARD_Y + 405))
+ 385:
+ 386: # クリア判定
+ 387: if self.is_solved():
+ 388: # 成功オーバーレイ
+ 389: overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
+ 390: pygame.draw.rect(overlay, (0, 0, 0, 150), (0, 0, SCREEN_WIDTH, SCREEN_HEIGHT))
+ 391: screen.blit(overlay, (0, 0))
+ 392:
+ 393: # 成功メッセージ
+ 394: clear_panel = pygame.Rect(SCREEN_WIDTH//2 - 200, SCREEN_HEIGHT//2 - 100, 400, 200)
+ 395: pygame.draw.rect(screen, BOARD_BG, clear_panel, border_radius=20)
+ 396: pygame.draw.rect(screen, TEXT_SUCCESS, clear_panel, 4, border_radius=20)
+ 397:
+ 398: clear_text = font_title.render("🎉 クリア!", True, TEXT_SUCCESS)
+ 399: clear_rect = clear_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 30))
+ 400: screen.blit(clear_text, clear_rect)
+ 401:
+ 402: moves_text = font_large.render(f"{self.moves}手でクリア", True, TEXT_PRIMARY)
+ 403: moves_rect = moves_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 20))
+ 404: screen.blit(moves_text, moves_rect)
+ 405:
+ 406: # メイン関数
+ 407: def main():
+ 408: clock = pygame.time.Clock()
+ 409: game = HakoiriMusume()
+ 410:
+ 411: running = True
+ 412: while running:
+ 413: for event in pygame.event.get():
+ 414: if event.type == pygame.QUIT:
+ 415: running = False
+ 416: elif event.type == pygame.MOUSEBUTTONDOWN:
+ 417: if event.button == 1: # 左クリック
+ 418: game.handle_mouse_click(event.pos)
+ 419: elif event.type == pygame.KEYDOWN:
+ 420: game.handle_key_press(event.key)
+ 421:
+ 422: game.draw(screen)
+ 423: pygame.display.flip()
+ 424: clock.tick(60)
+ 425:
+ 426: pygame.quit()
+ 427: sys.exit()
+ 428:
+ 429: if __name__ == "__main__":
+ 430: main()
Creating: /home/kenji/q/hakoiri_musume_final_layout.py
⋮
完璧!最終的な正確な配置になりました!
## 最終配置(座標確認):
### **各ピースの正確な位置**
• **(0,0)**: 父(2×1 = 幅1、高さ2)- 縦長緑ピース
• **(1,0)**: 娘(2×2 = 幅2、高さ2)- メインのコーラルピンクピース
• **(3,0)**: 母(2×1 = 幅1、高さ2)- 縦長緑ピース
• **(0,2)**: 兄(2×1 = 幅1、高さ2)- 縦長緑ピース
• **(1,2)**: 姉(1×2 = 幅2、高さ1)- 横長ブルーピース
• **(3,2)**: 叔父(2×1 = 幅1、高さ2)- 縦長緑ピース
• **(1,3)**: 弟1(1×1)- 小さいアンバーピース
• **(2,3)**: 弟2(1×1)- 小さいアンバーピース
• **(0,4)**: 弟3(1×1)- 小さいアンバーピース
• **(3,4)**: 弟4(1×1)- 小さいアンバーピース
### **空きマス**
• **(2,4)** が空いています(1マスのみ)
### **ピース構成**
• **2×2: 1個**(娘)
• **2×1: 4個**(縦長 - 父、母、兄、叔父)
• **1×2: 1個**(横長 - 姉)
• **1×1: 4個**(弟1〜4)
• **空きマス: 1個**
これで指定通りの正確な箱入り娘パズルになりました!空きマス1つを上手く活用して、娘を出口まで導いてください!🎯
おおよそ想定通りのものが完成しました。
完成後はブログやナレッジ共有系サービスに記事を投稿し、申し込みフォームに記載をして応募完了となります。
Tシャツが届くのが楽しみです。
おわりに
何から何まで日本語文章ベースでプロンプトを打つだけで15分ほどでインストールから実装まで終わって驚きました。
pygameのインストールだけではなく、それに足りないパッケージも自動でインストールしてくれたので自分はなにもしていない...。
作成したコードを理解したうえで遊び方や機能の説明をしてくれるのが素晴らしいです。
(y|n|t)でtを選んだからではありますが、ちょっとお願いしただけで全てをインストールして全てを作って全ての説明をしてくるのは少し恐ろしかったです。