前回は暗記カードの外側を作成していきました。
今回は内部の処理を追加していきます。
ウェブアプリ、「問題データ」の作成
外側の部分は概ね完了したので、次は内部の処理を作成していきます。
まずは問題用のデータを作成しましょう。
問題のデータは、問題、回答というペアのデータです。
この時、問題と回答の内容を一つ一つ変数に入れると
どの変数に問題があって、どの回答の変数に関係しているのか
把握することが難しくなってしまうので、
データ構造は配列を利用して下記のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 |
var data = [ ['Dog','犬'] ,['Cat','猫'] ,['Apple','りんご'] ,['Egg','卵'] ] //確認 //console.log(data[0][0]) //1問目の問題が表示される //console.log(data[0][1]) //1問目の回答が表示される //console.log(data[1][0]) //2問目の問題が表示される //console.log(data[1][1]) //2問目の回答が表示される |
以前学んだ配列の応用です。配列の要素にさらに配列を入れることができます。
これを多次元配列を言います。多次元配列を利用することで問題と回答の参照
がしやすくなります。
多次元配列を使おう
例で説明すると
dataの最初の添字が問題番号、次の添字が0の場合は問題、1の場合は回答になります。
図で書き表すと次のようになります。
理解てきたら問題表示を行いましょう。
ウェブアプリの問題表示機能作成の前準備
問題データの作成が完了したので問題を表示する処理を作っていきます。
問題を表示するケースは『次の問題』をクリックされたときです。
ですので、『次の問題』ボタンがクリックされた場合に画面に表示する処理を追加します。
クリックイベントです。
前回まで作成したHTMLは次のようになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" type="text/css" href="style.css"> <title>暗記ゲーム</title> </head> <body> <div> 遣唐使の廃止年は?<br> <input type="text" value=""><br> <input type="button" value="回答!"> <input type="button" value="次の問題!"> </div> <img src="neko-hutuu.png"> <img src="hart0.png"> <img src="hart0.png"> <img src="hart0.png"> </body> </html> |
CSS
1 2 3 4 5 6 7 8 9 |
div{ background-color:#9ef442; margin:20px; padding:10px; } img{ max-width:20%; } |
ここにjavascriptを組み込んでいきます。 ファイル名はmain.jsとしましょう。
HTMLのヘッダにjsの読み込みを忘れないようにしてください。
また、jQueryを利用するので、次のjQueryの読み込みも忘れずに書くように
してください。
1 2 3 4 |
<script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script> |
それでは、処理を書いていきます。
まずは『次の問題』ボタンの処理を書いていきましょう。
先ほども書きましたが、ボタンをクリックされたときに実行する処理のため、
クリックイベントを作成していきます。
クリックボタンを2個作る
処理を書いていく中で、注意することがあります。
今回はボタンが2あります。「回答」と「次の問題」ボタンです。
クリックイベントを作成する場合、セレクタが必要ですが、セレクタに『input』と書くと
3つも当てはまるものがあります。(入力欄、ボタン2つ)このままだと
3つのうち、どれかがクリックされたときにイベントが発生してしまうので、idまたはクラスを使って
どのボタンがクリックされたか明確にします。
今回は「次の問題」の表示機能を作るので、まずは『次の問題』ボタンにidをつけましょう。
id名は『next_question』にします。
1 2 3 4 5 6 7 8 9 10 11 12 |
<body> <div> 遣唐使の廃止年は?<br> <input type="text" value=""><br> <input type="button" value="回答!"> <input type="button" id="next_question" value="次の問題!"> </div> <img src="chara0.png"> <img src="hart0.png"> <img src="hart0.png"> <img src="hart0.png"> </body> |
idを追加しました。
ではイベントを作成していきます。
画面に出す前にデータの確認として、まずは
next_questionが押されたら最初の問題と回答をアラートで出すようにしましょう。
1 2 3 4 5 6 7 8 9 10 11 |
var data = [ ['Dog','犬'] ,['Cat','猫'] ,['Apple','りんご'] ,['Egg','卵']; ] $(document).on('click', '#next_question', function(){ alert(data[0][0]); alert(data[0][1]); }); |
dogと表示されない人は次の点に問題がないか確認してください。
- jQueryが読み込まれていること
- main.jsの読み込みが行われていること
- ボタンにidが付いていること
- jsのセレクタに誤りがないこと
問題と回答は表示されましたか?
表示されたら次のステップです。
ウェブアプリで次の問題を表示するには
現状、alertで表示している問題は添字0にしているので、何回ボタンを押しても
同じ問題が表示されます。
これを、ボタンを押すたびに配列の次の問題が出力されるようにする必要があります。
考え方は単純です。
同じ問題が出題される原因は最初の添字が常に0ということなので、
この部分を改善していきます。
解決策として、今回は、問題を格納している配列の添字を変数にして
その変数を『次の問題』を押すごとに増やしていきます。
次のプログラムを見てください。
questionNumberを追加しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var questionNumber = 0; var data = [ ['Dog','犬'] ,['Cat','猫'] ,['Apple','りんご'] ,['Egg','卵'] ]; $(document).on('click', '#next_question', function(){ alert(data[questionNumber][0]); alert(data[questionNumber][1]); questionNumber++; }); |
次のボタンを押すたびにquestionNumberが増えていくので
配列の次の問題が表示されていきます。
ここまでOKですね。
それでは今度はアラートではなく、実際に問題と回答を表示してみましょう。
ウェブアプリの問題表示処理の作成
それでは問題の表示を行なっていきます。
今まで習ってきたHTMLの書き換えを思い出すと、問題表示の変更は次のように
書けることがわかりますね。
1 2 3 4 |
$(document).on('click', '#next_question', function(){ $('div').text(data[questionNumber][0]); questionNumber++; }); |
プログラムの内容としては、
#next_questionがクリックされたら、divの中身をdata(questionNumber)[0]にしろ!
ということになりますが、実際に実行してみると『dog』だけが表示されます。
せっかく作ったテキストやボタンも全て消えてしまいます。
『divの中身をdog』にしろという命令ですので当然と言えば当然です。
これを解消するために、問題を表示しているdivの中にテキスト表示専用の場所を作ります。
HTMLは次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<body> <div> <span id="mondai">遣唐使の廃止年は?</span> <br> <input type="text" value=""><br> <input type="button" value="回答!"> <input type="button" id="next_question" value="次の問題!"> </div> <img src="neko-hutuu.png"> <img src="hart0.png"> <img src="hart0.png"> <img src="hart0.png"> </body> |
今まで、問題はHTMLで囲まれていなかったのですが、spanで囲って、idを付加しました。
これで、spanの中身のみを指定して内容を変更可能になり、
そのほかのdivの中身に影響を与えないようにすることができるようになりました。
先ほどのjavascriptの内容は次のように書き換えましょう。
1 2 3 4 |
$(document).on('click', '#next_question', function(){ $('#mondai').text(data[questionNumber][0]); questionNumber++; }); |
クリックするたびに問題の内容が切り替わっていきますね。
これで問題の表示ができました。
問題は配列から出題するので、最初に表示している
『遣唐使の廃止年は?』は消しておきましょう。
次は回答の処理です。
ウェブアプリの回答処理の考え方
回答ボタンの処理も考えてみましょう。
回答ボタンを押した場合は配列に格納されたデータと、入力欄に入力された内容を
比較して同じであれば、正解と表示します。
それ以外は不正解と表示します。
処理に必要なものは、次の通りです。
- ユーザから入力された値
- 配列に入っている値[問題番号][1]の内容
- 1,2の比較
ですね。
1は以前行った、jQueryの値取得val()で実現できそうです。
2についても問題所得時に利用している変数(questionNumber)が利用できますね。
では実際に、回答ボタンを回答ボタンを押したときのイベントを作成してみましょう。
まずは、回答が一致していたらアラートで『正解』または『不正解』と出すようにしましょう。
ウェブアプリの回答処理の作成
プログラムをみてみましょう。
回答ボタンをクリックしたらイベントを起こしたいのですが、先ほどの
次の問題ボタンと同じようにinputだけでは区別がつかないのでまずは
idをつけましょう。idは『answer_button』とします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<body> <div> <span id="mondai"></span> <br> <input type="text" value=""><br> <input type="button" id="answer_button" value="回答!"> <input type="button" id="next_question" value="次の問題!"> </div> <img src="neko-hutuu.png"> <img src="hart0.png"> <img src="hart0.png"> <img src="hart0.png"> </body> |
idを追加しました。
これを元にイベントを作成していきます。
回答ボタンが押された時のイベントの書き方は次のようになりますね。
1 2 3 4 |
//回答ボタンの処理 $(document).on('click', '#answer_button', function(){ //処理を書く }); |
処理の内容は先ほど整理した通りです。
まずは入力欄に入力された内容を取得しましょう。
少し上のHTMLをみてもらうとわかるのですが、入力欄にもidまたはclassがないため
入力欄に入力された内容の取得が難しいです。この部分にもidをつけましょう。
id名はinput_answerにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<body> <div> <span id="mondai"></span> <br> <input type="text" id="input_answer" value=""><br> <input type="button" id="answer_button" value="回答!"> <input type="button" id="next_question" value="次の問題!"> </div> <img src="neko-hutuu.png"> <img src="hart0.png"> <img src="hart0.png"> <img src="hart0.png"> </body> |
これでjQueryで値を取得しやすくなりました。
先ほどのjsファイルで入力欄の値を取得すると次のようになります。
1 2 3 4 5 |
//回答ボタンの処理 $(document).on('click', '#answer_button', function(){ //入力された値を持ってくる var inputValue = $('#input_answer').val(); }); |
次は配列に格納された回答の内容を取得します。
1 2 3 4 5 6 7 8 9 |
//回答ボタンの処理 $(document).on('click', '#answer_button', function(){ //入力された値を持ってくる var inputValue = $('#input_answer').val(); //配列の内容を変数に入れる var arrayAnswer = data[questionNumber-1][1]; }); |
questionNumberを-1しています。
理由は次の問題を押した段階でquestionNumberが+1されてしまうので
そのままquestionNumberを回答取得のための添字として利用すると
1つ先の回答を持ってきてしまうためです。
理解できましたか?
OKですね。これで必要なデータは揃ったので比較していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//回答ボタンの処理 $(document).on('click', '#answer_button', function(){ //入力された値を持ってくる var inputValue = $('#input_answer').val(); //配列の内容を変数に入れる var arrayAnswer = data[questionNumber-1][1]; //入力された内容と配列の回答を比較 if(inputValue == arrayAnswer){ alert("正解"); }else{ alert("不正解"); } }); |
ゲームっぽくなってきましたね。
ひとつ気になるとことがあります。
index.htmlを最初に開いた場合、問題が出ていません。
『次の問題』を押さないといけないです。
ゲームをプレイする人にとって手間になるので、
ウェブアプリを開くとすぐ問題が出るようにする
画面の表示した段階で問題が出るように修正しましょう。
修正についてですが、jquery,javascriptには画面読み込み完了時に処理を
実行させることができます。
書き方は次の通りです。
1 2 3 |
$(window).on('load',function(){ //処理 }); |
処理の内容に読み込み完了後に実行したい処理を書くことで、
HTML読み込み完了後に自動的に実行してくれます。
今回は『次の問題ボタン』を押して欲しいので、triggerを使ってみましょう。
プログラム全体は次のようになります。
1 2 3 4 |
//画面読み込み時の処理 $(window).on('load',function(){ $('#next_question').trigger('click'); }); |
これを書くことで画面表示の際に1問目が自動的に読み込まれていると思います。
今回は以上です。次回は回答結果によって画像を変更したりします。