数字掉落 - 小学数学闯关小游戏
by SonicStar40417 lines14.5 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">100</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.难度升级弹窗 -->
<div class="modal" id="diffModal">
<div class="modal-box" style="text-align:center;">
<h3 style="color:#c0392b">⚠️ 注意!难度升级</h3>
<p>接下来会同时掉落数字与加减乘除算式!<br>需要先计算算式结果,再判断是否符合关卡条件</p>
<button onclick="closeModal('diffModal')">接受挑战</button>
</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.开局关卡选择弹窗(主页) -->
<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:2;">
<p onclick="startGame(0)" style="cursor:pointer;margin:6px 0;color:#2369a0;">1. 找出所有偶数</p>
<p onclick="startGame(1)" style="cursor:pointer;margin:6px 0;color:#2369a0;">2. 找出3的倍数</p>
<p onclick="startGame(2)" style="cursor:pointer;margin:6px 0;color:#2369a0;">3. 找出5的倍数</p>
<p onclick="startGame(3)" style="cursor:pointer;margin:6px 0;color:#2369a0;">4. 找出质数</p>
<p onclick="startGame(4)" style="cursor:pointer;margin:6px 0;color:#2369a0;">5. 找出合数</p>
<p onclick="startGame(5)" style="cursor:pointer;margin:6px 0;color:#2369a0;">6. 找出大于10的数字</p>
</div>
<p style="font-size:14px;color:#666;text-align:center;">规则:点击符合条件的数字/算式得分,点错累计失误,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');
// 全局游戏变量
let score = 0;
let wrongCount = 0;
let currentLevel = 0;
let isPause = false;
let diffUp = false;
let gameTimer = null;
let fallList = [];
const baseTarget = 100;
// 读取本地最高分
let maxHighScore = Number(localStorage.getItem('mathGameHigh')) || 0;
highScoreText.innerText = maxHighScore;
// 关卡配置
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 + 50
},
{
title:"第3关:找出5的倍数",
note:"5的倍数:数字个位只能是0或5,例:5、15、30",
judge:(n)=> n % 5 === 0,
target: baseTarget + 50
},
{
title:"第4关:找出质数",
note:"质数:大于1,只能被1和自身整除的数;例:2、3、5、7、11,1不是质数",
judge:isPrime,
target: baseTarget + 80
},
{
title:"第5关:找出合数",
note:"合数:大于1,除1和自身外还有其他因数;例:4、6、8、9,1既不是质数也不是合数",
judge:(n)=> n>1 && !isPrime(n),
target: baseTarget + 80
},
{
title:"第6关:找出大于10的数",
note:"大于10的数字:数值严格超过10,11、12、13…均符合,10及以下不选择",
judge:(n)=> n > 10,
target: baseTarget + 30
}
];
// 质数判断
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;
// 显示主页关卡选择弹窗
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 = [];
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 = [];
const cfg = levelConfig[currentLevel];
levelTip.innerText = cfg.title;
targetScore.innerText = cfg.target;
setTimeout(startSpawn,600);
setTimeout(()=>{
diffUp = true;
document.getElementById('diffModal').style.display = "flex";
diffTip.innerText = "【难度升级:数字+算式混合】";
},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 = [];
closeModal('startModal');
setTimeout(startSpawn,600);
setTimeout(()=>{
diffUp = true;
document.getElementById('diffModal').style.display = "flex";
diffTip.innerText = "【难度升级:数字+算式混合】";
},20000);
}
// 随机数字1~30
function randNum(){
return Math.floor(Math.random()*30)+1;
}
// 生成加减乘除算式
function createFormula(){
const a = randNum();
const b = randNum();
const ops = ["+","-","*"];
const op = ops[Math.floor(Math.random()*3)];
let res;
let text = a + op + b;
switch(op){
case "+": res = a + b; break;
case "-": res = a - b; break;
case "*": res = a * b; break;
}
return {text, res};
}
// 创建下落元素(速度已调低:1 ~ 2.2)
function createFallItem(){
if(isPause) return;
const item = document.createElement('div');
item.className = "fall-item";
let value;
if(diffUp && Math.random() > 0.5){
const formula = createFormula();
item.innerText = formula.text;
value = formula.res;
}else{
value = randNum();
item.innerText = value;
}
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);
// 核心修改:下落速度大幅降低
const fallSpeed = 1 + Math.random() * 1.2;
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,700);
}
</script>
</body>
</html>Game Source: 数字掉落 - 小学数学闯关小游戏
Creator: SonicStar40
Libraries: none
Complexity: complex (417 lines, 14.5 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" to link back to the original. Then publish at arcadelab.ai/publish.