JavaScript
jQuery

JavaScriptで国旗クイズを作ってみる

国旗クイズを作ってみました。
約200カ国あるので、知らない国が多くて難易度高いです。

工夫したところ

国旗データはJSON形式にして、jQueryのgetJSONで読み込むようにしています。
覚えるために、正解しないと次の問題に進めないようにしました。

ハマったところ

$.getJSONを実行しても何の反応もなく困りましたが、調べたらJSONファイルの構文エラーが原因でした。
JSONの構文チェック大事。

難易度を選択時にon("click")イベントが何度も実行されました。off("click")してから次のイベントを実行しないといけないようです。

今後やりたいこと

操作性の向上。ボタン押した感とか。
サーバにアップして実機で見ると少し遅かったので、速度も上げたい。
解答時の演出。正解時のアニメーションとか効果音とか。
難易度の調整。
見た目の調整。

ブラッシュアップしました

2018.1.2追記
ボタン押した感。解答時の演出、効果音。見た目の調整。

2018.1.7追記
難易度を設定。JSとCSSを外部ファイル化。

動作サンプル

[自サイトにアップしました。](http://www.i-keita.com/flag_quiz/index.html)

コードサンプル(JavaScript)

$(function(){

    // 国旗データを読み込む
    function getFlagData() {
        return $.getJSON("flag.json", function(data){});
    }

    // 難易度 デフォルト
    var level = "1";

    // クイズ処理(イベント毎に実行したいので関数化)
    function drawFlag(level) {

        getFlagData().done(function(data){

            // 難易度調整 国旗データから該当の難易度のみ抽出
            if (level == "2") {
                data = data.filter(function(v){
                    return v.level == level || v.level == "1";
                });
            } else if (level == "3") {
                data = data.filter(function(v){
                    return v.level == level || v.level == "2";
                });
            } else {
                data = data.filter(function(v){
                    return v.level == "1";
                });
            }

            // 国旗をランダムに一つ選択する(正解)
            var q = Math.floor(Math.random() * data.length);

            // 国旗を表示
            $("#flag").html('<img src="flag_png/flag' + data[q]["id"] + '.png" />');
            var c = data[q]["id"];

            // 国旗データをシャッフルする
            var a = [];
            for (i = data.length - 1; i >= 0; i--) {
                // 0~iのランダムな数値を取得
                var rand = Math.floor(Math.random() * (i+1));

                // 配列の数値を入れ替える
                [data[i], data[rand]] = [data[rand], data[i]]
            }

            // シャッフルした国旗データから先頭の3つを取得
            for (i = 0; i < 3; i++) {
                a.push(data[i]);
            }

            // 正解が含まれているか確認し、選択肢を4つにする
            var d = false;
            for (i = 0; i < a.length; i++) {
                if (a[i]["id"] == c) {
                    d = true;
                }
            }
            // 含まれていればランダムに一つ追加
            if (d == true) {
                a.push(data[3]);
            // 含まれていなければ正解を追加
            } else {
                for (i = 0; i < data.length; i++) {
                    if (data[i]["id"] == c) {
                        a.push(data[i]);
                    }
                }
            }

            // 選択肢をシャッフルする
            for (i = a.length - 1; i >= 0; i--) {
                // 0~iのランダムな数値を取得
                var rand = Math.floor(Math.random() * (i+1));

                // 配列の数値を入れ替える
                [a[i], a[rand]] = [a[rand], a[i]]
            }

            // 選択肢を表示
            for (i = 0; i < a.length; i++) {
                $("#answer").append('<li id="li' + (i+1) + '"><a id="' + a[i]["id"] + '" href="#">' + a[i]["name"] + '</a></li>');
            }

            // 回答を選択時の処理
            $("#answer a").on("click", function(){

                // 正解すると次の問題へ
                if (this.id == c) {
                    // 効果音
                    var audio_o = new Audio("img/audio_o.mp3");
                    audio_o.play();

                    // ボタン変更
                    $(this).css("background","url(img/answer_o.png) no-repeat center");
                    $(this).css("background-size","contain");

                    // 少し時間を置いてから実行
                    setTimeout(function(){
                        $("#answer").empty();
                        $("#level a").off("click");  // イベントをオフにしないと何度もクリックイベントが実行されるので要注意
                        drawFlag(level);
                    }, 250);

                // 不正解だと選択肢を削る
                } else {
                    // 効果音
                    var audio_x = new Audio("img/audio_x.mp3");
                    audio_x.play();

                    // ボタン変更
                    $(this).css("background","url(img/answer_x.png) no-repeat center");
                    $(this).css("background-size","contain");
                }
            });

            // レベル選択
            $("#level a").on("click", function(){
                switch(this.id) {
                    case 'level1':
                        level = "1";
                        $("#level1").addClass("active");
                        $("#level2").removeClass("active");
                        $("#level3").removeClass("active");
                        break;
                    case 'level2':
                        level = "2";
                        $("#level2").addClass("active");
                        $("#level1").removeClass("active");
                        $("#level3").removeClass("active");
                        break;
                    case 'level3':
                        level = "3";
                        $("#level3").addClass("active");
                        $("#level1").removeClass("active");
                        $("#level2").removeClass("active");
                        break;
                    default:
                        level = "1";
                        break;
                }

                $("#answer").empty();
                $("#level a").off("click");  // イベントをオフにしないと何度もクリックイベントが実行されるので要注意
                drawFlag(level);
            });

        });
    }

    drawFlag(level);


    // 難易度メニュー トグル
    $("#level dd").hide();
    $("#level dt").click(function(){
        $("#level").children("dd").slideToggle("fast");
    });
    $("#level dd").click(function(){
        $("#level dd").hide();
    });


});

コードサンプル(HTML)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>国旗クイズ</title>
<link rel="stylesheet" href="flag.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="flag.js"></script>
</head>
<body>
<div id="content">
<dl id="level">
<dt>難易度</dt>
<dd><a id="level1" href="#" class="active">初級</a></dd>
<dd><a id="level2" href="#">中級</a></dd>
<dd><a id="level3" href="#">上級</a></dd>
</dl>
<div id="flag"></div>
<ul id="answer">
</ul>
</div>
</body>
</html>

コードサンプル(JSON)

[
{
    "id":"093",
    "name":"日本",
    "level":"1"
}
]