ふくちゃんのスキル道場

スキルを磨いて厳しい世の中を生き抜く事を目指すブログです。

DBの学習_Python×SQLiteで作る「RPGの戦闘画面」でCRUDの基本を理解しよう

こんにちは!
ふくちゃんです。

久しぶりの投稿になってしまいましたが、前回のDB学習についての記事の続きで書いていきます。
いきなりしっかりしたゲームを作成して、始めるのは大変なので簡単に始められるようにGoogle Ai Studioで作成し動かしながら学習してみました。
画面とかはなくターミナル上で戦闘が進んでいく簡略的なものですが、スタートにはちょうど良い簡単な内容になっています。

QUEST: データベース学習ログ

今回は、PythonとSQLiteを使って「RPGの簡単な戦闘画面」を作りながら、データベースの基本操作を体験してみました。

動作環境はVS Codeでpythonとpython debuggerの拡張機能いれてデバッグ実行しただけです。

Aiに作成してもらったプログラムは下記のような感じです。

プログラム全文を表示する
# -------------------------
import sqlite3
import time
# -------------------------
# 1. データベースの初期設定
# -------------------------
def setup_database():
    # DBファイルに接続(存在しない場合は rpg_game.db が作成されます)
    conn = sqlite3.connect("rpg_game.db")
    cursor = conn.cursor()
    # テーブルの作成(プレイヤーとモンスター)
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS players (
            id INTEGER PRIMARY KEY,
            name TEXT,
            hp INTEGER,
            attack INTEGER,
            defense INTEGER
        )
    """)
    
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS monsters (
            id INTEGER PRIMARY KEY,
            name TEXT,
            hp INTEGER,
            attack INTEGER,
            defense INTEGER
        )
    """)
    # データを毎回リセット(学習用のため)
    cursor.execute("DELETE FROM players")
    cursor.execute("DELETE FROM monsters")
    # 初期データの挿入 (INSERT)
    cursor.execute("INSERT INTO players (id, name, hp, attack, defense) VALUES (1, '勇者', 100, 25, 10)")
    cursor.execute("INSERT INTO monsters (id, name, hp, attack, defense) VALUES (1, 'スライム', 40, 15, 5)")
    cursor.execute("INSERT INTO monsters (id, name, hp, attack, defense) VALUES (2, 'ドラゴン', 200, 40, 20)")
    # 変更を保存して閉じる
    conn.commit()
    conn.close()
    print("システムのメッセージ:データベースのセットアップが完了しました。\n")
# -------------------------
# 2. 戦闘処理のプログラム
# -------------------------
def battle(player_id, monster_id):
    conn = sqlite3.connect("rpg_game.db")
    conn.row_factory = sqlite3.Row # 列名でデータにアクセスできるようにする
    cursor = conn.cursor()
    # DBからデータを取得 (SELECT)
    cursor.execute("SELECT * FROM players WHERE id = ?", (player_id,))
    player = dict(cursor.fetchone())
    cursor.execute("SELECT * FROM monsters WHERE id = ?", (monster_id,))
    monster = dict(cursor.fetchone())
    print(f"野生の {monster['name']} があらわれた!")
    print(f"【{player['name']}】HP: {player['hp']}  VS  【{monster['name']}】HP: {monster['hp']}\n")
    # 戦闘ループ
    while player['hp'] > 0 and monster['hp'] > 0:
        input("Enterキーを押して攻撃!")
        
        # 勇者の攻撃
        damage_to_monster = max(1, player['attack'] - monster['defense'])
        monster['hp'] -= damage_to_monster
        print(f"{player['name']} の攻撃! {monster['name']} に {damage_to_monster} のダメージ!")
        time.sleep(1)
        if monster['hp'] <= 0:
            print(f"{monster['name']} を倒した!\n")
            break
        # モンスターの攻撃
        damage_to_player = max(1, monster['attack'] - player['defense'])
        player['hp'] -= damage_to_player
        print(f"{monster['name']} の攻撃! {player['name']} に {damage_to_player} のダメージ!")
        print(f"現在の {player['name']} の残りHP: {max(0, player['hp'])}\n")
        time.sleep(1)
        if player['hp'] <= 0:
            print(f"{player['name']} は死んでしまった...\n")
            break
    # 戦闘終了後、プレイヤーの残りHPをデータベースに保存 (UPDATE)
    if player['hp'] > 0:
        cursor.execute("UPDATE players SET hp = ? WHERE id = ?", (player['hp'], player_id))
        conn.commit()
        print("システムのメッセージ:戦闘後のHPをデータベースに保存しました。")
    conn.close()
# -------------------------
# 3. メイン処理
# -------------------------
if __name__ == "__main__":
    setup_database()
    print("=== 第1回戦 ===")
    battle(player_id=1, monster_id=1)
    print("\n=== 第2回戦 ===")
    battle(player_id=1, monster_id=2)
# -------------------------

実行すると、3. メイン処理が実行され順番に第1回戦 、第2回戦 と呼び出されて実行される流れです。
起動するたびにDBはリセットされるので、繰り返し動きは確認できます。

この中で使用されている。基本的なSQL(CRUD)は下記になります。

1. C: Create(作成 / INSERT)
INSERT INTO players (id, name, hp, attack, defense) VALUES (1, '勇者', 100, 25, 10)

2. R: Read(読み込み / SELECT)
SELECT * FROM players WHERE id = 1

3. U: UPDATE(更新 / UPDATE)
SELECT * FROM players WHERE id = 1

4. D: DELETE(削除 /DELETE)
DELETE FROM players

Aiを使用することで学ぶために必要な素材を作成しやすくなっているので、うまく利用して学習を勧めていきたいと思います。
戦闘画面は一番下に載せておきます。

みなさんもぜひチャレンジしてみてください。

=== 第1回戦 ===
野生の スライム があらわれた!
【勇者】HP: 100 VS 【スライム】HP: 40

Enterキーを押して攻撃!
勇者 の攻撃! スライム に 20 のダメージ!
スライム の攻撃! 勇者 に 5 のダメージ!
現在の 勇者 の残りHP: 95

Enterキーを押して攻撃!
勇者 の攻撃! スライム に 20 のダメージ!
スライム を倒した!

システムのメッセージ:戦闘後のHPをデータベースに保存しました。
=== 第2回戦 ===
野生の ドラゴン があらわれた!
【勇者】HP: 95 VS 【ドラゴン】HP: 200

Enterキーを押して攻撃!
勇者 の攻撃! ドラゴン に 5 のダメージ!
ドラゴン の攻撃! 勇者 に 30 のダメージ!
現在の 勇者 の残りHP: 65

Enterキーを押して攻撃!
勇者 の攻撃! ドラゴン に 5 のダメージ!
ドラゴン の攻撃! 勇者 に 30 のダメージ!
現在の 勇者 の残りHP: 35

Enterキーを押して攻撃!
勇者 の攻撃! ドラゴン に 5 のダメージ!
ドラゴン の攻撃! 勇者 に 30 のダメージ!
現在の 勇者 の残りHP: 5

Enterキーを押して攻撃!
勇者 の攻撃! ドラゴン に 5 のダメージ!
ドラゴン の攻撃! 勇者 に 30 のダメージ!
現在の 勇者 の残りHP: 0

勇者 は死んでしまった...