番外編:ドラ〇エ風RPGをつくってみる

この授業ではこれまで学んだ printfscanfif 文を使って、簡単なバトルゲームを少しずつ作っていきます。
コードの中には、まだ授業で扱っていない仕組みも入っています。「読めなくても気にしない」「動けばOK」で進めましょう。

✅ 今回のゴール:スライムと戦って倒せる、そして「にげる」も選べる小さなRPGを完成させること。
早く終わった人は、ページ末尾の「もっと改造してみよう」に挑戦してください。

今回の流れ

段階やること身につくこと
STEP 1お手本コードをコピペして動かす「動くものを動かす」体験
DEBUGデバッガーで1行ずつ動きを追う変数の中身を確認する力
STEP 2scanf でコマンド入力を受け取る入力で動作を変える
STEP 3「にげる」を追加(else if複数の分岐
STEP 4無効コマンド対応(else)→ 完成例外処理の考え方
発展名前入力・敵強化・反撃など自由課題応用力
⚠ デバッガーのキー操作を思い出したいときは、別ファイルの「デバッガー早見表」を開いてください(左のナビゲーションから)。

STEP 1まずはコピペして動かしてみよう

まずはお手本のコードをそのままコピーして、実行してみます。
このコードは 自動でスライムを攻撃し続け、倒したら終わるプログラムです。

準備

1. いま開いているプロジェクトで、前のファイルを「ビルドから除外」する
2. 「ソース ファイル」に新しいファイル DoraBattleGame.c を追加する
3. 下のコードを丸ごとコピーして貼り付ける

コード

DoraBattleGame.c
#include <stdio.h>
#include <string.h>
#include <windows.h>  // Sleep 関数を使うため

// ====== 定数の定義 ======
#define NAME_MAX 10      // 名前の最大文字数
#define CHAR_HP   0      // HP の位置
#define CHAR_STR  1      // 攻撃力の位置
#define CHAR_DEF  2      // 防御力の位置

// ====== キャラクターのデータ ======
char playerName[NAME_MAX] = "さんぎょ";
int  playerParam[3] = { 10, 3, 3 };   // HP, 攻撃力, 防御力

char enemyName[] = "スライム";
int  enemyParam[3] = { 5, 3, 2 };     // HP, 攻撃力, 防御力

// ====== Enter キー待ち関数 ======
// 「Enterキーで続ける」と表示し、Enterが押されるまで待つ
void waitEnter() {
    printf("\n▼");
    while (getchar() != '\n');   // 改行が読まれるまで待つ
    printf("\n================================\n");
}

// ====== プレイヤーの状態を表示する ======
void showStatus() {
    printf("\n【あなた】\n");
    printf("名前: %s\n", playerName);
    printf("HP: %d  攻撃力: %d  防御力: %d\n",
        playerParam[CHAR_HP], playerParam[CHAR_STR], playerParam[CHAR_DEF]);
    Sleep(400);
}

// ====== 敵の状態を表示する ======
void showEnemy() {
    printf("\n【敵】\n");
    printf("名前: %s\n", enemyName);
    printf("HP: %d\n", enemyParam[CHAR_HP]);
    Sleep(400);
}

// ====== 戦闘処理(プレイヤーが敵に1回攻撃する)======
void battle() {
    int damage = playerParam[CHAR_STR] - enemyParam[CHAR_DEF];
    if (damage < 0) damage = 0;

    enemyParam[CHAR_HP] -= damage;

    Sleep(400);
    printf("\n%sのこうげき!", playerName);
    Sleep(600);
    printf("%sに%dのダメージ!\n", enemyName, damage);
    Sleep(400);

    if (enemyParam[CHAR_HP] <= 0) {
        printf("%sをたおした!\n", enemyName);
    }
}

// ====== メイン処理 ======
int main() {
    printf("=== バトルスタート ===\n");

    // 敵を倒すまで繰り返し攻撃する
    while (1) {
        showStatus();
        showEnemy();
        battle();

        // 敵のHPが0以下なら戦闘終了
        if (enemyParam[CHAR_HP] <= 0) {
            break;
        }

        waitEnter();   // Enter キーが押されるまで待つ
    }

    printf("=== バトル終了 ===\n");
    return 0;
}
▶ やってみよう
Ctrl + F5 で実行する。スライムが3回の攻撃で倒れて、「=== バトル終了 ===」と表示されればOK。

実行結果(例)

=== バトルスタート ===

【あなた】
名前: さんぎょ
HP: 10  攻撃力: 3  防御力: 3

【敵】
名前: スライム
HP: 5

さんぎょのこうげき!スライムに1のダメージ!

【あなた】
名前: さんぎょ
HP: 10  攻撃力: 3  防御力: 3

【敵】
名前: スライム
HP: 4

さんぎょのこうげき!スライムに1のダメージ!

(… 続く …)

スライムをたおした!
=== バトル終了 ===
もし scanf でエラーや警告が出たら:このSTEPでは scanf は使っていないので、まだ出ません。STEP 2 以降で出る可能性があります。そのときは先生に声をかけてください。
📖 このコードで「読めなくてOK」な書き方の一覧(クリックで開く)
登場した書き方いまは…
#define CHAR_HP 0「0という数字に CHAR_HP という名前を付けている」とだけ理解
int playerParam[3]「数字を3つまとめて入れられる箱」
void showStatus() { ... }「処理に名前を付けてまとめたもの(関数)」
while (1) { ... }「中身をずっと繰り返す」
break;「繰り返しを抜ける」
Sleep(400)「400ミリ秒(0.4秒)待つ」(Windows専用の待機関数)
waitEnter()「Enterキーが押されるまで待つ」(このゲーム専用の関数)

どれも今後の授業で詳しく扱います。今回はとにかく「動く」を体験できればOKです。


DEBUGデバッガーで動きを追ってみよう

「なんとなく動いた」状態のコードを、1行ずつ実行しながら変数の値を確認できる機能がVisual Studioには備わっています。
これをデバッガーといい、バグの原因を探したり、プログラムの動きを理解したりするために使います。

✅ デバッガーを使えるようになると、「なぜこの値になるのか」を自分で確認できるようになります。
エラーが出たときも、どこで何が起きているかを追跡できます。

ブレークポイントを設定する

ブレークポイントとは、「ここで実行を一時停止する」という目印です。

1 コードエディタで、止めたい行番号の左側をクリックする
→ 赤い丸 ● が付く。これがブレークポイント。
2 まずはSTEP 1 のコードの battle(); の行に設定してみる
⚠ 赤い丸をもう一度クリックすると、ブレークポイントが解除されます。

デバッグ実行する

3 これまでの Ctrl+F5(デバッグなし実行)ではなく、F5(デバッグ実行)を押す
4 ブレークポイントの行で黄色い矢印 が止まる
= 「プログラムがここで一時停止している」状態
Ctrl+F5 と F5 の違い
Ctrl+F5:ブレークポイントを無視して最後まで実行する(今まで使っていた方法)
F5:ブレークポイントで止まりながら実行する(デバッグ用)

ステップ実行する

一時停止した状態から、次のキーで1行ずつ進められます。

キー動作
F10次の1行へ進む(関数の中には入らない)
F11次の1行へ進む(関数の中まで入る)
F5次のブレークポイントまで一気に進む
Shift+F5デバッグを終了する
F10 と F11 の使い分け
F10:battle(); の行で止まっているとき、F10 を押すと battle 関数の中身を飛ばして次の行へ進む
F11:battle(); の行で止まっているとき、F11 を押すと battle 関数の中に入って1行目から確認できる

変数の値を確認する

5 実行が止まっている状態で、変数名の上にマウスカーソルを乗せる
→ ツールチップで現在の値が表示される
6 画面下部の「ローカル」ウィンドウにも変数の一覧が表示される
enemyParam の値が1行ごとにどう変わるかを確認できる
▶ やってみよう
  1. battle(); の行にブレークポイントを設定して F5 で実行する
  2. 止まったら F11 で battle 関数の中に入り、damage が計算される瞬間を確認する
  3. enemyParam[CHAR_HP] の値がターンごとに減っていくことをウォッチで確認する
  4. while(1) のループが繰り返されることを確認する
  5. 確認が終わったら Shift+F5 でデバッグ終了
    以降の実行は Ctrl+F5(デバッグなし実行)に戻す