コンテンツにスキップ

第11部 演習 — ケーススタディ

問1. 概念確認(破綻シグナルの診断)

次の症状は、どのケーススタディで学んだ何のサインですか。

  1. 「同じ型分岐のswitchが5つの関数に複製されている」
  2. 「bool変数が8個あり、if条件が4つ以上のフラグを見ている」
  3. 「機能追加のたびに、無関係なはずのゲームロジックのファイルに触っている」
  4. 「効果ごとにタイマー変数がキャラクラスに増えていく」
  5. 「アップデート後、ユーザーのセーブが読めなくなった」
解答 1. [武器切り替え](02_weapon_switching.md): switch散らばり=ポリモーフィズム/データ駆動の出番。2. [敵AI](03_enemy_ai.md): フラグの網=FSMのサイン。3. [実績](05_achievements.md)/[イベント通知](14_event_notification.md): 観測者がロジックに寄生=Pub/Subで分離。4. [ステート異常](04_status_effects.md): 同時複数・個別寿命=効果リスト。5. [セーブデータ](06_save_data.md): バージョン・名前付き形式の欠如。

問2. コード読解(設計案の識別)

void World::KillEnemy(Enemy& e) {
    score_.Add(e.Exp());
    drops_.SpawnFor(e);
    bus_.Publish(EnemyDied{e.Id(), e.Type(), e.Pos()});
    uiQueue_.Push(KillLogRequest{e.Name()});
    world_.Destroy(e);
}

スコア/ドロップ、バス発行、UIキューがそれぞれ別の仕組みなのはなぜですか。全部バスにした場合に起きる問題を1つ挙げてください。

解答 反応の性質が違うから: スコア・ドロップは「ルールの帰結」で順序と確実性が仕様(直呼びで順序をコードに固定)。実績等の「観測者」は順序不問・増減するのでバス。UI・音は「演出」で遅延・集約が欲しいのでキュー([イベント通知](14_event_notification.md))。全部バスにすると、例えば「ドロップ生成がDestroyの後になる」ような順序が購読登録順に依存し、保証のない偶然の動作になる。

問3. 問題のあるコードの改善(総合)

「ショップNPCに話しかけると、(1) 所持金UIを開き、(2) 販売リストをハードコードのswitchで構築し、(3) 購入時に Player::gold を直接減らし、(4) 購入音をFMOD APIで直接鳴らす」1つの関数(200行)があります。4つの問題それぞれに、学んだケースから対応する改善を割り当ててください。

解答の要点 (1) UI直接操作 → [UI通知](08_ui_notification.md): 画面遷移/表示はスタックやキュー経由に。(2) 商品ハードコード → [アイテム効果](12_item_effects.md)/[武器切り替え](02_weapon_switching.md)のデータ駆動: 商品テーブル(データ)化。(3) gold直接操作 → [カプセル化](../01_design_basics/05_abstraction_encapsulation.md)+購入手続きの集約(検証→支払→付与を1サービスに: [SOLID演習の問7](../02_solid/exercises.md))。(4) FMOD直叩き → [サウンド管理](11_sound_manager.md): ID化+Facade経由。全体としては[責務の分離](../01_design_basics/02_responsibility_and_separation.md)の総合演習。

問4. 設計比較(規模の判断)

「1人開発・開発期間3ヶ月・敵5種・武器3種」のアクションゲームで、次のどれに設計投資しますか。優先度順に3つ選び、理由を書いてください。

A. 敵AIのBehavior Tree基盤 B. セーブのバージョン管理 C. サウンドのID化 D. 武器のStrategy化 E. DIコンテナ F. イベントバス

解答例 推奨: **B → C → (D)**。B: セーブ互換は後から直せない(YAGNIの例外 → [セーブデータ](06_save_data.md))。C: 初日にID化するだけで将来の全進化が無痛([サウンド](11_sound_manager.md))、コストほぼゼロ。D: 武器3種ならswitchでも足りるが、固有状態(弾数)が出た時点で安い移行。A: 敵5種にBTは過剰([敵AI](03_enemy_ai.md))。E/F: この規模では配線コストが利益を上回る([Service LocatorとDI](../04_game_patterns/service_locator_and_di.md))。——「安い保険(B,C)を先に、重い基盤(A,E,F)は破綻の証拠が出てから」が判断の型。

問5. デバッグ問題

「ロックオン中にターゲットの敵が死ぬと、たまにカメラが原点(0,0,0)を向く」。照準制御第7部の知識で、原因の候補2つと対策を書いてください。

解答の要点 候補1: ターゲットへの参照がdangling(削除済み敵の位置=ゴミ or 解放済みメモリ)——「たまに」はメモリ再利用のタイミング依存の典型。候補2: 「死亡→null設定」はしているが、同フレームの後続処理(カメラ更新)が設定前の値を読む**更新順序**問題。対策: 弱参照/世代ハンドル+毎フレームの有効性確認を「照準モード更新の冒頭」に置き、無効ならその場でFreeAimへ遷移(フレーム内の順序も設計に含める)。

問6. 説明問題

「デザインパターンを勉強したので、次のプロジェクトでは最初から全部適用しようと思います」という後輩に、ケーススタディ全体の教訓を使って4文以内で助言してください。

解答例 各ケースで見た通り、正解は規模と要求で変わり、小規模では「素朴な実装」や「パターンなしの簡潔案」が最適なことが多い。パターンは破綻のシグナル(switchの複製、フラグの網、変更の波及)が出たときに、その痛みに対応するものを選ぶ道具だ。ただし「セーブのバージョン」「サウンドのID化」「意図の構造体」のような**後から変えるのが高くつく少数の決定**だけは先にやる価値がある。「全部最初から」でも「全部後回し」でもなく、可逆性で仕分けるのが実務の判断だよ([YAGNI](../01_design_basics/09_yagni_kiss_dry.md))。

問7. 小規模実装問題(総合)

ミニゲーム「Wave Survival」の骨格を設計・実装してください(コンソール出力の擬似ゲームで可):

評価基準: (a) 3分類(ルール/観測/演出)が構造に現れているか、(b) 各システムが他システムの内部に触れていないか、(c) 「この規模なら過剰だった部分」を自己申告できるか。samples/ の各サンプルが部品として流用できます。


前: 照準制御 | カテゴリ目次 | 第12部: 判断ガイドへ