【6日でできるJava入門】クイズゲームの改造②(ジャンルを増やす)

 クイズゲームをより楽しく、学習範囲を広げるためには、ジャンル(カテゴリ)を選べる仕組みが有効です。ここでは、もともと「県庁所在地クイズ」のみだったプログラムを、「世界史」「日本史」ジャンルにも対応できるように改造します。
加えて、前ステップで搭載した「チートモード(正解を出題時に表示)」もそのまま全ジャンルで利用できます。
 複数ジャンル対応にすることで、クイズデータの読み込み管理・ジャンル選択処理・ユーザインターフェースの切り替えなど、Javaプログラムの構造設計力も身につきます。

1.ジャンル選択機能の概要

1.1. ジャンルの種類と役割

プログラム開始時にユーザーがジャンル(出題範囲)を選べるようにします。
今回用意するジャンルは以下の3つです。

ジャンル内容問題数データファイル名
県庁所在地都道府県と県庁所在地47prefectures.txt
世界史世界史クイズ50world_history.txt
日本史日本史クイズ50japanese_history.txt

ジャンルごとに別ファイルで問題データを管理します。

1.2. ジャンル選択の仕組み

  • ゲーム開始時にジャンル一覧を画面表示
  • ユーザーは数字でジャンルを選択する
  • 選択結果に応じて、対応する問題データファイルを読み込みクイズを出題
  • すべてのジャンルでチートモード(コマンドライン引数 "cheat")は利用可能

2.ジャンル選択付きクイズ処理の構造と実装

2.1. ジャンル選択部分のロジック

  1. ジャンル一覧を表示
  2. ユーザーに番号を入力してもらう(1: 県庁所在地, 2: 世界史, 3: 日本史)
  3. 入力に応じてデータファイル名と問題タイトルを決定

ジャンル選択サンプル

System.out.println("ジャンルを選んでください:");
System.out.println("1: 県庁所在地クイズ");
System.out.println("2: 世界史クイズ");
System.out.println("3: 日本史クイズ");
System.out.print("==> ");

入力値(1/2/3)を判定し、ファイル名やタイトルを決定します。

2.2. 改造したクイズゲーム全体プログラム

ファイル名: Quiz_Game.java

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Random;

public class Quiz_Game {
    public static void main(String[] args) throws Exception {
        // チートモード判定
        boolean cheatMode = (args.length > 0 && args[0].equals("cheat"));

        // ジャンル選択
        System.out.println("ジャンルを選んでください:");
        System.out.println("1: 県庁所在地クイズ");
        System.out.println("2: 世界史クイズ");
        System.out.println("3: 日本史クイズ");
        System.out.print("==> ");
        byte[] b = new byte[128];
        int genre;
        while (true) {
            System.in.read(b);
            try {
                genre = Integer.parseInt((new String(b)).trim().substring(0, 1));
                if (genre >= 1 && genre <= 3) {
                    break;
                } else {
                    System.out.println("1~3の数字で選んでください。");
                    System.out.print("==> ");
                }
            } catch (Exception e) {
                System.out.println("数字を入力してください。");
                System.out.print("==> ");
            }
        }

        // ジャンルごとのファイル名・タイトル・問題数
        String fileName = "";
        String questionTitle = "";
        int questionCount = 10; // デフォルト
        switch (genre) {
            case 1:
                fileName = "prefectures.txt";
                questionTitle = "次の都道府県の県庁所在地はどれ?";
                questionCount = 10;
                break;
            case 2:
                fileName = "world_history.txt";
                questionTitle = "世界史クイズ:次の解答群で正しいものはどれ?";
                questionCount = 10; // 変更可
                break;
            case 3:
                fileName = "japanese_history.txt";
                questionTitle = "日本史クイズ:次の解答群で正しいものはどれ?";
                questionCount = 10; // 変更可
                break;
        }

        // データ読み込み
        ArrayList<String> questions = new ArrayList<String>();
        ArrayList<String> answers = new ArrayList<String>();
        BufferedReader br = new BufferedReader(new FileReader(fileName));
        String line;
        while ((line = br.readLine()) != null) {
            int idx = line.indexOf(',');
            questions.add(line.substring(0, idx));
            answers.add(line.substring(idx + 1));
        }
        br.close();

        // クイズ開始
        int score = 0;
        Random rand = new Random();
        for (int i = 1; i <= questionCount; i++) {
            if (questions.size() == 0) break; // 問題が足りない場合
            int qIdx = rand.nextInt(questions.size());
            String questionText = questions.remove(qIdx);
            String correctAns = answers.remove(qIdx);

            // 選択肢リスト作成
            ArrayList<String> choices = new ArrayList<String>();
            ArrayList<String> backupAnswers = new ArrayList<String>(answers);
            for (int j = 0; j < 3; j++) {
                if (backupAnswers.size() == 0) break;
                int cIdx = rand.nextInt(backupAnswers.size());
                choices.add(backupAnswers.remove(cIdx));
            }
            int insertIdx = rand.nextInt(choices.size() + 1);
            choices.add(insertIdx, correctAns);

            // 問題・選択肢の表示
            System.out.println(i + "問目:" + questionTitle);
            System.out.println("「" + questionText + "」");
            for (int j = 0; j < choices.size(); j++) {
                System.out.println((j + 1) + ":" + choices.get(j));
            }

            // チートモード時は正解を表示
            if (cheatMode) {
                System.out.println("【チートモード】正解は「" + correctAns + "」です。");
            }

            // 入力受付とチェック
            int answer;
            while (true) {
                System.out.print("==> ");
                System.in.read(b);
                try {
                    answer = Integer.parseInt((new String(b)).trim().substring(0, 1));
                    if (answer >= 1 && answer <= 4) {
                        break;
                    } else {
                        System.out.println("1~4の数字で選んでください。");
                    }
                } catch (Exception e) {
                    System.out.println("数字を入力してください。");
                }
            }
            answer--;

            // 判定
            if (answer == insertIdx) {
                score++;
                System.out.println("正解です!");
            } else {
                System.out.println("不正解。正解は「" + correctAns + "」です。");
            }
            System.out.println();
        }
        System.out.println("全" + questionCount + "問終了!あなたの得点は " + score + " 点です。");
    }
}

3.ジャンルごとのクイズデータ例

Eclipseでは、これらのファイルをプロジェクト直下に配置します。

(1)prefectures.txt(県庁所在地)例

北海道,札幌
青森県,青森
岩手県,盛岡
宮城県,仙台
秋田県,秋田
山形県,山形
福島県,福島
茨城県,水戸
栃木県,宇都宮
群馬県,前橋
埼玉県,さいたま
千葉県,千葉
東京都,東京
神奈川県,横浜
新潟県,新潟
富山県,富山
石川県,金沢
福井県,福井
山梨県,甲府
長野県,長野
岐阜県,岐阜
静岡県,静岡
愛知県,名古屋
三重県,津
滋賀県,大津
京都府,京都
大阪府,大阪
兵庫県,神戸
奈良県,奈良
和歌山県,和歌山
鳥取県,鳥取
島根県,松江
岡山県,岡山
広島県,広島
山口県,山口
徳島県,徳島
香川県,高松
愛媛県,松山
高知県,高知
福岡県,福岡
佐賀県,佐賀
長崎県,長崎
熊本県,熊本
大分県,大分
宮崎県,宮崎
鹿児島県,鹿児島
沖縄県,那覇

(2)world_history.txt(世界史)例

ピラミッドを建設した文明,古代エジプト
ローマ帝国の初代皇帝,アウグストゥス
産業革命が始まった国,イギリス
マグナ・カルタが制定された年,1215
アメリカ独立戦争が始まった年,1775
フランス革命が始まった年,1789
ノルマンディー上陸作戦が行われた年,1944
モンゴル帝国を築いた指導者,チンギス・ハン
アテネの民主政治を発展させた指導者,ペリクレス
大航海時代に世界一周を達成した人物,マゼラン
中国で最初に統一国家を築いた王朝,秦
ナポレオンが敗れた戦い,ワーテルローの戦い
ルネサンス発祥の地,イタリア
大西洋三角貿易で輸送された主なもの,奴隷
黒死病と呼ばれた疫病,ペスト
ルターが宗教改革を始めた国,ドイツ
南アフリカでアパルトヘイトを撤廃した大統領,ネルソン・マンデラ
第二次世界大戦のきっかけとなった国,ドイツ
インド独立運動の指導者,マハトマ・ガンジー
スパルタクスの反乱が起きた国,ローマ
パクス・ロマーナの意味,ローマの平和
冷戦時代の二大陣営,アメリカとソ連
アメリカ南北戦争が終結した年,1865
プロイセン王国の初代首相,ビスマルク
ビザンツ帝国の都,コンスタンティノープル
大化の改新を行った日本の天皇,孝徳天皇
ヴェルサイユ条約が締結された年,1919
ギリシャ神話の主神,ゼウス
大憲章マグナ・カルタを発布したイギリス王,ジョン王
ポリスと呼ばれた都市国家の代表例,アテネ
アメリカの奴隷解放宣言を出した大統領,リンカーン
古代インドの宗教家で仏教を開いた人物,ガウタマ・シッダールタ
十字軍遠征の目的,聖地エルサレムの奪還
ロシア革命の指導者,レーニン
ベルリンの壁が崩壊した年,1989
メソポタミア文明の楔形文字を使った民族,シュメール人
ヒトラー率いる政党,ナチス
スペインが新大陸を征服した探検家,コロンブス
イタリアの探検家でアジアを旅した人物,マルコ・ポーロ
マヤ文明が栄えた地域,中央アメリカ
太平洋戦争が始まった年,1941
ルイ14世が築いた豪華な宮殿,ヴェルサイユ宮殿
ギリシャの哲学者で「国家」を著した人物,プラトン
米ソ冷戦下で始まった宇宙開発競争の象徴的出来事,アポロ11号月面着陸
イギリスの王政復古を果たした王,チャールズ2世
ロシアの最初の皇帝(ツァーリ),イヴァン4世
第一次世界大戦の引き金となった事件,サラエボ事件
中国の三国時代で蜀を建国した人物,劉備

(3)japanese_history.txt(日本史)例

日本最初の元号,大化
聖徳太子が建立した寺院,法隆寺
大宝律令が制定された時代,飛鳥時代
平安京を建設した天皇,桓武天皇
最初の征夷大将軍,坂上田村麻呂
源頼朝が開いた幕府,鎌倉幕府
承久の乱を起こした天皇,後鳥羽天皇
元寇の襲来を撃退した武将,北条時宗
南北朝時代に活躍した武将,楠木正成
室町幕府を開いた人物,足利尊氏
応仁の乱が始まった年,1467
戦国時代を終結させた大名,徳川家康
本能寺の変で倒れた人物,織田信長
関ヶ原の戦いが起きた年,1600
江戸幕府の三代将軍,徳川家光
鎖国体制を完成させた将軍,徳川家光
島原の乱が起きた藩,天草藩
八代将軍吉宗の改革,享保の改革
田沼意次の政治で奨励された産業,株仲間
松平定信の行った改革,寛政の改革
幕末に大政奉還を行った将軍,徳川慶喜
明治維新で成立した新政府の政治体制,五箇条の御誓文
廃藩置県が実施された年,1871
西南戦争の指導者,西郷隆盛
日本初の憲法,大日本帝国憲法
初代内閣総理大臣,伊藤博文
日清戦争の講和条約,下関条約
日露戦争の講和条約,ポーツマス条約
関東大震災が発生した年,1923
満州事変が起こった年,1931
太平洋戦争が始まった年,1941
日本がポツダム宣言を受諾した年,1945
日本国憲法が施行された年,1947
サンフランシスコ平和条約が結ばれた年,1951
東京オリンピックが初開催された年,1964
高度経済成長期を象徴する新幹線,東海道新幹線
沖縄が日本に復帰した年,1972
バブル経済が崩壊した年,1991
平成元年,1989
令和元年,2019
遣唐使の派遣をやめた天皇,桓武天皇
大化の改新を行った人物,中大兄皇子
百人一首を編集した人物,藤原定家
江戸時代にオランダ語の翻訳で知られる人物,杉田玄白
農民一揆で有名な江戸時代の改革,天保の改革
ペリーが浦賀に来航した年,1853
明治時代の自由民権運動家,板垣退助
太平洋戦争中の首相,東條英機
敗戦後の連合国軍最高司令官,マッカーサー

4.クイズゲームの実行方法

 今回のサンプルプログラムでは、「cheat」というキーワードをコマンドライン引数として指定すると、チートモードで動作します。

コマンドラインで実行する場合

引数が「cheat」ならチートモード、それ以外は通常モードで動作します。

# チートモード(正解を表示)
java Quiz_Game cheat

# 通常モード(正解は表示しない)
java Qiuiz_Game

Eclipseで実行する場合

メニューの「実行」→「実行構成」をクリックします。

「引数」のタブで、「プログラムの引数」に「cheat」と入力し、「実行」ボタンをクリックします。

実行結果例

ジャンルを選んでください:
1: 県庁所在地クイズ
2: 世界史クイズ
3: 日本史クイズ
==> 2
1問目:世界史クイズ:次の解答群で正しいものはどれ?
「ビザンツ帝国の都」
1:ワーテルローの戦い
2:1865
3:コンスタンティノープル
4:コロンブス
【チートモード】正解は「コンスタンティノープル」です。
==> 3
正解です!

2問目:世界史クイズ:次の解答群で正しいものはどれ?
「ヴェルサイユ条約が締結された年」
1:1919
2:ビスマルク
3:1865
4:奴隷
【チートモード】正解は「1919」です。
==> 

まとめ

  • ジャンル選択でクイズの幅が大きく広がる。
  • データファイルの切り替えと読み込み、タイトル・問題数の変更も柔軟に対応
  • チートモードも全ジャンルで共通に動作
  • データファイルをジャンルごとに増やせば、他ジャンルへの応用も容易

この構造を元に、さらに新ジャンルの追加や出題数の調整も簡単にできます。