0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

IIT(Iwate Industrial Tecnology)Advent Calendar 2021

Day 19

JSでポケモン英語クイズを作ってみた

Last updated at Posted at 2021-12-18

#はじめに
 私はプログラミングの勉強をしている学生で、趣味の1つがポケモンのゲームで遊ぶことなのですが、ある日、YouTubeを見ていたら、ある動画を見つけました。
ある動画
  
 動画の内容はポケモンの技や特性などを英語にしたクイズを、ポケモンバトル系のゲーム実況者でポケモンの知識は優れているが英語の知識は人並みのライバロリさんと、東大の医学部出身で英語の知識は優れているが、ポケモンは初心者の河野玄斗さんが協力して、答えていくというものです。

 自分が好きなポケモンを通じて英語の勉強もできる神動画でした!それで、この動画のようなクイズのサイトがないかググってみたのですが、見つかりませんでした。ポケモンで英語を学ぼうだなんて無謀なんだと一瞬諦めかけたその時、ある考えが浮かびました。

だったら、自分でそのクイズサイトを作ろう!
#本題
 とは言ったものの、私は今までC言語くらいしかまともに学んでおらず、HTMLとCSSは苦手でJavaScriptは最近やり始めたくらいの実力です。なので、一から作ることは今の自分には不可能だと考えました。そこで、ネットに転がっている良さそうなソースコードをパクって、それをちょこっと変えればいいと考え、こちらのサイトのものをほぼ丸パクリして、その後に自分が作りたいクイズになるように改造しました。具体的には、クイズの中身を変えるのはもちろん、トップ画面でクイズの難易度を選べるようにしたり、解答をキーボードで入力できるようにしたり、問題の出題がランダムになるようにしたりしました。また、その他細かい動作の改造もしました。
 また、クイズの中身もポケモンをよく知っている人もあまり知らない人も楽しめるように自分なりに工夫しました。
 中には、まだ習っていない表現や関数がありましたが、なんとか自分の納得がいく出来になったので、下にソースコードの一部を載せておきます。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0, user-scalable=no">
    <title>ポケモン英語クイズ</title>
    <link rel="stylesheet" href="style.css">
    <link rel="icon" href="monsterball.png">
</head>
<body>
    <div class="p-quiz js-quiz-content">
        <h1 class="p-quiz-ttl">ポケモン英語クイズ</h1>
        <h2 class="p-quiz-sub-ttl">英語で書かれている単語や文章に合う解答をしてください。</h2>
        <div class="p-quiz-next">
            <ol class="p-quiz-choices">
                <li class="p-quiz-choices__item"><a href="quiz.html" class="c-btn">普通(技)</a></li>
                <li class="p-quiz-choices__item"><a href="quiz2.html" class="c-btn">難しい(特性)</a></li>
            </ol>
        </div>
    </div>
</body>
</html>
quiz.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0, user-scalable=no">
    <title>ポケモン英語クイズ</title>
    <link rel="icon" href="monsterball.png">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="p-quiz js-quiz-content"></div>

    <script src="main.js"></script>
</body>
</html>
result06.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0, user-scalable=no">
    <title>ポケモン英語クイズ</title>
    <link rel="icon" href="monsterball.png">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="p-quiz">
        <h1 class="p-quiz-ttl">結果は5問中0問正解でした。</h1>
        <p class="p-quiz-commentary">コイキング級です。</p>
        <div class="p-quiz-next">
            <a href="index.html" class="c-btn">トップに戻る</a>
        </div>
        <div class="Twitter">
            <a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-show-count="false">Tweet</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
        </div>
    </div>

    <script src="main.js"></script>
</body>
</html>
style.css
body{
    background-image: url(black_00070.jpg);
    background-repeat: no-repeat;
    background-size: cover;
    height: 100vh;
    color: white;
}
.c-btn {
    -webkit-appearance: none;
    appearance: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 40px;
    padding: 0;
    border: none;
    outline: none;
    color: white;
    font-size: 16px;
    text-decoration: none;
    background: gray;
    cursor: pointer;
}
/* ボタンにカーソルが乗ったときに色が変わる。 */
.c-btn:hover {
    background-color:darkgray;
}
.p-quiz {
    width: 600px;
    margin: 300px auto;
    text-align: center;
}
.p-quiz-ttl{
    margin: 0 0 10px;
    font-size: 40px;
    font-weight: normal;
    text-align: center;
}
.p-quiz-sub-ttl{
    margin: 0 0 20px;
    font-size: 20px;
    font-weight: normal;
    /* text-align: center; */
}
.kouka{
    text-align:center;
    padding-top:25px;
}
h2{
    /* width: 1000px; */
    text-align: center;
}

.p-quiz-next {
    width: 300px;
    margin: auto;
}
.p-quiz-choices {
    display: inline-flex;
    flex-wrap: wrap;
    width: 100%;
    /* margin: 20px; */
    padding-left: 0;
}
.p-quiz-choices__item {
    width: calc(50% - 20px);
    list-style: none;
    margin: 7px;
}
.Twitter{
    margin-top: 80px;
}
#name{
    width:300px;
}
#written{
    margin-left:10px;
/*     background-color:; */
    color: white;
    background-color:gray;
    border: none;
    cursor: pointer;
    padding-left:15px;
    padding-right:15px;
    padding-top:5px;
    padding-bottom:5px;
    border-radius:10px;
}
#written:hover{
    background-color:darkgray;
}

@media screen and (max-width: 480px) {
	/* 480px以下に適用されるCSS(スマホ用) */
    .p-quiz{
        width: 100%;
        margin: 150px auto;
    }
}
main.js
let quizData = [    //問題の一部です。。
    [
        ['Bite',['あくのはどう','イカサマ','かみつく','わるだくみ'],2,'正解はかみつくで、Biteは噛むという意味。'],
        ['Painsplit',['いたみわけ','いのちがけ','おんねん','いやなおと'],0,'正解はいたみわけで、Painは痛み、Splitは分割という意味。'],
        ['Ice Fang',['こおりのつぶて','こおりのキバ','こごえるかぜ','れいとうビーム'],1,'正解はこおりのキバで、Iceは氷、Fangは牙という意味。'],
        ['Scald',['いあいぎり','どくどく','ねっとう','みずびたし'],2,'正解はねっとう。'],
        ['Leech Seed',['すいとる','タネばくだん','なやみのタネ','やどりぎのタネ'],3,'正解はやどりぎのタネで、Leechは吸う、Seedはタネという意味。']
    ],
    [
        [5,'result01.html'],
        [4,'result02.html'],
        [3,'result03.html'],
        [2,'result04.html'],
        [1,'result05.html'],
        [0,'result06.html']  
    ]
];      
let currentQuizNo;      //現在の問題番号
let quizCount = 0;      //現在の問題数
let correctCount = 0;   //正解数
let experience = [];    //既に出題した問題を入れるための配列
let exCount = 0;        //experience配列の添え字に使う用
 
// 問題データの取得
get_quiz_data();

/**
 * 問題のデータを取得する
 * 
 */
function get_quiz_data() {      /* 1 */
    // let xhr = new XMLHttpRequest();
    // xhr.onload = function() {
    //     quizData = xhr.response;
        // 問題画面の生成
    generate_quiz_content();    /**2 */
        // 問題の選択肢を選択したときのイベント設定
    register_choice_event();    /**3 */
//     }
//     xhr.open('GET', 'quiz.json');
//     xhr.responseType = "json";
//     xhr.send();
// }
}
 
/**
 * 問題の選択肢を選択したときのイベントを設定する
 * 
 */
function register_choice_event() {  /*3*/
    for (var i = 0; i < document.querySelectorAll('.js-quiz-choice').length; i++) {
        document.querySelectorAll('.js-quiz-choice')[i].addEventListener('click', function(e) {
            // 回答・解説画面の生成
            //getAttribute()...()内の属性の値を取得する。
            //parseFroat()...()内の文字列を浮動小数点数に変換
            generate_answer_content(parseFloat(this.getAttribute('data-quiz_choice')));     /**3-1 */
            // 未回答の問題がある場合
            if(quizCount + 1 < 5) {
                // 次の問題へ遷移するときのイベント設定
                register_nextquiz_event();  /**3-2 */
            }
        }, false);
    }
}
 
/**
 * 次の問題へ遷移するときのイベントを設定する
 * 
 */
function register_nextquiz_event() {    /*3-2*/ 
    document.querySelector('.js-quiz-next').addEventListener('click', function() {
        quizCount++;
        // 問題画面の生成
        generate_quiz_content();    /*2*/
        // 問題の選択肢を選択したときのイベント設定
        register_choice_event();    /*3*/
    }, false);
}
 
/**
 * 問題画面を生成する
 * 
 */
function generate_quiz_content() {      /*2*/
    while(true){    //重複しない乱数を生成
        let num = Math.floor(Math.random()*quizData[0].length);
        if(!experience.includes(num)){
            experience.push(num);
            break;
        }
    }
    currentQuizNo = experience[exCount];
    exCount++;

    var ins = '<h1 class="p-quiz-ttl">' + quizData[0][currentQuizNo][0] + '</h1>';
    ins += '<ol class="p-quiz-choices">';
        for (var i = 0; i < quizData[0][currentQuizNo][1].length; i++) {
            ins += '<li class="p-quiz-choices__item">';
                ins += '<button class="c-btn js-quiz-choice" data-quiz_choice="' + i + '">' + quizData[0][currentQuizNo][1][i] + '</button>';
            ins += '</li>';
        }
    ins += '</ol>';
 
    document.querySelector('.js-quiz-content').innerHTML = ins;
}

//  * 回答・解説画面を生成する
function generate_answer_content(choice) {      /*3-1*/
    var ins = '<h1 class="p-quiz-ttl">' + quizData[0][currentQuizNo][0] + '</h1>';
    // 正解の場合
    if(quizData[0][currentQuizNo][2] == choice) {
        ins += '<p class="p-quiz-result">正解</p>';
        correctCount++;
    // 不正解の場合
    } else {
        ins += '<p class="p-quiz-result">不正解</p>';
    }
    ins += '<p class="p-quiz-commentary">' + quizData[0][currentQuizNo][3] + '</p>';
    // 未回答の問題がある場合
    if(quizCount + 1 < 5) {
        ins += '<div class="p-quiz-next">';
            ins += '<button class="c-btn js-quiz-next">次の問題</button>';
        ins += '</div>';
    // 全て回答済の場合
    } else {
        ins += '<div class="p-quiz-next">';
        for (var i = 0; i < quizData[1].length; i++) {
            if(correctCount === quizData[1][i][0]) {
                ins += '<a href="' + quizData[1][i][1] + '" class="c-btn">結果を見る</a>';
                break;
            }
        }
        ins += '</div>';
    }
 
    document.querySelector('.js-quiz-content').innerHTML = ins;
}

   
  こんな感じの画面になりました。
スクリーンショット (29).png
※画面は開発中のものです。

スクリーンショット (31).png

まだまだ、ソースコードはあるのですが、上のコードと大体同じなのでここでは省略します。
クイズはこちらから遊べます。
#さいごに
なんとか形にはなったので、ある程度満足ですが、効率の悪い書き方をしていたり、画面レイアウトが殺風景だったりするので、まだまだ勉強しなきゃならないとも思いました。感想や意見などがありましたら、コメント欄にお書きください。気が向いたら、改善します。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?