今回は、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)