今回は、Webブラウザ上で遊べる「2択質問ゲーム」のコードを見ながら、どんな技術が使われていて、どんなふうに動作しているのかを初心者にもわかるように丁寧に説明していきます。

完成版は、質問に対してAまたはBを選ぶと、多数派か少数派かが表示され、選択の履歴と割合がグラフで見えるという仕組みです。では、さっそく仕組みを見ていきましょう!


どんな機能があるの?

このアプリは、次のような要素で構成されています。

機能内容
ランダムな2択質問JavaScriptで質問をランダムに出題
ボタンで選択A or Bのボタンをクリックして回答
多数派・少数派の判定架空の9人分の選択を加えて集計し、多数派か少数派かを判定
グラフ表示AとBの選択割合をプログレスバーで可視化
履歴管理ローカルストレージに保存、表形式で履歴表示
CSVダウンロード履歴をCSVファイルとして保存可能
履歴クリアボタン1つで履歴を全消去

HTML部分の構造を解説

<h2>とボタン配置

<h2 id="questionText">質問を読み込み中...</h2>
<button class="btn btn-primary" id="choiceA" data-choice="A">❤️ A</button>
<button class="btn btn-success" id="choiceB" data-choice="B">💙 B</button>

  • id="questionText":JavaScriptで質問テキストを差し替えるためのID。
  • data-choice:AまたはBのどちらを選んだかを判別するカスタム属性。

<div class="progress">によるグラフ表示

<div class="progress-bar bg-danger" id="barA" style="width: 0%">❤️ A</div>
<div class="progress-bar bg-info" id="barB" style="width: 0%">💙 B</div>

  • Bootstrapの「プログレスバー」で視覚的な割合の表示が可能です。
  • 幅(width)をJavaScriptで動的に変えることで、リアルタイムなグラフに見せています。

JavaScriptロジックの流れ

質問のランダム表示

function pickQuestion() {
  currentQuestion = questions[Math.floor(Math.random() * questions.length)];
}

  • Math.random()でランダムなインデックスを生成。
  • questions配列から1つの質問オブジェクトを取得。

回答ボタンのクリック処理

btn.addEventListener('click', () => {
  const userChoice = side === 'A' ? currentQuestion.A : currentQuestion.B;
});

  • data-choice属性を使って、どちらを選んだかを判定。
  • currentQuestion.Aなどで該当の選択肢の文字列を取得。

仮想の「他の9人」の回答を生成

const others = Array.from({ length: 9 }, () =>
  Math.random() < 0.5 ? currentQuestion.A : currentQuestion.B
);

  • Math.random() < 0.5 によって ランダムにAまたはBを生成
  • 自分の回答も加えて、全体で10人分の集計を作成。

結果判定と表示

const isMajority = (userChoice === currentQuestion.A && countA > countB) ||
                   (userChoice === currentQuestion.B && countB > countA);

  • 多数派(他の人と同じ回答が多い)なら 🎉、少数派なら 😅。

選択履歴とローカルストレージ

保存と表示の仕組み

localStorage.setItem(historyKey, JSON.stringify(history));

  • localStorage:ブラウザに永続的にデータを保存できる場所
  • JSON.stringify()JSON.parse()配列を文字列として保存・取得しています。

CSVダウンロード

const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);

  • BlobでCSV文字列をファイル化し、<a>タグでダウンロードさせます。

実際の流れを図にしてみよう

┌────────────┐
│ 質問を表示  │
└────┬───────┘
     ↓
┌────────────┐
│ 回答を選択  │ ←ユーザー操作
└────┬───────┘
     ↓
┌────────────┐
│ 他の9人の回答を生成 │
└────┬───────┘
     ↓
┌────────────┐
│ 結果表示(多数 or 少数)│
└────┬───────┘
     ↓
┌────────────┐
│ グラフ更新 & 履歴保存│
└────┬───────┘
     ↓
┌────────────┐
│ 次の質問へ   │
└────────────┘

今後の学習ポイント

このゲームで扱っている内容を理解できたら、次のステップにも挑戦してみましょう!

テーマ次に学ぶとよいこと
イベント処理keydown, mouseover, submit なども試してみよう
状態管理currentQuestionのような状態管理の考え方を理解
フロントエンドフレームワークReactやVueで同じ機能を作ってみよう
データの永続化FirebaseやIndexedDBを使った本格的な保存方法

まとめ

この「2択質問ゲーム」は、ユーザーインターフェースの設計、ロジック構築、データの保存と表示の仕組みがすべて詰まったサンプルです。

「質問をランダムに出す」「ボタンで反応する」「グラフで表示する」「履歴を記録する」――こういった基本ができれば、どんなWebアプリにも応用できます!

ぜひ、自分なりの質問を増やしたり、3択にしてみたり、結果をSNSでシェアできるようにしたりと、自由にアレンジしてみてください。

(Sample)

最後までお読みいただきありがとうございます。