
【ゲーム】JavaScript:58 計算スピードチャレンジ
「➕ 計算スピードチャレンジ ➖」は、制限時間60秒の間に次々と出題される四則演算の問題をいかに速く&正確に解答できるかを競うタイムアタック型の学習ゲームです。足し算・引き算・掛け算の3種類の問題がランダムに出題され、正解数がそのままスコアになります。シンプルながら熱中度が高く、短時間で脳トレにも最適です。
遊び方・操作方法
- タイトル画面で「スタート」ボタンをクリック(タップ)。
- ゲーム画面で残り時間(60秒)とスコア(初期0)が表示されます。
- 中央に表示される計算問題(例:
37 + 58 = ?
)の答えを、下の入力欄に数字で入力。 - Enterキーまたは「答える」ボタンを押すと回答を判定し、正解なら即座に次の問題が出題されます。
- 残り時間が0になるとゲーム終了。最終スコア(正解数)が表示されます。
ルール
- 制限時間:60秒
- 得点:正解1問につきスコア+1
- 問題形式:
- 足し算:10~99 のランダムな2数の和
- 引き算:10~99 のうち、引かれる数 ≥ 引く数 となるよう2数を生成
- 掛け算:2~16 のランダムな2数の積
- 不正解:ペナルティはなし。間違えると「ちがいます」と表示され入力をやり直す
- 終了条件:残り時間が0秒になると即終了
🎮ゲームプレイ
以下のリンク先から実際にプレイできます。
58 計算スピードチャレンジ
素材のダウンロード
以下のリンクから使用する素材をダウンロードできます。
calculation_speed_title.png | calculation_speed_bg.png |
---|---|
![]() | ![]() |
ゲーム画面イメージ

プログラム全文(calculation_speed.html)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>➕ 計算スピードチャレンジ ➖</title>
<style>
html, body {
margin: 0; padding: 0;
width: 100vw; height: 100vh;
font-family: 'Yu Gothic', 'Meiryo', sans-serif;
background: url('calculation_speed_bg.png') no-repeat center center fixed;
background-size: cover;
}
body {
width: 100vw;
height: 100vh;
overflow: auto;
}
.container {
width: 800px;
margin: 40px auto;
background: rgba(255,255,255,0.94);
border-radius: 22px;
box-shadow: 0 4px 24px rgba(0,0,0,0.13);
padding-bottom: 32px;
min-height: 600px;
position: relative;
}
.title-img {
display: block;
margin: 20px auto 18px auto;
width: 400px;
max-width: 80%;
height: auto;
}
h1 {
text-align: center;
font-size: 2.1em;
margin: 0.6em 0 0.15em 0;
color: #1976d2;
text-shadow: 1px 1px 7px #fff;
letter-spacing: 0.04em;
}
.rule-section {
background: rgba(235,245,255,0.98);
border-radius: 14px;
margin: 28px 32px 14px 32px;
padding: 16px 24px;
box-shadow: 0 2px 8px #4d90fe22;
}
.rule-title {
text-align: center;
font-weight: bold;
font-size: 1.3em;
margin-bottom: 10px;
color: #1976d2;
}
.rule-text {
text-align: left;
font-size: 1.09em;
line-height: 1.65;
color: #174078;
letter-spacing: 0.01em;
}
.btn {
display: block;
margin: 28px auto 0 auto;
padding: 14px 50px;
font-size: 1.2em;
border: none;
border-radius: 28px;
background: linear-gradient(90deg, #87c9fa, #1565c0);
color: #fff;
font-weight: bold;
box-shadow: 0 2px 8px #1976d266;
cursor: pointer;
transition: background 0.2s;
}
.btn:hover { background: linear-gradient(90deg, #b7e4fe, #1976d2); }
.game-area {
width: 700px;
margin: 36px auto 0 auto;
background: rgba(240,248,255,0.96);
border-radius: 16px;
box-shadow: 0 1px 10px #1565c055;
display: flex;
flex-direction: column;
align-items: center;
min-height: 260px;
padding: 24px 0 30px 0;
user-select: none;
}
.status-bar {
text-align: center;
margin: 18px auto 0 auto;
font-size: 1.12em;
font-weight: bold;
background: rgba(255,255,220,0.96);
color: #1976d2;
width: 380px;
border-radius: 12px;
box-shadow: 0 1px 7px #1976d244;
padding: 10px;
letter-spacing: 0.05em;
}
.question {
font-size: 2.3em;
font-weight: bold;
color: #1976d2;
letter-spacing: 0.1em;
margin: 38px 0 16px 0;
text-align: center;
}
.answer-input {
font-size: 1.8em;
padding: 8px 22px;
width: 130px;
border-radius: 10px;
border: 2px solid #1976d2;
margin-bottom: 16px;
margin-top: 6px;
text-align: center;
background: #fff;
color: #174078;
box-shadow: 0 1px 8px #1976d244;
outline: none;
}
.message {
font-size: 1.3em;
color: #e53935;
margin-top: 12px;
min-height: 30px;
text-align: center;
}
.message.ok {
color: #388e3c;
}
.message.none {
color: transparent;
}
.score-bar {
font-size: 1.11em;
color: #388e3c;
margin: 0 0 12px 0;
font-weight: bold;
letter-spacing: 0.03em;
}
.timer-bar {
font-size: 1.15em;
color: #e53935;
margin-bottom: 10px;
font-weight: bold;
letter-spacing: 0.06em;
}
.message-box {
text-align: center;
background: rgba(235,245,255,0.98);
font-size: 2em;
color: #1976d2;
font-weight: bold;
border-radius: 16px;
box-shadow: 0 4px 24px #1976d233;
width: 80%;
max-width: 480px;
margin: 40px auto 0 auto;
padding: 38px 18px;
position: relative;
z-index: 2;
}
.center-btn { margin: 24px auto 0 auto; }
@media (max-width: 900px) {
.container, .game-area { width: 98vw !important; min-width: 0; }
.game-area { padding-left:0; padding-right:0; }
}
</style>
</head>
<body>
<div class="container" id="main-container"></div>
<script>
// ====== 計算スピードチャレンジ ======
// ゲーム状態
let score = 0;
let timer = 60;
let intervalId = null;
let correctAnswer = 0;
// タイトル画面
function showTitleScreen() {
clearInterval(intervalId);
document.getElementById('main-container').innerHTML = `
<h1>➕ 計算スピードチャレンジ ➖</h1>
<img src="calculation_speed_title.png" class="title-img" alt="計算スピードチャレンジ タイトル">
<div class="rule-section">
<div class="rule-title">🎲 遊び方・ルール 🎲</div>
<div class="rule-text">
・制限時間60秒でできるだけ多くの計算問題に答えましょう。<br>
・答えを入力してEnterキーか「答える」ボタンを押してください。<br>
・正解するとすぐ次の問題が出ます。<br>
・スコアは正解数です。どこまで伸ばせるか挑戦しましょう!
</div>
</div>
<button class="btn" id="start-btn">スタート</button>
`;
document.getElementById('start-btn').onclick = startGame;
}
// ゲーム開始
function startGame() {
score = 0;
timer = 60;
showGameScreen();
nextQuestion();
updateStatus();
intervalId = setInterval(() => {
timer--;
updateStatus();
if (timer <= 0) {
clearInterval(intervalId);
setTimeout(showEndScreen, 500);
}
}, 1000);
}
// ゲーム画面
function showGameScreen(msg) {
document.getElementById('main-container').innerHTML = `
<h1>➕ 計算スピードチャレンジ ➖</h1>
<div class="game-area">
<div class="timer-bar" id="timer-bar"></div>
<div class="score-bar" id="score-bar"></div>
<div class="question" id="question"></div>
<input type="number" id="answer-input" class="answer-input" autocomplete="off" />
<button class="btn" id="answer-btn" style="margin-top:8px;">答える</button>
<div class="message none" id="message"></div>
</div>
`;
document.getElementById('answer-btn').onclick = checkAnswer;
document.getElementById('answer-input').addEventListener('keydown', function(e){
if (e.key === "Enter") checkAnswer();
});
document.getElementById('answer-input').focus();
}
// ステータス更新
function updateStatus() {
document.getElementById('timer-bar').textContent = `残り時間:${timer}秒`;
document.getElementById('score-bar').textContent = `スコア:${score}`;
}
// 新しい問題を出題
function nextQuestion() {
let a, b, op, q, ans;
const type = Math.floor(Math.random() * 3); // 0:足し算, 1:引き算, 2:掛け算
if (type === 0) {
// 足し算
a = Math.floor(Math.random()*90)+10;
b = Math.floor(Math.random()*90)+10;
ans = a + b;
op = "+";
} else if (type === 1) {
// 引き算
a = Math.floor(Math.random()*90)+10;
b = Math.floor(Math.random()*(a-10))+10;
ans = a - b;
op = "-";
} else {
// 掛け算
a = Math.floor(Math.random()*15)+2;
b = Math.floor(Math.random()*15)+2;
ans = a * b;
op = "×";
}
q = `${a} ${op} ${b} = ?`;
correctAnswer = ans;
document.getElementById('question').textContent = q;
document.getElementById('answer-input').value = "";
document.getElementById('answer-input').focus();
document.getElementById('message').textContent = "";
document.getElementById('message').className = "message none";
}
// 回答チェック
function checkAnswer() {
if (timer <= 0) return;
const userAns = document.getElementById('answer-input').value.trim();
const msg = document.getElementById('message');
if (userAns === "") {
msg.textContent = "答えを入力してください";
msg.className = "message";
return;
}
if (parseInt(userAns) === correctAnswer) {
score++;
msg.textContent = "正解!";
msg.className = "message ok";
updateStatus();
setTimeout(nextQuestion, 500);
} else {
msg.textContent = "ちがいます";
msg.className = "message";
document.getElementById('answer-input').select();
}
}
// 終了画面
function showEndScreen() {
document.getElementById('main-container').innerHTML = `
<h1>➕ 計算スピードチャレンジ ➖</h1>
<img src="calculation_speed_title.png" class="title-img" alt="計算スピードチャレンジ タイトル">
<div class="message-box">
ゲーム終了!<br>
<span style="font-size:1.2em;color:#1976d2;">あなたのスコア:${score} 問</span>
</div>
<button class="btn center-btn" id="back-title-btn">タイトル画面に戻る</button>
`;
document.getElementById('back-title-btn').onclick = showTitleScreen;
}
// 初期表示
showTitleScreen();
</script>
</body>
</html>
アルゴリズムの流れ
手順 | 処理内容 |
---|---|
1 | showTitleScreen() でタイトル画面を描画 |
2 | 「スタート」押下 → startGame() → スコア・タイマー初期化 |
3 | 毎秒タイマー減少&表示更新、0秒で showEndScreen() |
4 | nextQuestion() で問題(+,−,×)をランダム生成・画面表示 |
5 | Enterキー/ボタンクリックで checkAnswer() を呼び出し解答判定 |
6 | 正解ならスコア+1、メッセージ表示後500msで次の問題へ |
7 | 不正解なら「ちがいます」表示、そのまま次入力待ち |
8 | 時間切れ後、終了画面で最終スコアを表示しタイトルへ戻る |
関数の詳細
関数名 | 機能概要 | 詳細説明 |
---|---|---|
showTitleScreen() | タイトル画面の描画 | ルール説明+「スタート」ボタンを設置。既存タイマーをクリアして初期表示。 |
startGame() | ゲーム開始処理 | スコア・タイマーをリセットし、ゲーム画面を描画、タイマー&出題ループを開始。 |
showGameScreen(msg) | ゲーム画面ブラッシュアップ | タイマー・スコア・問題欄・入力欄・メッセージ領域を描画し、入力イベント登録。 |
updateStatus() | タイマー&スコア表示更新 | DOMを書き換えて残り時間と現在スコアをリアルタイムに表示。 |
nextQuestion() | 新問題の生成・表示 | 足し算/引き算/掛け算をランダムに選び、correctAnswer をセット&画面更新。 |
checkAnswer() | ユーザー解答チェック | 入力値と correctAnswer を比較し、正誤メッセージ表示&スコア更新 or 再入力。 |
showEndScreen() | ゲーム終了画面の描画 | タイマー停止後、最終スコアを表示する結果画面を描画し、タイトル戻りを設定。 |
改造のポイント
- 問題形式の拡張:割り算や小数、連立計算などを追加し、上級者向けモードを実装。
- 難易度設定:時間制限(30/60/90秒)や問題の最大値(3桁同士の加減乗除)を変更できるように。
- タイムボーナス:連続正解時に残り時間を少し回復するボーナスシステムを追加し、リズム感を演出。
- ランキング機能:
localStorage
を使ってハイスコアを保存し、ランキング表示で競争要素を強化。 - 視覚・聴覚演出:正解時のエフェクトやBGM、タイマー残り10秒のアラート音を入れて緊張感を高める。
アドバイス
まずは基本的な問題出題&解答ループをしっかり動作させ、次に「難易度選択」「ボーナス要素」「ランキング機能」を段階的に実装すると、継続プレイ率とユーザー満足度が大きく向上します。楽しく学べる仕組み作りを意識しましょう!