ビット数とパターンの数

8問出ます。そのビット数で表現できるパターンが何種類になるか8つのボタンから選んでください。

制作意図

「1ビット増えるとパターンは2倍」を体感してもらうように考えました。

問題は簡単ですし、意図とは異なる解法に気がつくかもしれません。でも、ビット、パターンなどの言葉の意味がわかればそれでいいのだと思います。反射的に答えられるようになる必要は全くありません。

プログラムなど

次の一連のvarとfunctionをscriptタグの中に並べます。解説のために分けています。各部部ブロックの順序も問いません。

グローバル変数

グローバル変数という言い方もjavascriptでは正確ではないかと思います。実際のところArray以外はここに書いてなくても正常に動作します。varをつけた変数はfunction内のスコープになるので、他のfunctionからも参照したければvarをつけずに代入すればいいのですが、共通に使うものを外に出して複数のfunctionから参照されることを意識して書くようにしています。このこだわりはあまり見かけません。

functionの外の文のもう一つの違いはHTMLの読み込み中に実行されるというところです。

qは問題の候補、aはその正解です。aはそのままの順で選択肢にします。

q,aを書き換えることで様々な問題に使えるようにしてあります。

var mondaimax = 10; //mondai-suu
var mondaiNo = 1;
var q = new Array("1","2","3","4" ,"5" ,"6" ,"7"  ,"8"  );
var a = new Array("2","4","8","16","32","64","128","256");
var ran;
var seikaict=0;
var gotouct =0;
var toiwaku;
var answers;
var toitxt ;
var mondaimax = 10; //mondai-suu
var mondaiNo = 1;
var q = new Array("1","2","3","4" ,"5" ,"6" ,"7"  ,"8"  );
var a = new Array("2","4","8","16","32","64","128","256");
var ran;
var seikaict=0;
var gotouct =0;
var toiwaku;
var answers;
var toi ;

startを押したら

引数の t は問題数。

startのボタンを非表示にし、問枠、選択肢枠を入れる要素を変数でアクセスできるようにしておき、選択肢となるボタンのセットをします。

ボタンの作成手順は、i番目の選択肢文字列からテキストノードを作成、button要素を作ってそこにaddします。ボタンにイベントハンドラを取り付けて選択肢枠に加えるという作業を配列の要素数だけ繰り返します。イベントハンドラではiを文字列として埋め込みます。動作するときは数値として解釈されるはずです。

最後に putmondai()を呼び出して第一問を出題します。

function start(t){
  document.getElementById("start").setAttribute("style","display:none;");
  toiwaku = document.getElementById("toiwaku");
  mondaimax = t;
  answers = document.getElementById("answers")
  answers.setAttribute("style","display:block;");
  var sentakushi;
  var text;
  for (var i = 0; a.length > i ; i++) {
     text = document.createTextNode(a[i]);
     sentakushi = document.createElement("button");
     sentakushi.appendChild(text);
     sentakushi.setAttribute("type","button");
     sentakushi.setAttribute("onclick","answer("+i+")");
     answers.appendChild(sentakushi);
  }
  putmondai();
}
function start(t){
  document.getElementById("start").setAttribute("style","display:none;");
  toiwaku = document.getElementById("toiwaku");
  mondaimax = t;
  answers = document.getElementById("answers")
  answers.setAttribute("style","display:block;");
  var sentakushi;
  var text;
  for (var i = 0; a.length > i ; i++) {
     text = document.createTextNode(a[i]);
     sentakushi = document.createElement("button");
     sentakushi.appendChild(text);
     sentakushi.setAttribute("type","button");
     sentakushi.setAttribute("onclick","answer("+i+")");
     answers.appendChild(sentakushi);
  }
  putmondai();
}

問題の出題

ランダム関数は0以上1未満の数を出すので0から配列の要素数-1までの整数に直します

配列から問題を拾って問題番号と合わせてテキストノードを作り、p要素を作って加えます。

問枠に子ノードとして加えます。乱数で出したranが後で解答と比較されます。

function putmondai(){    
    ran = Math.floor( Math.random() *q.length );
    toitxt = document.createTextNode(
        "第"+mondaiNo+"問 : " + q[ran]);
    var pnode = document.createElement("p");
    pnode.appendChild(toitxt);
    toiwaku.appendChild(pnode);
}
function putmondai(){    
    ran = Math.floor( Math.random() *q.length );
    var text = document.createTextNode(
        "第"+mondaiNo+"問 : " + q[ran]);
    toi = document.createElement("p");
    toi.appendChild(text);
    toiwaku.appendChild(toi);
}

選択肢から回答をクリックしたら

引数の解答番号とranを比較し、正解かどうかを判断します

putmondai()で作ったテキストノードの値を正誤の判定などに書き換えてしまいます。

問題数が予定数に達してなければ次の問題を出し、予定数になったら正解率をからテキストノードをつくり、p要素も作って問枠の最後に加えます。

解答選択肢の枠を非表示にして、「もう一回」の枠を表示します。

function answer(ans){
  if (ans == ran){
    seikaict++;
    toitxt.nodeValue = "第"+mondaiNo+"問 : 正解です。"
         +" 正解数は"+seikaict+" ,誤答数は"+gotouct;
  }
  else{
    gotouct++;
    toitxt.nodeValue = "第"+mondaiNo+"問 : 違います。"
         +" 正解数は"+seikaict+" ,誤答数は"+gotouct; 
  }
  if (mondaimax>mondaiNo){
    mondaiNo++;
    putmondai();
  }
  else{
    var text = document.createTextNode(
        "正答率は "+seikaict/(seikaict+gotouct)*100 +" % でした。");
    var pnode = document.createElement("p");
    pnode.appendChild(text);
    toiwaku.appendChild(pnode);
    answers.setAttribute("style","display:none;");
    document.getElementById("replay").setAttribute("style","display:block;");
  }
}
function answer(ans){
  if (ans == ran){
    seikaict++;
    toi.firstChild.nodeValue = "第"+mondaiNo+"問 : 正解です。"
         +" 正解数は"+seikaict+" ,誤答数は"+gotouct;
  }
  else{
    gotouct++;
    toi.firstChild.nodeValue = "第"+mondaiNo+"問 : 違います。"
         +" 正解数は"+seikaict+" ,誤答数は"+gotouct; 
  }
  if (mondaimax>mondaiNo){
    mondaiNo++;
    putmondai();
  }
  else{
    var text = document.createTextNode(
        "正答率は "+seikaict/(seikaict+gotouct)*100 +" % でした。");
    toi = document.createElement("p");
    toi.appendChild(text);
    toiwaku.appendChild(toi);
    document.getElementById("answers").setAttribute("style","display:none;");
    document.getElementById("replay").setAttribute("style","display:block;");
  }
}

HTML

appendChild()の受け皿にはテキストノードはなくても構いません。(nodeValueの変更の対象はテキストノードがないとエラーになります)。

再挑戦はlocation.reload()で済ませています。

<div id="start">
<button type="button" onclick="start('8')">start</button>
</div>

<div id="toiwaku"></div>

<div id="answers"></div>

<div id="replay">
<button type="button" onclick="location.reload();">もう一度</button>
</div>