C言語入門|STEP18:マップ探索ロジックの実装-2次元配列・移動判定・イベント分岐

はじめに:RPGはマップを歩いてこそ始まる

STEP17では、アイテムと装備の仕組みを解説しました。
STEP18では、RPGの「冒険感」を支える マップ探索ロジック に注目します。

このRPGでは、

  • 文字で描かれたマップ
  • プレイヤーの移動
  • 敵・宝箱・イベントの発生

2次元配列 を使って実装しています。
一見難しそうですが、仕組み自体はとても素直です。

マップは2次元配列で表現する

まず、マップは次のように定義されています。

#define MAP_W 25
#define MAP_H 25

static char g_map[MAP_H][MAP_W];

なぜ2次元配列なのか

理由内容
直感的縦横の座標が分かりやすい。
表示しやすいそのまま画面に描画できる。
判定が簡単壁・イベント確認が容易

RPGのマップは、
配列と非常に相性が良い構造 です。

マップに使われている記号の意味

マップ内では、1文字が1マスを表します。

記号意味
#壁(通行不可)
.通路
@プレイヤー
E
T宝箱
Iイベント
Bボス

文字だけで状態を表現できるため、
デバッグもしやすくなっています。

マップの初期化処理

ゲーム開始時には、
マップを初期化します。

static void init_map(void) {
    for (int y = 0; y < MAP_H; y++) {
        for (int x = 0; x < MAP_W; x++) {
            g_map[y][x] = '.';
        }
    }
}

この処理のポイント

  • 全マスを通路で初期化
  • 壁やイベントは後から配置

まず「空の世界」を作ってから、
要素を配置する流れ になっています。

壁の配置で迷路を作る

壁は、別の処理で配置されます。

g_map[0][x] = '#';
g_map[MAP_H-1][x] = '#';

なぜ外周を壁にするのか

  • マップ外への移動を防ぐ。
  • 移動判定が簡単になる。

外周を壁にしておくことで、
境界チェックを減らせます。

プレイヤーの位置管理

プレイヤーの位置は、
座標で管理されています。

int px = 1;
int py = 1;

座標管理の基本

  • x:横方向
  • y:縦方向

配列アクセスでは
g_map[py][px]
という形になる点に注意しましょう。

マップ表示処理の考え方

マップは、
毎ターン描画されます。

for (int y = 0; y < MAP_H; y++) {
    for (int x = 0; x < MAP_W; x++) {
        if (x == px && y == py)
            putchar('@');
        else
            putchar(g_map[y][x]);
    }
    putchar('\n');
}

表示処理のポイント

  • プレイヤー位置だけ特別扱い。
  • マップ配列は背景扱い。

これにより、
プレイヤーが動いて見える ようになります。

移動入力の受け取り方

移動は、テンキー風の入力で行います。

入力移動
8
2
4
6
int cmd;
scanf("%d", &cmd);

この入力をもとに、
移動方向を決定します。

移動先が通行可能かの判定

移動前には、
必ず判定を行います。

if (g_map[ny][nx] == '#') {
    printf("壁があって進めない!\n");
    return;
}

このチェックの意味

  • 壁には入れない。
  • マップ破壊を防ぐ。

移動前チェック は、
マップ探索の基本です。

マスに応じたイベント分岐

移動先のマスによって、
処理が分岐します。

switch (g_map[ny][nx]) {
    case 'E': start_battle(); break;
    case 'T': open_treasure(); break;
    case 'I': trigger_event(); break;
}

文字による分岐のメリット

  • 1文字で状態が分かる。
  • switch文で整理しやすい。
  • 拡張が簡単

RPGのイベント処理は、
文字コード分岐が定番 です。

敵と遭遇したあとの処理

敵と戦闘したあとは、
そのマスを通路に戻します。

g_map[ny][nx] = '.';

なぜ消すのか

  • 同じ敵と何度も戦わない。
  • マップが進行状態を覚える。

これにより、
探索済みエリアが分かる ようになります。

宝箱・イベントも一度きりにする理由

宝箱やイベントも、
処理後はマップから消えます。

g_map[ny][nx] = '.';

この設計の効果

  • 探索の意味が出る。
  • 無限取得を防ぐ。
  • シンプルな状態管理

一度きりのイベントは、
マップを書き換えるだけで実現できます。

ボスマス到達時の特別処理

ボスのマスでは、
通常とは違う処理に進みます。

if (g_map[ny][nx] == 'B') {
    start_boss_battle();
}

ここがゲームの山場

  • 通常戦闘とは別扱い。
  • エンディングへ直結

マップ探索と物語が、
ここでつながる構造 になっています。

STEP18で押さえておきたいポイントまとめ

STEP18の重要ポイントはこちらです。

  • マップは2次元配列で管理する
  • 1文字=1マスで状態を表す
  • 移動前に必ず通行判定を行う
  • マスの文字でイベントを分岐する
  • 処理後はマップを書き換えて状態管理する