Skip to content

実装計画書 - Python 数当てゲーム (Premium CLI Edition)

目標

Pythonを使用して、単なるテキストベースではなく、視覚的に洗練された「数当てゲーム」を作成します。rich ライブラリを活用し、リッチなテキスト、色、パネル、プログレスバーなどを用いたプレミアムなCLI体験を提供します。

提案する機能

  • 難易度設定: 初級・中級・上級から選択可能。
  • リッチなUI: rich ライブラリによるカラー出力、テーブル表示、絵文字の使用。
  • ヒント機能: 「もっと大きい」「もっと小さい」などの動的なフィードバック。
  • スコア機能: 試行回数に基づいたランク付け。
  • 入力バリデーション: 数字以外が入力された際のエラーハンドリング。

技術スタック

  • 言語: Python 3
  • ライブラリ: rich (美しさを追求するため)

実装ステップ

[Logic]

[NEW] game_logic.py

  • 数当てのコアロジックを管理。
  • 難易度に応じた数値の範囲設定。

[UI]

[NEW] main.py

  • ゲームのエントリーポイント。
  • rich を使用したユーザーインターフェースと入力受け付け。
🐍 ソースコードを表示 (Logic & UI)
py
import random

class GameLogic:
    def __init__(self, difficulty='medium'):
        self.difficulty = difficulty
        self.range_max = self._set_range()
        self.secret_number = random.randint(1, self.range_max)
        self.attempts = 0

    def _set_range(self):
        if self.difficulty == 'easy':
            return 10
        elif self.difficulty == 'hard':
            return 100
        else: # medium
            return 50

    def check_guess(self, guess):
        self.attempts += 1
        if guess < self.secret_number:
            return "Too low!"
        elif guess > self.secret_number:
            return "Too high!"
        else:
            return "Correct!"

    def get_rank(self):
        if self.attempts <= 3:
            return "S (Master Mind 🧠)"
        elif self.attempts <= 6:
            return "A (Great Guessing 🌟)"
        elif self.attempts <= 10:
            return "B (Good Job 👍)"
        else:
            return "C (Better luck next time 🧊)"
py
import sys
from rich.console import Console
from rich.panel import Panel
from rich.prompt import Prompt, IntPrompt
from rich.table import Table
from rich.live import Live
from rich.text import Text
from game_logic import GameLogic

console = Console()

def show_welcome():
    console.print(Panel.fit(
        "[bold magenta]✨ Premium Number Guessing Game ✨[/bold magenta]\n"
        "[cyan]PythonとRichライブラリによる最高のエクスペリエンス[/cyan]",
        border_style="bright_blue"
    ))

def select_difficulty():
    table = Table(title="難易度を選択してください", show_header=True, header_style="bold cyan")
    table.add_column("Level", style="dim")
    table.add_column("Name", style="bold")
    table.add_column("Range", justify="right")
    
    table.add_row("1", "Easy", "1 - 10")
    table.add_row("2", "Medium", "1 - 50")
    table.add_row("3", "Hard", "1 - 100")
    
    console.print(table)
    
    choice = Prompt.ask("選択してください", choices=["1", "2", "3"], default="2")
    
    mapping = {"1": "easy", "2": "medium", "3": "hard"}
    return mapping[choice]

def start_game():
    show_welcome()
    difficulty = select_difficulty()
    game = GameLogic(difficulty)
    
    console.print(f"\n[bold green]Game Start![/bold green] 1から{game.range_max}の間の数字を当ててください。")
    
    while True:
        try:
            guess = IntPrompt.ask(f"予想を入力 (1-{game.range_max})")
            
            if guess < 1 or guess > game.range_max:
                console.print(f"[bold red]範囲外です![/bold red] 1から{game.range_max}の間で入力してください。")
                continue
                
            result = game.check_guess(guess)
            
            if result == "Too low!":
                console.print("[yellow]👇 もっと大きいです![/yellow]")
            elif result == "Too high!":
                console.print("[yellow]👆 もっと小さいです![/yellow]")
            else:
                # Correct!
                console.print(f"\n[bold green]🎊 おめでとうございます! 正解は {game.secret_number} でした![/bold green]")
                console.print(f"[bold cyan]トータル試行回数: {game.attempts}[/bold cyan]")
                
                rank = game.get_rank()
                console.print(Panel(
                    f"[bold yellow]ランク: {rank}[/bold yellow]",
                    title="結果発表",
                    border_style="bright_yellow"
                ))
                break
        except Exception:
            console.print("[bold red]エラーが発生しました。[/bold red]")
            break

    if Prompt.ask("\nもう一度プレイしますか?", choices=["y", "n"], default="y") == "y":
        console.clear()
        start_game()
    else:
        console.print("[bold magenta]プレイしていただきありがとうございました![/bold magenta] 👋")

if __name__ == "__main__":
    try:
        start_game()
    except KeyboardInterrupt:
        console.print("\n[bold red]ゲームを中断しました。[/bold red]")
        sys.exit(0)

🎓 練習ドリル:自力で作ってみよう!

このプロジェクトの核心部分を自分の手で実装してみましょう。

ドリル1: 基礎ロジックの実装

  1. random.randint を使って、1〜100のランダムな数字を生成する関数を書いてください。
  2. ユーザーが入力した数字と比較し、「大きい」「小さい」「正解!」を表示するループを作成してください。

ドリル2: クラス化

  1. ドリル1のロジックを NumberGuessingGame クラスにまとめてみましょう。

ドリル3: Rich ライブラリの導入

  1. pip install rich でインストール。
  2. rich.panel.Panel を使い、ゲームのタイトルをボックスで囲んで表示してください。

ドリル4: 入力エラーへの対応

  1. 数字以外が入力された際、プログラムが強制終了せずに「数字を入力してください」と警告を出すように try...except を使って実装してください。

検証計画

  • python main.py を実行し、ゲームが正常に進行することを確認。
  • 不適切な入力(文字、範囲外の数字)に対する挙動を確認。

Released under the MIT License.