<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>クイズ</title>
<style>
:root {
--primary-color: #228B22;
--secondary-color: #FFA500;
--correct-color: #32CD32;
--incorrect-color: #800080;
--light-bg: #f0fff0;
--white-bg: #ffffff;
--text-color: #333;
}
body {
font-family: 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', Meiryo, sans-serif;
background-color: var(--light-bg);
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
padding: 20px 0;
}
#container {
width: 90%;
max-width: 700px;
}
.panel {
background-color: var(--white-bg);
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
padding: 20px 30px;
text-align: center;
margin-bottom: 20px;
border: 1px solid #90ee90;
}
.hidden {
display: none;
}
h1, h2 {
color: var(--primary-color);
}
#question-number {
font-size: 18px;
font-weight: bold;
color: var(--primary-color);
}
#question {
font-size: 20px;
min-height: 50px;
margin: 10px 0;
line-height: 1.5;
}
#options {
display: flex;
flex-direction: column;
gap: 12px;
margin: 20px 0;
}
.option {
background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
color: white;
border: none;
border-radius: 8px;
padding: 15px;
font-size: 18px;
cursor: pointer;
transition: opacity 0.3s, transform 0.1s;
}
.option:hover:not(:disabled) {
opacity: 0.85;
}
.option:active:not(:disabled) {
transform: scale(0.98);
}
.option:disabled {
cursor: default;
}
#timer-area {
margin-top: 20px;
font-size: 28px;
font-weight: bold;
color: var(--secondary-color);
}
#score {
font-size: 36px;
font-weight: bold;
color: var(--primary-color);
margin: 10px 0 20px;
}
.action-button {
background: linear-gradient(45deg, var(--secondary-color), var(--primary-color));
color: white;
border: none;
border-radius: 8px;
padding: 15px 30px;
font-size: 18px;
cursor: pointer;
transition: opacity 0.3s;
margin: 5px;
}
.action-button:hover {
opacity: 0.85;
}
#show-explanation-button {
background: var(--secondary-color);
color: #fff;
}
#explanation-list {
text-align: left;
margin-top: 20px;
}
.explanation-item {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 15px;
margin-bottom: 15px;
}
.explanation-item h3 {
font-size: 16px;
margin: 0 0 10px 0;
color: var(--primary-color);
border-bottom: 2px solid var(--primary-color);
padding-bottom: 5px;
}
.explanation-item p {
margin: 5px 0;
line-height: 1.6;
}
.user-answer.correct {
color: var(--correct-color);
font-weight: bold;
}
.user-answer.incorrect {
color: var(--incorrect-color);
font-weight: bold;
text-decoration: line-through;
}
.comment {
margin-top: 10px;
padding: 10px;
border-radius: 5px;
font-style: italic;
font-weight: bold;
}
.comment.correct {
background-color: var(--light-bg);
color: var(--correct-color);
}
.comment.incorrect {
background-color: #f3e5f5;
color: var(--incorrect-color);
}
</style>
</head>
<body>
<div id="container">
<div id="quiz-area" class="panel">
<h1 id="main-title"></h1>
<div id="question-area">
<p id="question-number"></p>
<p id="question"></p>
</div>
<div id="options">
<button class="option"></button>
<button class="option"></button>
<button class="option"></button>
</div>
<div id="timer-area">
残り時間: <span id="timer">20</span>秒
</div>
</div>
<div id="result-area" class="panel hidden">
<h2 id="result-title"></h2>
<p id="result-message"></p>
<p id="score"></p>
<button id="show-explanation-button" class="action-button"></button>
<button id="restart-button" class="action-button"></button>
</div>
<div id="explanation-area" class="panel hidden">
<h2 id="explanation-title"></h2>
<div id="explanation-list"></div>
<button id="restart-button-2" class="action-button"></button>
</div>
</div>
<script>
'use strict';
// ===================================
// ① プログラムのロジック(関数定義)
// ===================================
// --- グローバル変数 ---
let quizData = [];
let userAnswers = [];
let currentShuffledOptions = [];
let currentQuestionIndex = 0;
let score = 0;
let timerInterval;
let timeLeft;
// --- DOM要素の取得(一度だけ行う) ---
const mainTitleEl = document.getElementById('main-title');
const quizAreaEl = document.getElementById('quiz-area');
const resultAreaEl = document.getElementById('result-area');
const explanationAreaEl = document.getElementById('explanation-area');
const questionNumberEl = document.getElementById('question-number');
const questionEl = document.getElementById('question');
const optionButtons = document.querySelectorAll('.option');
const timerEl = document.getElementById('timer');
const resultTitleEl = document.getElementById('result-title');
const resultMessageEl = document.getElementById('result-message');
const scoreEl = document.getElementById('score');
const showExplanationButton = document.getElementById('show-explanation-button');
const restartButtons = [document.getElementById('restart-button'), document.getElementById('restart-button-2')];
const explanationTitleEl = document.getElementById('explanation-title');
const explanationListEl = document.getElementById('explanation-list');
// --- 関数定義 ---
function shuffleArray(array) {
const newArray = [...array];
for (let i = newArray.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[newArray[i], newArray[j]] = [newArray[j], newArray[i]];
}
return newArray;
}
function startQuiz() {
quizData = shuffleArray(quizConfig.allQuizData).slice(0, 10);
userAnswers = [];
currentQuestionIndex = 0;
score = 0;
quizAreaEl.classList.remove('hidden');
resultAreaEl.classList.add('hidden');
explanationAreaEl.classList.add('hidden');
showQuestion();
}
function showQuestion() {
if (currentQuestionIndex >= quizData.length) {
showResult();
return;
}
const currentQuestion = quizData[currentQuestionIndex];
questionNumberEl.textContent = `第 ${currentQuestionIndex + 1} 問`;
questionEl.textContent = currentQuestion.question;
const optionsWithCorrectness = currentQuestion.options.map((optionText, index) => ({
text: optionText,
isCorrect: (index === currentQuestion.answer)
}));
currentShuffledOptions = shuffleArray(optionsWithCorrectness);
currentShuffledOptions.forEach((optionData, index) => {
optionButtons[index].textContent = optionData.text;
optionButtons[index].disabled = false;
});
startTimer();
}
function startTimer() {
timeLeft = quizConfig.timerSeconds;
timerEl.textContent = timeLeft;
clearInterval(timerInterval);
timerInterval = setInterval(() => {
timeLeft--;
timerEl.textContent = timeLeft;
if (timeLeft <= 0) {
clearInterval(timerInterval);
handleAnswer(-1);
}
}, 1000);
}
function handleAnswer(selectedIndex) {
clearInterval(timerInterval);
if (selectedIndex === -1) {
userAnswers.push({ text: "時間切れ", isCorrect: false });
} else {
userAnswers.push(currentShuffledOptions[selectedIndex]);
}
if (selectedIndex !== -1 && currentShuffledOptions[selectedIndex].isCorrect) {
score++;
}
optionButtons.forEach(button => { button.disabled = true; });
setTimeout(() => {
currentQuestionIndex++;
showQuestion();
}, 500);
}
function showResult() {
quizAreaEl.classList.add('hidden');
resultAreaEl.classList.remove('hidden');
scoreEl.textContent = `${score} / 10 問正解`;
}
function showExplanations() {
resultAreaEl.classList.add('hidden');
explanationAreaEl.classList.remove('hidden');
explanationListEl.innerHTML = '';
quizData.forEach((q, index) => {
const userAnswer = userAnswers[index];
const isCorrect = userAnswer.isCorrect;
const commentArray = isCorrect ? quizConfig.correctComments : quizConfig.incorrectComments;
const randomComment = commentArray[Math.floor(Math.random() * commentArray.length)];
const explanationHTML = `
<div class="explanation-item">
<h3>第${index + 1}問: ${q.question}</h3>
<p>あなたの回答: <span class="user-answer ${isCorrect ? 'correct' : 'incorrect'}">${userAnswer.text}</span></p>
<p>正解: <strong>${q.options[q.answer]}</strong></p>
<p><strong>【解説】</strong>: ${q.explanation}</p>
<div class="comment ${isCorrect ? 'correct' : 'incorrect'}">${randomComment}</div>
</div>
`;
explanationListEl.innerHTML += explanationHTML;
});
}
function applyTheme(config) {
const root = document.documentElement;
Object.keys(config.colors).forEach(key => {
root.style.setProperty(`--${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`, config.colors[key]);
});
document.title = config.title;
mainTitleEl.textContent = config.title;
resultTitleEl.textContent = config.resultTitle;
resultMessageEl.textContent = config.resultMessage;
explanationTitleEl.textContent = config.explanationTitle;
showExplanationButton.textContent = config.showExplanationButtonText;
restartButtons.forEach(button => button.textContent = config.restartButtonText);
}
function initializeQuiz(config) {
applyTheme(config);
optionButtons.forEach((button, index) => button.addEventListener('click', () => handleAnswer(index)));
restartButtons.forEach(button => button.addEventListener('click', startQuiz));
showExplanationButton.addEventListener('click', showExplanations);
startQuiz();
}
// ===================================
// ② テーマ別データベース
// ===================================
const quizConfig = {
title: "HUNTER×HUNTERクイズ",
resultTitle: "試験終了!",
resultMessage: "あなたのハンターライセンスは...",
explanationTitle: "解説",
showExplanationButtonText: "解説を見る",
restartButtonText: "再試験",
timerSeconds: 20,
colors: {
primary: "#228B22",
secondary: "#FFA500",
correct: "#32CD32",
incorrect: "#800080",
lightBg: "#f0fff0",
},
correctComments: [
"お主、見込みがあるな!", "SSS級の知識だ!", "ハンターライセンス、授与!", "あんたは光だ…輝いている!",
"まさに奇跡の価値は!", "いいね!ゴンさんみたいだ!", "その知識、伸縮自在の愛(バンジーガム)並みに応用が利くな。",
"神の不在証明(パーフェクトプラン)!完璧だ。", "素晴らしい!ダブルのプロハンターだな。", "その博識、盗賊の極意(スキルハンター)で盗みたいぜ。",
"天晴れ!龍星群(ドラゴンダイヴ)級のインパクトだ!", "完全に捉えたな!束縛する中指の鎖(チェーンジェイル)!",
"いいハンターになれるぜ、お前は。", "ゾルディック家も雇いたがるレベルだ。", "おめでとう。これで心置きなく昇天できる…",
"素晴らしい…!もうゴールしてもいいよね?", "あんたはすごいよ。褒めてやる。", "いい質問(クイズ)には敬意を払う。そして全力で答える…!",
"こいつは、とんでもねェ大物だぜ…!", "メルエム様もご満悦であられるぞ。"
],
incorrectComments: [
],
allQuizData: [
{ question: "主人公ゴンの父親の名前は何?", options: ["ジン・フリークス", "ミト・フリークス", "シルバ・ゾルディック"], answer: 0, explanation: "ゴンの父親は、世界で5本の指に入ると言われる偉大なハンター、ジン・フリークスです。ゴンは彼に会うためにハンターを目指します。" },
{ question: "「新人つぶし」の異名を持つ、ハンター試験のベテラン受験者の名前は?", options: ["トンパ", "ニコル", "バーボン"], answer: 0, explanation: "トンパは、新人受験者を陥れて脱落させることを楽しみにしているベテラン受験者です。下剤入りのジュースを渡すのが常套手段です。" },
{ question: "キルアがハンター試験の最終試験で、ある受験者を殺害して失格になりました。その相手は誰?", options: ["ボードー", "ギタラクル", "ゴズ"], answer: 0, explanation: "兄イルミの精神的な呪縛(針)により、キルアは「自分より強いかもしれない相手とは戦ってはいけない」という暗示をかけられていました。ボードーとの戦いでその暗示が発動し、殺害してしまいます。" },
{ question: "念能力の四大行(てん・ぜつ・れん・はつ)のうち、オーラを体内に留めておく技術は?", options: ["纏(テン)", "絶(ゼツ)", "練(レン)"], answer: 0, explanation: "「纏」は、念の基本中の基本であり、体から溢れ出るオーラを留める技術です。これにより、肉体の老化を防いだり、防御力を高めたりできます。" },
{ question: "ヒソカの念能力「伸縮自在の愛(バンジーガム)」が持つ、2つの性質とは何?", options: ["ゴムとガム", "電気と炎", "水と氷"], answer: 0, explanation: "バンジーガムは、ゴムのように伸縮し、ガムのように粘着するという、非常にシンプルかつ応用力の高い能力です。ヒソカの戦闘センスと相まって、絶大な強さを発揮します。" },
{ question: "幻影旅団の団長、クロロ=ルシルフル。彼の念能力「盗賊の極意(スキルハンター)」はどんな能力?", options: ["他人の念能力を盗んで使う", "オーラを盗む", "他人の記憶を盗む"], answer: 0, explanation: "スキルハンターは、様々な条件をクリアすることで、他人の念能力を盗み、本に封じ込めて自分の能力として使用できるという、極めて強力で希少な能力です。" },
{ question: "ゴンの必殺技「ジャジャン拳」。グー、パー、チョキで、それぞれどの系統の能力が発動する?", options: ["グー(強化系)、チョキ(変化系)、パー(放出系)", "グー(強化系)、チョキ(放出系)、パー(変化系)", "グー(放出系)、チョキ(変化系)、パー(強化系)"], answer: 0, explanation: "「最初はグー!」の掛け声と共にオーラを高め、グーは強化系の打撃、チョキは変化系の刃、パーは放出系の弾を放ちます。" },
{ question: "キメラアントの王の名前は何?", options: ["メルエム", "レオル", "ザザン"], answer: 0, explanation: "女王が「全てを照らす光」という意味を込めて名付けました。メルエムは、生まれながらにして全ての生物の頂点に立つ王として、圧倒的な力とカリスマ性を持っていました。" },
{ question: "ネテロ会長が、メルエムとの最終決戦で使用した、自身の念能力の集大成である技の名前は?", options: ["百式観音", "龍星群(ドラゴンダイヴ)", "超破壊拳(ビッグバンインパクト)"], answer: 0, explanation: "百式観音は、音を置き去りにするほどの速さで、無数の掌打を繰り出す能力です。ネテロは、感謝の正拳突きを毎日一万回繰り返すという修行の果てに、この能力に至りました。" },
{ question: "カイトを殺された怒りと悲しみから、ゴンが自らに「制約と誓約」を課して強制的に成長した姿。その通称は?", options: ["ゴンさん", "覚醒ゴン", "リミットブレイク"], answer: 0, explanation: "「もうこれで終わってもいい」という覚悟のもと、未来の自分の可能性を全て前借りして得た姿です。その圧倒的なオーラは、ピトーすら恐怖させました。" }
]
};
// ===================================
// ③ 実行命令
// ===================================
// ページが読み込まれたら、上記のデータベースを使ってクイズを開始
document.addEventListener('DOMContentLoaded', () => {
initializeQuiz(quizConfig);
});
</script>
</body>
</html>
使用変数
applyTheme -------( Function ) | |
button | |
charset | |
class | |
commentArray | |
content | |
currentQuestion | |
disabled | |
entShuffledOptions | |
explanationAreaEl | |
explanationHTML | |
explanationListEl | |
explanationTitleEl | |
handleAnswer -------( Function ) | |
i | |
id | |
index | |
initializeQuiz -------( Function ) | |
innerHTML | |
isCorrect | |
j | |
key | |
lang | |
mainTitleEl | |
name | |
newArray | |
onsWithCorrectness | |
optionButtons | |
questionEl | |
questionNumberEl | |
quizAreaEl | |
quizConfig | |
quizData | |
randomComment | |
restartButtons | |
resultAreaEl | |
resultMessageEl | |
resultTitleEl | |
root | |
rrentQuestionIndex | |
scale | |
score | |
scoreEl | |
selectedIndex | |
showExplanations -------( Function ) | |
showQuestion -------( Function ) | |
showResult -------( Function ) | |
shuffleArray -------( Function ) | |
startQuiz -------( Function ) | |
startTimer -------( Function ) | |
textContent | |
timeLeft | |
timerEl | |
timerInterval | |
title | |
userAnswer | |
userAnswers | |
wExplanationButton | |
width |