広告スペース

C言語ゲーム制作チャレンジ

「もっと面白くしたい」という工夫がコーディング力を一番伸ばします。
まず基本版を作り、拡張課題で自分なりの工夫を加えてみましょう。

進め方: 各ゲームには「基本実装」→「段階的拡張」の流れがあります。基本版を動かしてから、拡張課題に自由に挑戦してください。正解は1つではありません。
🎯
GAME 1: 数当てゲーム
入門 乱数 ループ 条件分岐
コンピュータが選んだ秘密の数を当てるゲーム。ヒント(大きい/小さい)を頼りに正解を探す。
🎯 1〜100の数を当ててください! 予想> 50 もっと大きいです 予想> 75 もっと小さいです 予想> 63 🎉 正解! 3回で当たりました!
1
乱数で答えを決める: srand(time(NULL))rand() % 100 + 1 で1〜100のランダムな数を生成
2
ループで入力を受け付ける: while で正解するまで繰り返す。scanf で予想を読み込む
3
判定して表示: 予想 > 答え なら「小さい」、予想 < 答え なら「大きい」、一致なら「正解」
4
試行回数をカウント: int 型の変数で回数を数え、正解時に表示
拡張課題(工夫してみよう)
  • 試行回数に応じて評価を変える(5回以内なら「天才!」、10回以内なら「まずまず」等)
  • 難易度選択を追加(Easy: 1〜50、Normal: 1〜100、Hard: 1〜1000)
  • 「もう一度遊ぶ?」機能を do-while で実装
  • 二分探索なら最大何回で当たるか計算して表示
  • 制限回数を設けて、超えたらゲームオーバーにする
骨格:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
    srand((unsigned)time(NULL));
    int answer = rand() % 100 + 1;
    int guess, count = 0;

    printf("1〜100の数を当ててください!\n");
    do {
        printf("予想> ");
        scanf("%d", &guess);
        count++;
        if (guess > answer) printf("もっと小さいです\n");
        else if (guess < answer) printf("もっと大きいです\n");
    } while (guess != answer);

    printf("正解! %d回で当たりました!\n", count);
    return 0;
}
GAME 2: じゃんけんゲーム
入門 switch 乱数 配列
コンピュータとじゃんけん対決。勝敗を記録して戦績を表示する。
✊✌✋ じゃんけんゲーム(0:グー 1:チョキ 2:パー -1:終了) あなた> 0 あなた: グー vs CPU: チョキ 🎉 あなたの勝ち! あなた> 2 あなた: パー vs CPU: パー 😐 あいこ! あなた> -1 --- 戦績 --- 3勝 1敗 1分 (勝率60.0%)
1
手の名前を配列で管理: char *hands[] = {"グー","チョキ","パー"};
2
勝敗判定: (player - cpu + 3) % 3 が 0=あいこ、1=負け、2=勝ち
3
戦績管理: 勝ち/負け/あいこ の3変数をカウント
4
終了処理: -1 入力でループ脱出、戦績を表示
拡張課題
  • 3本勝負(先に2勝した方が勝ち)モードを追加
  • プレイヤーの手の偏りを記録して、CPUが対策する「学習AI」を作る
  • 「グー・チョキ・パー・リザード・スポック」5択版に拡張
  • 対戦履歴を配列に記録して、最後に全履歴を表示
勝敗判定のコツ:
// 0=グー, 1=チョキ, 2=パー
int result = (player - cpu + 3) % 3;
if (result == 0) printf("あいこ\n");
else if (result == 2) printf("あなたの勝ち!\n");
else printf("あなたの負け…\n");
🎰
GAME 3: スロットマシン
入門 乱数 配列 条件分岐
3つのリールを回して絵柄を揃えるスロットマシン。所持コインの増減を管理する。
🎰 スロットマシン(所持: 100コイン) Enterで回す(1回10コイン)> | 🍒 | 🍋 | 🍒 | → ハズレ… 残り: 90コイン Enterで回す> | 7️ | 7️ | 7️ | → 🎉 ジャックポット! +500コイン! 残り: 580コイン
1
絵柄を配列で管理: char *symbols[] = {"🍒","🍋","🔔","⭐","7"};
2
3つのリールをランダムに決定: rand() % 絵柄数 を3回
3
当たり判定: 3つ揃い→大当たり、2つ揃い→小当たり、バラバラ→ハズレ
4
コイン管理: 毎回10コイン消費、当たりで加算。0以下でゲームオーバー
拡張課題
  • 絵柄ごとに配当を変える(7が揃うと高配当)
  • リールの出現確率を偏らせる(7は出にくい等)
  • ベット額を選べるようにする
  • プレイ履歴をファイルに保存して、次回起動時に読み込む
GAME 4: ○×ゲーム(三目並べ)
中級 2次元配列 関数 ループ
3×3のマスに○と×を交互に置く。先に1列揃えた方が勝ち。2次元配列で盤面を管理する。
1 | 2 | 3 ---+---+--- 4 | 5 | 6 ---+---+--- 7 | 8 | 9 Oのターン マス番号> 5 | | ---+---+--- | O | ---+---+--- | | Xのターン マス番号> 1 X | | ---+---+--- | O | ---+---+--- | |
1
盤面を2次元配列で表現: char board[3][3]。空=' ', O='O', X='X'
2
盤面表示関数: void print_board(char board[3][3]) で罫線付き表示
3
勝利判定関数: 縦3列・横3行・斜め2本の計8ラインをチェック
4
入力バリデーション: 既に埋まっているマスには置けない。1〜9以外は再入力
拡張課題
  • CPU対戦(ランダムに空いているマスを選ぶAI)を実装
  • CPUを賢くする(角を優先する、リーチを阻止する等)
  • 盤面を4×4や5×5に拡大(4目並べ)
  • 戦績をファイルに記録し、通算成績を表示
  • 完全な必勝AIをミニマックス法で実装(上級者向け)
勝利判定のコツ:
int check_win(char b[3][3], char c) {
    for (int i = 0; i < 3; i++) {
        if (b[i][0]==c && b[i][1]==c && b[i][2]==c) return 1; // 横
        if (b[0][i]==c && b[1][i]==c && b[2][i]==c) return 1; // 縦
    }
    if (b[0][0]==c && b[1][1]==c && b[2][2]==c) return 1; // 斜め
    if (b[0][2]==c && b[1][1]==c && b[2][0]==c) return 1; // 斜め
    return 0;
}
🏃
GAME 5: 迷路脱出ゲーム
中級 2次元配列 構造体 関数
2次元配列で迷路を表現し、WASDキーでプレイヤーを動かしてゴールを目指す。
################ #P.....#.......# #.####.#.#####.# #......#.#...#.# ######.#.#.#.#.# #......#...#...# #.##########.### #..............G ################ 移動 (w/a/s/d)> d
1
迷路データ: char maze[H][W] で '#'=壁、'.'=通路、'P'=プレイヤー、'G'=ゴール
2
プレイヤー座標を構造体で管理: struct Pos { int x, y; };
3
移動処理: 移動先が壁でなければ座標を更新。壁なら「進めません」と表示
4
ゴール判定: プレイヤーの座標がGの位置と一致したらクリア
拡張課題
  • 移動歩数をカウントしてスコアにする
  • アイテム(鍵)を拾わないと開かない扉を追加
  • 敵キャラ(ランダムに動く)を追加して、触れたらゲームオーバー
  • 迷路データをファイルから読み込めるようにする
  • 迷路を自動生成するアルゴリズム(穴掘り法等)に挑戦
  • 「視界」を制限する(プレイヤー周囲3マスだけ表示)
🃏
GAME 6: ブラックジャック
中級 構造体 配列 関数 乱数
トランプのブラックジャック。手札の合計を21に近づけるが、超えたらバースト。構造体でカードを管理。
🃏 ブラックジャック あなたの手札: [♠A] [♥K] → 合計: 21 ディーラー: [♦7] [??] Hit(h) / Stand(s)> s ディーラーの手札: [♦7] [♣9] → 合計: 16 ディーラー Hit: [♠5] → 合計: 21 😐 引き分け!
1
カードを構造体で表現: struct Card { int suit; int rank; }; スートと数字
2
デッキ(52枚)を配列で作ってシャッフル: Fisher-Yatesシャッフル
3
手札の合計計算関数: Aは1 or 11として最適な方を選ぶロジック
4
ディーラーのAI: 合計17以上になるまでHitし続ける(標準ルール)
拡張課題
  • 所持チップとベットの仕組みを追加
  • ダブルダウン・スプリット・サレンダーを実装
  • 複数デッキ(6デッキ等)に対応
  • カードカウンティングの練習モード
📝
GAME 7: ハングマン(単語当て)
中級 文字列 配列 ループ
隠された単語を1文字ずつ推測。間違いが一定回数でゲームオーバー。文字列操作の実践に最適。
単語を当てよう!(残りミス: 6回) _ _ _ _ _ _ _ _ _ 文字> e _ _ _ _ _ _ _ _ e ⭕ 文字> a 該当なし ❌(残り: 5回) 文字> r _ r _ _ r _ _ _ e ⭕
1
単語リストを配列で用意: char *words[] = {"programming","computer",...};
2
正解状態を配列で管理: int revealed[MAX] で各文字が開示済みかどうかを記録
3
入力文字を全位置と照合: forループで単語の全文字と比較、一致したら開示
4
終了判定: 全文字開示→勝ち、ミス上限到達→負け
拡張課題
  • AA(アスキーアート)でハングマンの絵を段階的に表示
  • 難易度で単語の長さを変える
  • 使用済み文字の一覧を表示
  • 単語リストをファイルから読み込む
  • 日本語版(ローマ字→ひらがな)に改造
⚔️
GAME 8: テキストRPGバトル
上級 構造体 ポインタ 関数 乱数
勇者と魔物のターン制バトル。構造体でキャラのステータスを管理し、攻撃・防御・回復のコマンドを選ぶ。
⚔️ スライムが現れた! 勇者 HP:100/100 MP:30/30 スライム HP:50/50 1:攻撃 2:防御 3:魔法 > 1 勇者の攻撃! スライムに 15 ダメージ! スライム HP: 35/50 スライムの攻撃! 勇者に 8 ダメージ! 勇者 HP: 92/100
1
キャラ構造体: struct Character { char name[20]; int hp, max_hp, mp, atk, def; };
2
ダメージ計算関数: int calc_damage(int atk, int def) 乱数でブレを加える
3
コマンド選択: switch文で攻撃/防御/魔法を分岐
4
バトルループ: どちらかの HP が 0 以下になるまで繰り返す
拡張課題
  • 複数の敵を配列で管理し、連戦にする
  • 経験値とレベルアップの仕組みを追加
  • アイテム(薬草等)をインベントリ(配列)で管理
  • 敵のAIを賢くする(HPが低いと回復を使う等)
  • ボス戦の特殊演出を追加
  • セーブ/ロード機能(ファイル入出力)
💣
GAME 9: マインスイーパ
上級 2次元配列 再帰 関数
地雷が埋まったマスを避けて全マスを開ける。周囲の地雷数の計算と、0マスの連鎖オープン(再帰)が核心。
1 2 3 4 5 1 . . . . . 2 . . . . . 3 . . . . . 4 . . . . . 5 . . . . . 開く (行 列)> 3 3 1 2 3 4 5 1 1 . . . 2 1 2 . . 3 1 . . 4 1 2 . 5 1 .
1
盤面を2つの2次元配列で管理: int mines[H][W](地雷配置) と int visible[H][W](開示状態)
2
地雷のランダム配置: 指定個数をランダムな位置に配置(重複回避)
3
周囲の地雷数計算: 8方向のマスを調べてカウント
4
連鎖オープン(再帰): 周囲の地雷数が0のマスを開けたら、隣接マスも自動的に開ける
拡張課題
  • フラグ機能(地雷だと思うマスにマークを付ける)
  • 最初の1手は絶対に地雷に当たらないようにする
  • 盤面サイズと地雷数を選べるようにする
  • クリアタイムを計測して表示
  • ハイスコアをファイルに記録
🧱
GAME 10: 落ちものパズル(テトリス風)
上級 2次元配列 構造体 タイマー
ブロックが上から落ちてきて、横一列揃うと消える。テキストベースでテトリス風のゲームを実装する最上級チャレンジ。
| | | | | | | ## | | ## | | | | | | # | | ### | | #### ## | +----------+ Score: 100 Level: 1
1
フィールドを2次元配列で表現: 固定済みブロックの状態を保持
2
テトリミノを構造体+配列で定義: 7種の形状を4×4配列で定義
3
衝突判定: 移動・回転先にブロックや壁がないかチェック
4
ライン消去: 横一列が埋まったら消して上を落とす
拡張課題
  • 次のブロックのプレビュー表示
  • レベルが上がると落下速度アップ
  • ホールド機能(ブロックを1つ保管)
  • スコアランキングをファイルに保存
ヒント: ターミナルでリアルタイム入力を行うには、termios.h(Linux/Mac)や conio.h(Windows)を使ってノンブロッキング入力を実装する必要があります。まずは「1手ごとに入力を待つ」ターン制バージョンから始めるのがおすすめです。

ロードマップ

上から順に難易度が上がります。まずは GAME 1〜3 から始めて、自信がついたら 4〜7 に挑戦しましょう。
入門
数当て
入門
じゃんけん
入門
スロット
中級
○×ゲーム
中級
迷路
中級
ブラックジャック
中級
ハングマン
上級
RPGバトル
上級
マインスイーパ
上級
テトリス風

ゲーム制作をさらに深めるなら

基礎を固めた上でゲーム制作に挑戦すると、実力が飛躍的に伸びます

📘
苦しんで覚えるC言語
MMGames 著
初心者向けの定番入門書。丁寧な解説で基礎を固められます。
Amazonで見る
📗
新・明解C言語 入門編
柴田望洋 著
図解が豊富で、演習問題も充実。
Amazonで見る
📙
プログラミング言語C 第2版
B.W.カーニハン, D.M.リッチー 著
通称K&R。C言語の原典。
Amazonで見る

※ 上記リンクはアフィリエイトリンクです。購入によりサイト運営を支援いただけます。

この記事をシェア
X(Twitter)でシェア Facebookでシェア LINEで送る はてブ