【JavaScript】アプリで実装したい機能のアルゴリズムを考える

【Railsでアプリ開発中】プログラミング初心者の勉強ブログ #38

こんにちは。

38日目。JavaScriptでアルゴリズムを考える回。配列操作、条件分岐、繰り返しを用いたアルゴリズム具体例。(フローチャートも作成)。ユーザーが入力した条件で問題が出るようにするにはどのように関数を組めば良いか。

はじめに

この記事は、railsフレームワークでオリジナルwebアプリ「免許学科試験学習サイト」作成中の僕が、プログラミングをしている中で気づいたことや学んだことを書いております。プログラミング初心者なので知識は少ないですが、現在通っているプログラミングスクール「DIVE INTO CODE」で学んでいることや、ネットで見つけた様々な記事を参考に記事を作成しております。

 

目次

[toc]

 

前回までの内容

前回(【Ruby】eachを動的に使う方法(〇〇.each_with_index)JavaScriptとの連携)はeachを動的に使い、eachの繰り返し文を用いて表示した文章1つ1つに対して、JavaScriptで動きをつけていくことをしました。

今回は免許アプリの「一問一答機能」でユーザーが選択した範囲の問題のみ抽出するため、JavaScriptでアルゴリズムを考えていきます。

一問一答画面

 

 アプリに実装したい機能のアルゴリズムを考える

今回の機能実装における流れです。

1、やりたいこと・機能を明確にする

アルゴリズムを考えるために、まず自分がやりたいことを明確にしなければなりません。

自分が作りたいアプリの機能が曖昧だと、アルゴリズム考えていくうちにブレてまとまらなくなります。

今回僕は「免許アプリの一問一答」に「ユーザーが選択した(問題数を選ぶ)、(出題範囲を選ぶ)、(問題を選ぶ)それぞれの条件に該当した問題をランダムに出せる機能」を作ります。

 

ちなみに、ユーザーの選択肢は以下の通りです。

 

(問題数を選ぶ)

・・・5、10、15、20、30から選択

 

(出題範囲を選ぶ)

・・・全ての範囲から出題 or 仮免許の範囲から出題 or 分野別に出題(27分野)から選択

 

(問題を選ぶ)

・・全ての問題から出題 or 間違った問題から出題(ログインユーザーのみ)から選択

 

これらの条件をユーザーが選択し、それに対応した問題を抽出する必要があります。

 

2、フローチャートを作成する

条件をどのような手順でどう処理すれば問題が抽出できるか、フローチャートを作成し考えます。

※フローチャートについては、(【DIVE INTO CODE】第2回授業レポート「成績判定プログラム」のフローチャート作成)にて説明しております。

今回の場合、

フローチャート

フローチャートはこんな感じになります。 ただ、問題数はユーザーの選択した値をそのまま使えば良いので、5問から順番にイエスノーを繰り返す必要はなく実際には分岐を書いてません。

ちなみに、フローチャートはdraw.ioで簡単に書くことができます。上のフローチャートもこれで作成しました。

3、実際にコードを書く

あとはコードを書くだけ。と言っても難しいんですが。

実際に書いたコードです。

    var select_num = $('#select_num').val();
    var select_field = $('#select_field').val();
    var select_questions = $('#select_questions').val();
   #セレクトボックスでユーザーが入力した値を変数に格納。 
 
    function random(array, num) {
      var a = array;
      var t = [];
      var r = [];
      var l = a.length;
      var n = num < l ? num : l;
      while (n-- > 0) {
        var i = Math.random() * l | 0;
        r[n] = t[i] || a[i];
        --l;
        t[i] = t[l] || a[l];
      }
      return r;
    };
   #配列(array)から特定の数(num)ランダムに選択する関数を定義。

    function selectdFieldQuestions(){
      if(select_field == "all_fields"){
    #「出題範囲を選ぶ」で全ての問題を選択したとき
        fieldIdArray = gon.questions;
    #「gon.questions」の中にある全ての問題をそのまま「fieldIdArray」へ。
      }else if(select_field == "temporary"){
    #「出題範囲を選ぶ」で仮免許の範囲の問題を選択したとき
        var temporary = [];
    #仮免許問題idを入れる配列を定義。
        for (var i = 0;  i < gon.fields.length; i++) {
          if(gon.fields[i].temporary == true){
            temporary.push(gon.fields[i].id);
          }; #分野データ「gon.fields」の配列数分繰り返し行う。「temporary  = true」だと仮免分野。
        };
        for (var x = 0;  x < gon.questions.length; x++) {
          var fieldId = gon.questions[x].field_id;
          for (var y = 0; y < temporary.length; y++) {
            var tem = temporary[y];
            if (tem == fieldId){
              fieldIdArray.push(gon.questions[x]);
            }; #仮免許問題idを入れた配列「temporary」と一致したidを持つ問題を「fieldIdArray」へ。
          };
        };
      }else{
        for (var i = 0;  i < gon.questions.length; i++) {
          if (gon.questions[i].field_id == select_field){
            fieldIdArray.push(gon.questions[i]);
          };
        }; #「出題範囲を選ぶ」で特定の分野を選択したとき
      };
    };

    function onlyWrongQuestions(){
      if(select_questions == "wrong_questions"){
    #間違った問題のみやりたいとき
        var wrongQuestion = [];
        for (var i = 0;  i < gon.torves.length; i++) {
          if(gon.torves[i].answer_log == false){
            wrongQuestion.push(gon.torves[i].question_id);
          };
        };
        for (var x = 0;  x < fieldIdArray.length; x++) {
          var questionId = fieldIdArray[x].id;
          for (var y = 0; y < wrongQuestion.length; y++) {
            var wrong = wrongQuestion[y];
            if (wrong == questionId){
              userSelectQuestions.push(fieldIdArray[x]);
            };
          };
        };
      }else{
        userSelectQuestions = fieldIdArray;
      };
    };
    var fieldIdArray = [];
    var userSelectQuestions = [];
    selectdFieldQuestions();
    onlyWrongQuestions();
    samples = random(userSelectQuestions, select_num);

最後の「samples」に最終的にユーザーに出題する問題が入ってます。

※ログインの有無の分岐はセレクトボックスをログイン時のみ表示させることにしましたので、ここにはコードを書いてません。

 

まとめ

今回はアルゴリズムを考えjavaScriptで書いていきました。

ずっとrailsでやっていたので、基本メソッド使えばなんでも解決するんですけど、今回みたいにJavaScript側で色々データいじって関数を定義するとなるとなかなか面倒くさいです。

railsだったらfindメソッドだったりsampleメソッドだったりで、データ抽出してランダムに取り出すのが容易に行えるんですが、フレームワークがないと、まずランダムに取り出すための「random関数」を定義しなければならないとか。(ネットでコピペしただけなので苦労はあまりしてない。)

フレームワークの素晴らしさを感じました。

 

次回はデザインを少しまともにしようと思ってます。

以上ありがとうございました。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA