こんにちは、AM0500です。
少し遅いですがちいかわ「草むしり検定」5級合格おめでとうございます!その後に公開された漫画に心がザワザワしていますが…。
合格記念として草むしり検定をイメージした○✕クイズゲームを作ってみました。草に関する試験を受けて合格を目指しましょう。
🔗 実際にプレイしてみる
👉 ちいかわの草むしり検定5級をイメージした草クイズゲーム
👉 使用したAI Claude(claude 4 sonnet)はこちら
🎮 ゲーム画面(スクリーンショット)



📝 一言コメント
ちいかわパークのアトラクションとして草むしり検定とか無いかな~なんて思いながら作りました。合格発表部分に少しこだわりを入れて作っています。よろしければ改変して、もっと問題数や演出にこだわったものを作ってみてください。
…ちいかわパークのアトラクションでこんなのあったらどうでしょう?
🧠 使用したClaudeへのプロンプト
今回、使用したプロンプトです。
以下の要件に沿って、HTML / CSS / JavaScriptで、PC・スマホどちらでも動作するシンプルなマルバツクイズゲームを作成してください。
【タイトル】
ちいかわの草むしり検定(受験番号93)
【ゲーム概要】
草に関するマルバツ(○×)クイズを10問出題し、8問以上正解で合格とするシンプルなゲーム。
【画面仕様】
1. 受験番号「93」を画面右上に常に表示(例:「受験番号 93」と記載)。
2. クイズ画面は大きく「問題文」と「○ / × ボタン」表示。
3. 各問題ごとに制限時間10秒カウントダウン表示。
4. 問題はCSVファイルから読み込み可能とし、URL指定で取得する形式。
- CSVは「問題文」「正解(○ または ×)」の2列。
5. 結果画面は、「合格発表板」風のデザイン。
- 1〜200まで番号が並んだ板状のUI。受験番号93が合格かどうかで演出。
- 番号93付近でスロー&集中線演出あり、合格/不合格が派手に表示される。
6. 合格の場合:「合格!!!」の大きな表示。
7. 不合格の場合:「残念… 不合格」の表示。
【合格条件】
- 10問中、8問以上正解で合格。
【操作方法】
- スマホ / PC両対応。クリックまたはタップで○か×を選択。
【技術要件】
- HTML / CSS / JavaScriptのみ。
- 外部ライブラリは必要最小限(CDN利用OK)。
- CSVはURLから fetch で取得し、問題と正解を読み込む仕様。
【実装順序(推奨)】
1. ○×クイズ機能(10問 / 制限時間付き / 判定)
2. スコアによる合格 or 不合格の分岐
3. 合格発表板デザイン → 93付近スロー&集中線 → 結果演出
4. 出題される問題と回答は添付のCSVを参照。
基本的にはこれで作成されますが、必要に応じて修正依頼を行うようにしてください。ブログ公開の作品はブログの表示の問題により記号や背景色の調整しております。
🕹️ Claudeが返してくれた説明文
主な機能
受験番号表示: 右上に「受験番号 93」を常時表示
10秒タイマー: 各問題に制限時間付き(3秒以下で警告色)
CSV問題読み込み: 提供されたCSVデータから問題を自動取得
ランダム出題: 40問の中から10問をランダムに選択
合格発表板: 1-200番の番号が並んだ本格的な発表板デザイン
特別演出:
番号93周辺でスポットライト効果
集中線アニメーション
合格時の祝福アニメーション
操作方法
開始: 「検定開始」ボタンをクリック
回答: ○または×ボタンをクリック/タップ
再挑戦: 結果画面の「もう一度受験する」ボタン
合格条件
10問中8問以上正解で合格です!
スマートフォンでもPCでも快適にプレイできるレスポンシブデザインになっています。ちいかわらしい可愛い色合いと、本格的な検定風の演出で楽しめるゲームに仕上がりました🌱
💡 ソースコード(HTML)
下記がゲーム本体のhtmlの中身になります。ご自由にご利用ください。もちろん改変などもOKです。リンクや紹介していただけたら嬉しいです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ちいかわの草むしり検定</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', Arial, sans-serif;
background: linear-gradient(135deg, #a8e6cf 0%, #7fcdcd 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.exam-number {
position: absolute;
top: 20px;
right: 20px;
background: rgba(255, 255, 255, 0.9);
padding: 10px 15px;
border-radius: 10px;
font-weight: bold;
font-size: 16px;
color: #333;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 1000;
}
.quiz-container {
background: white;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
padding: 40px;
max-width: 600px;
width: 90%;
text-align: center;
position: relative;
}
.title {
font-size: 28px;
color: #4a90e2;
margin-bottom: 30px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
}
.question-info {
display: flex;
justify-content: center;
margin-bottom: 20px;
font-size: 18px;
color: #666;
}
.timer {
font-size: 24px;
font-weight: bold;
color: #e74c3c;
margin-bottom: 20px;
}
.timer.warning {
color: #ff0000;
animation: pulse 0.5s infinite;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.question-text {
font-size: 22px;
color: #333;
margin-bottom: 40px;
line-height: 1.5;
min-height: 80px;
display: flex;
align-items: center;
justify-content: center;
}
.answer-buttons {
display: flex;
gap: 30px;
justify-content: center;
margin-bottom: 30px;
}
.answer-btn {
width: 120px;
height: 120px;
border: none;
border-radius: 50%;
font-size: 48px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.answer-btn.correct {
background: #27ae60;
color: white;
}
.answer-btn.incorrect {
background: #e74c3c;
color: white;
}
.answer-btn:hover {
transform: translateY(-5px);
box-shadow: 0 8px 20px rgba(0,0,0,0.3);
}
.answer-btn:active {
transform: translateY(0);
}
.start-btn {
background: #4a90e2;
color: white;
border: none;
padding: 15px 30px;
font-size: 18px;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
}
.start-btn:hover {
background: #357abd;
transform: translateY(-2px);
}
.results-board {
background: #2c3e50;
color: white;
padding: 40px;
border-radius: 20px;
max-width: 800px;
width: 95%;
height: 80vh;
overflow: hidden;
position: relative;
}
.board-content {
height: 100%;
display: flex;
flex-direction: column;
}
.numbers-container {
flex: 1;
overflow-y: auto;
scroll-behavior: smooth;
padding-right: 10px;
}
.numbers-container::-webkit-scrollbar {
width: 8px;
}
.numbers-container::-webkit-scrollbar-track {
background: #34495e;
border-radius: 4px;
}
.numbers-container::-webkit-scrollbar-thumb {
background: #f39c12;
border-radius: 4px;
}
.board-title {
font-size: 32px;
color: #f39c12;
margin-bottom: 30px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
.numbers-grid {
display: grid;
grid-template-columns: repeat(10, 1fr);
gap: 8px;
margin-bottom: 30px;
}
.number-cell {
background: #34495e;
padding: 12px;
border-radius: 8px;
font-size: 18px;
text-align: center;
transition: all 0.3s ease;
margin-bottom: 10px;
min-height: 50px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
}
.number-cell.highlight {
background: #f39c12;
color: #2c3e50;
font-weight: bold;
transform: scale(1.1);
z-index: 10;
position: relative;
animation: spotlight 3s ease-in-out;
box-shadow: 0 0 30px rgba(243, 156, 18, 0.8);
}
.number-cell.missing {
background: transparent;
color: transparent;
border: 2px dashed rgba(255, 255, 255, 0.3);
min-height: 50px;
}
@keyframes spotlight {
0% {
transform: scale(1);
box-shadow: 0 0 0 rgba(243, 156, 18, 0.8);
}
30% {
transform: scale(1.05);
box-shadow: 0 0 20px rgba(243, 156, 18, 0.8);
}
60% {
transform: scale(1.1);
box-shadow: 0 0 40px rgba(243, 156, 18, 0.9);
}
100% {
transform: scale(1.1);
box-shadow: 0 0 30px rgba(243, 156, 18, 0.8);
}
}
.concentration-lines {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
opacity: 0;
transition: opacity 0.5s ease;
}
.concentration-lines.active {
opacity: 1;
}
.concentration-lines::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200%;
height: 200%;
background: radial-gradient(circle, transparent 30%, rgba(255,255,255,0.1) 31%, rgba(255,255,255,0.1) 32%, transparent 33%);
animation: concentrate 1s ease-in-out;
}
@keyframes concentrate {
0% { transform: translate(-50%, -50%) scale(3); }
100% { transform: translate(-50%, -50%) scale(1); }
}
.result-announcement {
font-size: 48px;
font-weight: bold;
margin-top: 30px;
text-shadow: 3px 3px 6px rgba(0,0,0,0.5);
opacity: 0;
animation: fadeInUp 1s ease-out 2s forwards;
}
.result-announcement.pass {
color: #27ae60;
animation: fadeInUp 1s ease-out 2s forwards, celebrate 2s ease-in-out 3s infinite;
}
.result-announcement.fail {
color: #e74c3c;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes celebrate {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.score-info {
font-size: 24px;
margin-top: 20px;
color: #ecf0f1;
opacity: 0;
animation: fadeInUp 1s ease-out 4s forwards;
}
.retry-btn {
background: #4a90e2;
color: white;
border: none;
padding: 15px 30px;
font-size: 18px;
border-radius: 10px;
cursor: pointer;
margin-top: 30px;
transition: all 0.3s ease;
opacity: 0;
animation: fadeInUp 1s ease-out 5s forwards;
}
.retry-btn:hover {
background: #357abd;
transform: translateY(-2px);
}
.loading {
font-size: 20px;
color: #4a90e2;
}
@media (max-width: 768px) {
.quiz-container {
padding: 30px 20px;
}
.title {
font-size: 24px;
}
.question-text {
font-size: 18px;
}
.answer-btn {
width: 100px;
height: 100px;
font-size: 36px;
}
.answer-buttons {
gap: 20px;
}
.numbers-grid {
grid-template-columns: repeat(6, 1fr);
gap: 8px;
}
.number-cell {
font-size: 16px;
padding: 10px;
min-height: 45px;
}
.board-title {
font-size: 24px;
}
.result-announcement {
font-size: 32px;
}
}
</style>
</head>
<body>
<div class="exam-number">受験番号 93</div>
<div class="quiz-container" id="quiz-container">
<h1 class="title">ちいかわの草むしり検定</h1>
<div class="loading" id="loading">問題を読み込み中...</div>
<button class="start-btn" id="start-btn" style="display: none;">検定開始</button>
<div id="quiz-screen" style="display: none;">
<div class="question-info">
<span id="question-number">問題 1/10</span>
</div>
<div class="timer" id="timer">10</div>
<div class="question-text" id="question-text"></div>
<div class="answer-buttons">
<button class="answer-btn correct" id="correct-btn">○</button>
<button class="answer-btn incorrect" id="incorrect-btn">×</button>
</div>
</div>
</div>
<div class="results-board" id="results-board" style="display: none;">
<div class="board-content">
<h2 class="board-title">🌱 合格発表板 🌱</h2>
<div class="numbers-container" id="numbers-container">
<div class="numbers-grid" id="numbers-grid"></div>
</div>
<div class="concentration-lines" id="concentration-lines"></div>
<div class="result-announcement" id="result-announcement"></div>
<div class="score-info" id="score-info"></div>
<button class="retry-btn" id="retry-btn">もう一度受験する</button>
</div>
</div>
<script>
class KusaQuiz {
constructor() {
this.questions = [];
this.currentQuestion = 0;
this.score = 0;
this.timer = null;
this.timeLeft = 10;
this.isAnswered = false;
this.audioContext = null;
this.init();
}
// 効果音を生成する関数
createBeepSound() {
if (!this.audioContext) {
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
const oscillator = this.audioContext.createOscillator();
const gainNode = this.audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(this.audioContext.destination);
oscillator.frequency.setValueAtTime(800, this.audioContext.currentTime);
gainNode.gain.setValueAtTime(0.3, this.audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, this.audioContext.currentTime + 0.1);
oscillator.start();
oscillator.stop(this.audioContext.currentTime + 0.1);
}
async init() {
await this.loadQuestions();
this.setupEventListeners();
}
async loadQuestions() {
try {
// CSVデータを直接使用
const csvData = `問題,正解
草は植物の総称である。,○
シロツメクサは日本原産である。,×
ススキは春に花を咲かせる。,×
芝生は基本的に多年草である。,○
雑草は全て食べられるわけではない。,○
クローバーは別名シロツメクサである。,○
タンポポはキク科の植物である。,○
ネコジャラシはエノコログサという草である。,○
ヨモギは草餅の材料になる。,○
セイタカアワダチソウは外来種である。,○
イネ科の草は花粉症の原因となることがある。,○
カタバミの葉は夜に閉じる。,○
シロツメクサは四つ葉になることがある。,○
薬草は全て毒がある。,×
雑草の生命力は非常に強い。,○
稲は草ではなく木である。,×
ススキは秋の七草である。,○
雑草は草むしりしないとどんどん増える。,○
コケは種を持つ植物である。,×
雑草はコンクリートを突き破って生えることがある。,○
ドクダミは独特の臭いがある。,○
チガヤはイネ科である。,○
ササは木に分類される。,×
藤はつる植物だが草ではない。,○
シダ植物は胞子で増える。,○
ヨシ(アシ)は川辺に生える。,○
イタドリは春に若芽が食べられる。,○
葉がギザギザしている草は全部毒ではない。,×
花粉症の原因は草花に多い。,○
オオバコは踏まれても育つ。,○
サトイモは食用だが葉は食べられない。,○
ツクシはスギナの胞子茎である。,○
オジギソウは触れると葉を閉じる。,○
カラスノエンドウはマメ科である。,○
アザミは葉にトゲがある。,○
スギナは地下茎で増える。,○
ドクダミは食用として流通している。,×
シソ科の草は香りが強いものが多い。,○
スズメノカタビラはイネ科である。,○
シロツメクサは花が白い。,○`;
const lines = csvData.trim().split('\n');
const headers = lines[0].split(',');
this.questions = [];
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(',');
this.questions.push({
question: values[0],
answer: values[1]
});
}
// 問題をシャッフルして10問選択
this.questions = this.shuffleArray(this.questions).slice(0, 10);
document.getElementById('loading').style.display = 'none';
document.getElementById('start-btn').style.display = 'block';
} catch (error) {
console.error('問題の読み込みに失敗しました:', error);
document.getElementById('loading').textContent = '問題の読み込みに失敗しました';
}
}
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;
}
setupEventListeners() {
document.getElementById('start-btn').addEventListener('click', () => this.startQuiz());
document.getElementById('correct-btn').addEventListener('click', () => this.answerQuestion('○'));
document.getElementById('incorrect-btn').addEventListener('click', () => this.answerQuestion('×'));
document.getElementById('retry-btn').addEventListener('click', () => this.resetQuiz());
}
startQuiz() {
document.getElementById('start-btn').style.display = 'none';
document.getElementById('quiz-screen').style.display = 'block';
this.showQuestion();
}
showQuestion() {
if (this.currentQuestion >= this.questions.length) {
this.showResults();
return;
}
const question = this.questions[this.currentQuestion];
document.getElementById('question-number').textContent = `問題 ${this.currentQuestion + 1}/10`;
document.getElementById('question-text').textContent = question.question;
this.isAnswered = false;
this.timeLeft = 10;
this.startTimer();
// ボタンを有効化
document.getElementById('correct-btn').disabled = false;
document.getElementById('incorrect-btn').disabled = false;
}
startTimer() {
const timerElement = document.getElementById('timer');
timerElement.textContent = this.timeLeft;
timerElement.className = 'timer';
this.timer = setInterval(() => {
this.timeLeft--;
timerElement.textContent = this.timeLeft;
if (this.timeLeft <= 3) {
timerElement.classList.add('warning');
}
if (this.timeLeft <= 0) {
this.timeUp();
}
}, 1000);
}
timeUp() {
if (!this.isAnswered) {
this.isAnswered = true;
this.stopTimer();
// 時間切れの場合は不正解として扱う
setTimeout(() => this.nextQuestion(), 1000);
}
}
stopTimer() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
}
answerQuestion(answer) {
if (this.isAnswered) return;
this.isAnswered = true;
this.stopTimer();
// 効果音を再生
this.createBeepSound();
const question = this.questions[this.currentQuestion];
const isCorrect = answer === question.answer;
if (isCorrect) {
this.score++;
}
// ボタンを無効化
document.getElementById('correct-btn').disabled = true;
document.getElementById('incorrect-btn').disabled = true;
setTimeout(() => this.nextQuestion(), 1000);
}
nextQuestion() {
this.currentQuestion++;
this.showQuestion();
}
showResults() {
document.getElementById('quiz-container').style.display = 'none';
document.getElementById('results-board').style.display = 'block';
this.createNumbersGrid();
this.animateResults();
}
createNumbersGrid() {
const grid = document.getElementById('numbers-grid');
grid.innerHTML = '';
const isPassed = this.score >= 8;
// 歯抜けの番号を生成(合格なら93含む、不合格なら93抜き)
const numbers = this.generateNumbers(isPassed);
numbers.forEach(num => {
const cell = document.createElement('div');
if (num === 93) {
cell.className = 'number-cell';
cell.textContent = '93';
cell.id = 'number-93';
} else if (num === 'missing') {
cell.className = 'number-cell missing';
cell.textContent = '';
cell.id = 'number-93';
} else {
cell.className = 'number-cell';
cell.textContent = num;
}
grid.appendChild(cell);
});
}
generateNumbers(isPassed) {
const numbers = [];
// 1から200までの数字を適度に歯抜けで生成
for (let i = 1; i <= 200; i++) {
// 約70%の確率で番号を表示
if (Math.random() < 0.7) {
if (i === 93) {
if (isPassed) {
numbers.push(93);
} else {
numbers.push('missing');
}
} else {
numbers.push(i);
}
}
}
// 93が含まれていない場合は強制的に追加
if (!numbers.includes(93) && !numbers.includes('missing')) {
const insertIndex = Math.floor(Math.random() * numbers.length);
if (isPassed) {
numbers.splice(insertIndex, 0, 93);
} else {
numbers.splice(insertIndex, 0, 'missing');
}
}
return numbers;
}
animateResults() {
const isPassed = this.score >= 8;
const container = document.getElementById('numbers-container');
const target93 = document.getElementById('number-93');
// 最初にコンテナを一番上にスクロール
container.scrollTop = 0;
// 93番の位置を計算
const targetPosition = target93.offsetTop - container.clientHeight / 2;
// スローダウン開始位置(93の少し手前)
const slowdownStart = Math.max(0, targetPosition - 200);
// アニメーション関数
const animateScroll = () => {
const currentScroll = container.scrollTop;
const remainingDistance = targetPosition - currentScroll;
if (remainingDistance > 0) {
let speed;
if (currentScroll < slowdownStart) {
// 高速スクロール
speed = Math.min(remainingDistance, 20);
} else {
// スロースクロール
speed = Math.min(remainingDistance, 3);
}
container.scrollTop += speed;
requestAnimationFrame(animateScroll);
} else {
// スクロール完了後の演出
setTimeout(() => {
target93.classList.add('highlight');
// 集中線演出
document.getElementById('concentration-lines').classList.add('active');
setTimeout(() => {
// 結果発表
const announcement = document.getElementById('result-announcement');
const scoreInfo = document.getElementById('score-info');
if (isPassed) {
announcement.textContent = '合格!!!';
announcement.className = 'result-announcement pass';
} else {
announcement.textContent = '残念… 不合格';
announcement.className = 'result-announcement fail';
}
scoreInfo.textContent = `${this.score}/10問正解`;
// 集中線を徐々に消す
setTimeout(() => {
document.getElementById('concentration-lines').classList.remove('active');
}, 3000);
}, 500);
}, 200);
}
};
// アニメーション開始
setTimeout(() => {
animateScroll();
}, 500);
}
resetQuiz() {
this.currentQuestion = 0;
this.score = 0;
this.timeLeft = 10;
this.isAnswered = false;
this.stopTimer();
// 問題を再シャッフル
this.questions = this.shuffleArray(this.questions);
document.getElementById('results-board').style.display = 'none';
document.getElementById('quiz-container').style.display = 'block';
document.getElementById('quiz-screen').style.display = 'none';
document.getElementById('start-btn').style.display = 'block';
}
}
// ゲーム開始
new KusaQuiz();
</script>
</body>
</html>🔔 補足・注意事項
このコードや説明は、Claudeのバージョンや環境によって出力内容が異なる可能性があります。
同じ命令をしても、まったく違うコードが返ってくることもあるので、再現性は参考程度にご覧ください。

0 件のコメント:
コメントを投稿