数字掉落 - 小学数学闯关小游戏
by SonicStar40506 lines18.3 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>数字掉落 - 小学数学闯关小游戏</title>
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:"微软雅黑",system-ui,sans-serif;}
body{overflow:hidden;background:linear-gradient(160deg,#87CEEB,#c0e8ff);color:#222;height:100vh;width:100vw;}
/* 顶部工具栏 */
.top-bar{
position:fixed;top:0;left:0;width:100%;height:64px;
background:rgba(255,255,255,0.85);display:flex;align-items:center;justify-content:space-between;
padding:0 14px;z-index:999;box-shadow:0 2px 8px #99c8e8;
}
.top-bar button{
background:#3498db;border:none;color:#fff;padding:8px 10px;border-radius:10px;
font-size:14px;cursor:pointer;margin:0 3px;transition:0.2s;
}
.top-bar button:hover{background:#2179b9;}
.info-text{font-size:17px;font-weight:bold;color:#1a4c70;}
/* 游戏画布 */
#gameArea{
width:100vw;height:100vh;position:relative;
padding-top:64px;
}
/* 掉落数字/算式元素 卡通样式 */
.fall-item{
position:absolute;font-size:30px;font-weight:bold;
padding:6px 14px;border-radius:16px;
background:rgba(52,152,219,0.8);cursor:pointer;
user-select:none;box-shadow:0 3px 10px #72b8e6;color:#fff;
border:2px solid #fff;
}
/* 弹窗通用样式 */
.modal{
position:fixed;top:0;left:0;width:100%;height:100%;
background:rgba(0,0,0,0.6);display:none;align-items:center;justify-content:center;
z-index:9999;
}
.modal-box{
background:#fff;color:#111;padding:28px;max-width:92%;width:540px;
border-radius:20px;font-size:17px;line-height:1.8;box-shadow:0 0 20px #66a8d8;
}
.modal-box h3{margin-bottom:14px;color:#2369a0;text-align:center;}
.modal-box h2{text-align:center;color:#195788;margin-bottom:16px;}
.modal-box button{
margin-top:18px;padding:10px 26px;background:#3498db;color:white;
border:none;border-radius:12px;font-size:16px;cursor:pointer;display:block;margin-left:auto;margin-right:auto;
}
.modal-box button:hover{background:#2179b9;}
/* 底部计分面板 */
.score-panel{
position:fixed;bottom:22px;left:22px;z-index:998;
font-size:19px;background:rgba(255,255,255,0.8);padding:12px 20px;border-radius:14px;
box-shadow:0 2px 10px #a2cbe6;color:#164263;
}
/* 难度升级提示文字 */
.level-tag{position:fixed;top:72px;left:50%;transform:translateX(-50%);font-size:20px;font-weight:bold;z-index:997;color:#c0392b;background:#fff8f8;padding:4px 16px;border-radius:12px;}
/* 最高分显示 */
.high-score{
position:fixed;bottom:22px;right:22px;z-index:998;
font-size:17px;background:rgba(255,255,255,0.8);padding:10px 16px;border-radius:12px;color:#b04000;
}
</style>
</head>
<body>
<!-- 顶部控制栏:返回主页、暂停、知识点按钮 -->
<div class="top-bar">
<div>
<button id="homeBtn">🏠 返回主页</button>
<button id="pauseBtn">⏸️ 暂停</button>
<button id="noteBtn">📒 知识点笔记本</button>
<button id="musicBtn" disabled style="opacity:0.5;">🔇音乐</button>
</div>
<div class="info-text" id="levelTip">请先选择关卡开始游戏</div>
</div>
<div class="level-tag" id="diffTip"></div>
<!-- 游戏主区域 -->
<div id="gameArea"></div>
<!-- 计分面板 -->
<div class="score-panel">
当前得分:<span id="scoreNum">0</span> / 目标:<span id="targetScore">200</span>
<br/>失误次数:<span id="wrongNum">0</span>/3
</div>
<!-- 本地最高分 -->
<div class="high-score">🏆 历史最高分:<span id="highScoreText">0</span></div>
<!-- 1.笔记本知识点弹窗 -->
<div class="modal" id="noteModal">
<div class="modal-box">
<h3>📖 本关数学知识点</h3>
<div id="noteContent"></div>
<button onclick="closeModal('noteModal')">关闭笔记</button>
</div>
</div>
<!-- 2.难度升级弹窗【无确认按钮,自动3秒关闭】 -->
<div class="modal" id="diffModal">
<div class="modal-box" style="text-align:center;">
<h3 style="color:#c0392b">⚠️ 提示:难度自动升级</h3>
<p>现在会同时掉落数字与简单口算算式<br>算式下落速度更慢,给你充足计算时间</p>
<!-- 删除确认按钮,无需手动点击 -->
</div>
</div>
<!-- 3.失误三次重置关卡弹窗 -->
<div class="modal" id="resetModal">
<div class="modal-box" style="text-align:center;">
<h3 style="color:#c0392b">失误达到3次!关卡重置</h3>
<p>别灰心,点击笔记本复习知识点再挑战一次</p>
<button onclick="resetLevel()">重新开始本关</button>
</div>
</div>
<!-- 4.通关成功弹窗 -->
<div class="modal" id="winModal">
<div class="modal-box" style="text-align:center;">
<h2>🎉 恭喜通关本关!</h2>
<p>你成功达到目标分数,数学掌握得很棒!</p>
<button onclick="closeModal('winModal');nextLevel()">进入下一关</button>
</div>
</div>
<!-- 5.开局关卡选择弹窗(14个关卡完整列表) -->
<div class="modal start-modal" id="startModal" style="display:flex;">
<div class="modal-box">
<h2>🔢 数字掉落 · 小学数学闯关</h2>
<p style="margin:12px 0;text-align:center;">选择你要练习的数学关卡:</p>
<div style="text-align:left;margin:15px 0;line-height:1.6;font-size:15px;">
<p onclick="startGame(0)" style="cursor:pointer;margin:4px 0;color:#2369a0;">1. 找出所有偶数(2的倍数)</p>
<p onclick="startGame(1)" style="cursor:pointer;margin:4px 0;color:#2369a0;">2. 找出3的倍数</p>
<p onclick="startGame(2)" style="cursor:pointer;margin:4px 0;color:#2369a0;">3. 找出4的倍数</p>
<p onclick="startGame(3)" style="cursor:pointer;margin:4px 0;color:#2369a0;">4. 找出5的倍数</p>
<p onclick="startGame(4)" style="cursor:pointer;margin:4px 0;color:#2369a0;">5. 找出7的倍数</p>
<p onclick="startGame(5)" style="cursor:pointer;margin:4px 0;color:#2369a0;">6. 找出8的倍数</p>
<p onclick="startGame(6)" style="cursor:pointer;margin:4px 0;color:#2369a0;">7. 找出9的倍数</p>
<p onclick="startGame(7)" style="cursor:pointer;margin:4px 0;color:#2369a0;">8. 找出质数</p>
<p onclick="startGame(8)" style="cursor:pointer;margin:4px 0;color:#2369a0;">9. 找出合数</p>
<p onclick="startGame(9)" style="cursor:pointer;margin:4px 0;color:#2369a0;">10. 找出小于10的数字</p>
<p onclick="startGame(10)" style="cursor:pointer;margin:4px 0;color:#2369a0;">11. 找出大于10的数字</p>
<p onclick="startGame(11)" style="cursor:pointer;margin:4px 0;color:#2369a0;">12. 找出大于20的数字</p>
<p onclick="startGame(12)" style="cursor:pointer;margin:4px 0;color:#2369a0;">13. 找出10~20之间的数</p>
<p onclick="startGame(13)" style="cursor:pointer;margin:4px 0;color:#2369a0;">14. 找出算式结果等于12的式子</p>
</div>
<p style="font-size:14px;color:#666;text-align:center;margin-top:10px;">规则:点击符合条件的数字/算式得分,点错累计失误,3次失误重置关卡,达到目标分即可通关</p>
</div>
</div>
<script>
// DOM元素获取
const gameArea = document.getElementById('gameArea');
const scoreNum = document.getElementById('scoreNum');
const wrongNum = document.getElementById('wrongNum');
const levelTip = document.getElementById('levelTip');
const noteContent = document.getElementById('noteContent');
const diffTip = document.getElementById('diffTip');
const targetScore = document.getElementById('targetScore');
const highScoreText = document.getElementById('highScoreText');
const homeBtn = document.getElementById('homeBtn');
const diffModal = document.getElementById('diffModal');
// 全局游戏变量
let score = 0;
let wrongCount = 0;
let currentLevel = 0;
let isPause = false;
let diffUp = false;
let gameTimer = null;
let fallList = [];
const baseTarget = 200;
// 读取本地最高分
let maxHighScore = Number(localStorage.getItem('mathGameHigh')) || 0;
highScoreText.innerText = maxHighScore;
// 14个关卡完整配置
const levelConfig = [
{
title:"第1关:找出所有偶数",
note:"偶数:可以被2整除的整数;个位数字为0、2、4、6、8,例:2、14、20",
judge:(n)=> n % 2 === 0,
target: baseTarget
},
{
title:"第2关:找出3的倍数",
note:"3的倍数:所有数位数字相加的和能被3整除,例:12 → 1+2=3,18 →1+8=9",
judge:(n)=> n % 3 === 0,
target: baseTarget + 100
},
{
title:"第3关:找出4的倍数",
note:"4的倍数:最后两位数字组成的数能被4整除,例:12、24、32",
judge:(n)=> n % 4 === 0,
target: baseTarget + 100
},
{
title:"第4关:找出5的倍数",
note:"5的倍数:数字个位只能是0或5,例:5、15、30",
judge:(n)=> n % 5 === 0,
target: baseTarget + 100
},
{
title:"第5关:找出7的倍数",
note:"7的倍数:数字除以7没有余数,例:7、14、21、28",
judge:(n)=> n % 7 === 0,
target: baseTarget + 120
},
{
title:"第6关:找出8的倍数",
note:"8的倍数:最后三位数字组成的数能被8整除,例:8、16、24",
judge:(n)=> n % 8 === 0,
target: baseTarget + 120
},
{
title:"第7关:找出9的倍数",
note:"9的倍数:所有数位数字相加和能被9整除,例:9、18、27",
judge:(n)=> n % 9 === 0,
target: baseTarget + 120
},
{
title:"第8关:找出质数",
note:"质数:大于1,只能被1和自身整除的数;例:2、3、5、7、11,1不是质数",
judge:isPrime,
target: baseTarget + 160
},
{
title:"第9关:找出合数",
note:"合数:大于1,除1和自身外还有其他因数;例:4、6、8、9,1既不是质数也不是合数",
judge:(n)=> n>1 && !isPrime(n),
target: baseTarget + 160
},
{
title:"第10关:找出小于10的数字",
note:"小于10:数字1~9,数字10及以上不符合要求",
judge:(n)=> n < 10,
target: baseTarget + 60
},
{
title:"第11关:找出大于10的数字",
note:"大于10的数字:数值严格超过10,11、12、13…均符合,10及以下不选择",
judge:(n)=> n > 10,
target: baseTarget + 60
},
{
title:"第12关:找出大于20的数字",
note:"大于20:数字21、22、23…,20及更小数字不要点击",
judge:(n)=> n > 20,
target: baseTarget + 80
},
{
title:"第13关:找出10~20之间的数",
note:"10~20之间:数字大于等于10、小于等于20,其余数字不选",
judge:(n)=> n >= 10 && n <= 20,
target: baseTarget + 90
},
{
title:"第14关:找出结果等于12的算式",
note:"计算加减乘简单口算算式,结果等于12才点击;纯数字全部不选",
judge:(n)=> n === 12,
target: baseTarget + 180
}
];
// 质数判断工具
function isPrime(num){
if(num<=1) return false;
for(let i=2;i<=Math.sqrt(num);i++){
if(num%i===0) return false;
}
return true;
}
// 关闭弹窗
function closeModal(id){
document.getElementById(id).style.display = "none";
}
// 返回主页按钮
homeBtn.addEventListener('click', ()=>{
clearInterval(gameTimer);
fallList.forEach(el=>el.remove());
fallList = [];
diffUp = false;
diffTip.innerText = "";
score = 0;
wrongCount = 0;
scoreNum.innerText = score;
wrongNum.innerText = wrongCount;
diffModal.style.display = "none";
document.getElementById('startModal').style.display = "flex";
});
// 笔记本按钮
document.getElementById('noteBtn').addEventListener('click',()=>{
const cfg = levelConfig[currentLevel];
noteContent.innerText = cfg.note;
document.getElementById('noteModal').style.display = "flex";
});
// 暂停按钮
document.getElementById('pauseBtn').addEventListener('click',()=>{
isPause = !isPause;
const btn = document.getElementById('pauseBtn');
if(isPause){
btn.innerText = "▶️ 继续";
clearInterval(gameTimer);
fallList.forEach(item=>item.style.opacity="0.35");
}else{
btn.innerText = "⏸️ 暂停";
fallList.forEach(item=>item.style.opacity="1");
startSpawn();
}
});
// 3次失误重置关卡
function resetLevel(){
wrongCount = 0;
wrongNum.innerText = wrongCount;
diffUp = false;
diffTip.innerText = "";
fallList.forEach(el=>el.remove());
fallList = [];
diffModal.style.display = "none";
closeModal('resetModal');
startSpawn();
}
// 下一关
function nextLevel(){
currentLevel = (currentLevel + 1) % levelConfig.length;
score = 0;
wrongCount = 0;
scoreNum.innerText = score;
wrongNum.innerText = wrongCount;
diffUp = false;
diffTip.innerText = "";
fallList.forEach(el=>el.remove());
fallList = [];
diffModal.style.display = "none";
const cfg = levelConfig[currentLevel];
levelTip.innerText = cfg.title;
targetScore.innerText = cfg.target;
setTimeout(startSpawn,600);
// 20秒自动开启难度升级,弹窗3秒自动消失
setTimeout(()=>{
diffUp = true;
diffModal.style.display = "flex";
diffTip.innerText = "【难度升级:数字+简单口算算式|算式下落更慢】";
// 3秒自动关闭提示弹窗,无需按钮确认
setTimeout(()=>{
diffModal.style.display = "none";
},3000);
},20000);
}
// 启动选中关卡
function startGame(levelIdx){
currentLevel = levelIdx;
const cfg = levelConfig[currentLevel];
levelTip.innerText = cfg.title;
targetScore.innerText = cfg.target;
score = 0;
wrongCount = 0;
scoreNum.innerText = score;
wrongNum.innerText = wrongCount;
diffUp = false;
diffTip.innerText = "";
fallList.forEach(el=>el.remove());
fallList = [];
diffModal.style.display = "none";
closeModal('startModal');
setTimeout(startSpawn,600);
// 20秒自动开启难度升级
setTimeout(()=>{
diffUp = true;
diffModal.style.display = "flex";
diffTip.innerText = "【难度升级:数字+简单口算算式|算式下落更慢】";
// 3秒自动关闭提示弹窗
setTimeout(()=>{
diffModal.style.display = "none";
},3000);
},20000);
}
// 随机数字1~30
function randNum(){
return Math.floor(Math.random()*30)+1;
}
// 生成【无负数、简单口算】加减乘算式
function createFormula(){
// 1~9小数字,保证口算简单
const a = Math.floor(Math.random() * 9) + 1;
const b = Math.floor(Math.random() * 9) + 1;
const ops = ["+","-","*"];
const op = ops[Math.floor(Math.random()*3)];
let res;
let text;
switch(op){
case "+":
text = a + "+" + b;
res = a + b;
break;
case "-":
// 大数减小数,结果一定≥0,无负数
if(a >= b){
text = a + "-" + b;
res = a - b;
}else{
text = b + "-" + a;
res = b - a;
}
break;
case "*":
text = a + "×" + b;
res = a * b;
break;
}
return {text, res};
}
// 创建下落元素【分层慢速:算式远慢于数字】
function createFallItem(){
if(isPause) return;
const item = document.createElement('div');
item.className = "fall-item";
let value;
let fallSpeed;
if(diffUp && Math.random() > 0.5){
// 算式:超慢速,充足计算时间
const formula = createFormula();
item.innerText = formula.text;
value = formula.res;
fallSpeed = 0.3 + Math.random() * 0.4;
}else{
// 纯数字:普通慢速
value = randNum();
item.innerText = value;
fallSpeed = 0.6 + Math.random() * 0.6;
}
const maxX = window.innerWidth - 90;
const x = Math.random() * maxX;
item.style.left = x + "px";
item.style.top = "-65px";
gameArea.appendChild(item);
fallList.push(item);
function fallLoop(){
if(isPause) return;
let top = parseFloat(item.style.top);
top += fallSpeed;
item.style.top = top + "px";
if(top > window.innerHeight){
item.remove();
fallList = fallList.filter(el => el !== item);
return;
}
requestAnimationFrame(fallLoop);
}
fallLoop();
// 点击判断逻辑
item.addEventListener('click',()=>{
const cfg = levelConfig[currentLevel];
if(cfg.judge(value)){
score += value;
scoreNum.innerText = score;
item.style.background = "rgba(46, 204, 113, 0.85)";
if(score >= cfg.target){
clearInterval(gameTimer);
if(score > maxHighScore){
maxHighScore = score;
localStorage.setItem('mathGameHigh',maxHighScore);
highScoreText.innerText = maxHighScore;
}
document.getElementById('winModal').style.display = "flex";
}
}else{
wrongCount++;
wrongNum.innerText = wrongCount;
item.style.background = "rgba(231, 76, 60, 0.85)";
if(wrongCount >= 3){
clearInterval(gameTimer);
document.getElementById('resetModal').style.display = "flex";
}
}
setTimeout(()=>{
item.remove();
fallList = fallList.filter(el => el !== item);
},180);
})
}
// 生成间隔拉长,画面不拥挤
function startSpawn(){
clearInterval(gameTimer);
gameTimer = setInterval(createFallItem,850);
}
</script>
</body>
</html>Game Source: 数字掉落 - 小学数学闯关小游戏
Creator: SonicStar40
Libraries: none
Complexity: complex (506 lines, 18.3 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-sonicstar40-mqpyb89b" to link back to the original. Then publish at arcadelab.ai/publish.