<!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>
:root {
--primary: #FF9F1C; /* 活力橙 */
--secondary: #2EC4B6; /* 清新绿 */
--accent: #E71D36; /* 警示红 */
--purple: #9D4EDD; /* 魔法紫 */
--blue: #2196F3; /* 科技蓝 */
--dark: #011627; /* 深蓝黑 */
--light: #FDFFFC; /* 奶白 */
--bg: #E0F7FA; /* 背景浅蓝 */
--card-shadow: 0 8px 16px rgba(0,0,0,0.1);
}
* {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
background-color: var(--bg);
margin: 0;
padding: 0;
color: var(--dark);
height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 顶部导航 */
header {
background: var(--primary);
color: white;
padding: 15px;
text-align: center;
font-size: 1.2rem;
font-weight: bold;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
flex-shrink: 0;
z-index: 10;
}
/* 底部模块切换 - 适配更多按钮 */
.tab-bar {
display: flex;
background: white;
padding: 10px 5px;
justify-content: space-between;
box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
flex-shrink: 0;
overflow-x: auto; /* 允许横向滚动 */
}
.tab-btn {
background: #f0f0f0;
border: none;
padding: 8px 12px;
border-radius: 15px;
font-weight: bold;
color: #666;
font-size: 0.85rem;
white-space: nowrap; /* 防止换行 */
margin: 0 2px;
transition: all 0.2s;
cursor: pointer;
flex: 1; /* 均分空间 */
}
.tab-btn.active {
background: var(--purple);
color: white;
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(157, 78, 221, 0.4);
}
/* 主内容区域 */
#main-container {
flex: 1;
overflow-y: auto;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
max-width: 600px;
margin: 0 auto;
}
/* 教学卡片 */
.card {
background: white;
border-radius: 20px;
padding: 25px;
width: 100%;
margin-bottom: 20px;
box-shadow: var(--card-shadow);
animation: slideIn 0.5s ease-out;
border-bottom: 5px solid #e0e0e0;
}
@keyframes slideIn {
from { transform: translateY(20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
h2 {
margin-top: 0;
color: var(--primary);
font-size: 1.4rem;
text-align: center;
}
.explanation {
font-size: 1.1rem;
line-height: 1.6;
margin: 15px 0;
}
/* 数字方块 */
.number-box {
display: inline-block;
background: #eee;
padding: 4px 8px;
border-radius: 6px;
font-family: monospace;
font-weight: bold;
margin: 2px;
}
.highlight {
background: var(--primary);
color: white;
}
/* 算式容器 */
.math-block {
background: #f9f9f9;
border-radius: 10px;
padding: 15px;
margin: 10px 0;
text-align: center;
font-size: 1.2rem;
border: 2px dashed #ddd;
overflow-x: auto;
}
/* 按钮样式 */
.action-btn {
display: block;
width: 100%;
padding: 15px;
margin-top: 20px;
border: none;
border-radius: 15px;
background: var(--secondary);
color: white;
font-size: 1.2rem;
font-weight: bold;
cursor: pointer;
box-shadow: 0 4px 0 #1B7A71;
transition: transform 0.1s;
}
.action-btn:active {
transform: translateY(4px);
box-shadow: none;
}
/* 短除法样式 */
.short-division {
display: flex;
flex-direction: column;
align-items: center;
font-family: monospace;
font-size: 1.5rem;
margin: 20px 0;
}
.sd-row {
display: flex;
align-items: stretch;
}
.sd-divisor {
padding: 5px 10px;
border-right: 2px solid var(--dark);
border-bottom: 2px solid var(--dark);
color: var(--accent);
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
}
.sd-dividend {
padding: 5px 20px;
border-bottom: 2px solid var(--dark);
display: flex;
gap: 20px;
align-items: center;
}
.sd-last .sd-divisor, .sd-last .sd-dividend {
border-bottom: none;
}
.sd-last .sd-dividend {
color: var(--blue);
font-weight: bold;
}
/* 因数公式卡片样式 */
.exp-card-container {
display: flex;
justify-content: center;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.exp-card {
background: #f0f0f0;
padding: 8px;
border-radius: 8px;
border: 2px solid #ccc;
text-align: center;
min-width: 50px;
}
.exp-card.selected {
background: var(--purple);
color: white;
border-color: #5a189a;
transform: translateY(-5px);
}
/* 闯关按钮 */
.quiz-option { display: flex; gap: 10px; margin-top: 15px; }
.quiz-btn {
flex: 1; padding: 15px; border-radius: 12px;
border: 2px solid #eee; background: white;
font-size: 1.2rem; font-weight: bold;
}
.quiz-btn.correct { background: #D4EDDA; border-color: #28a745; color: #155724; }
.quiz-btn.wrong { background: #F8D7DA; border-color: #dc3545; color: #721c24; }
</style>
</head>
<body>
<header>🧙♂️ 数论大冒险</header>
<div id="main-container">
<!-- 内容动态注入区域,这是之前缺失的部分 -->
<div id="content-area"></div>
</div>
<div class="tab-bar">
<button class="tab-btn active" onclick="switchModule('tail')">整除特征</button>
<button class="tab-btn" onclick="switchModule('factors')">因数魔法</button>
<button class="tab-btn" onclick="switchModule('gcd')">短除大神</button>
<button class="tab-btn" onclick="switchModule('quiz')">闯关练习</button>
</div>
<script>
// --- 数据与状态 ---
let currentModule = 'tail';
let currentStep = 0;
let quizScore = 0;
let quizTotal = 0;
let currentQuestion = null;
// --- 教学内容数据 ---
const lessons = {
// --- 模块0: 原整除特征 (保留作为复习) ---
'tail': [
{
title: "👋 欢迎来到数论大冒险",
html: `<p class="explanation">这里是数学魔法世界!我们将探索数字背后的秘密。</p>
<p class="explanation">你可以学习:</p>
<ul style="text-align:left; padding-left:30px; font-size:1.1rem">
<li>🔍 <strong>整除特征</strong>:一眼看穿数字</li>
<li>🧱 <strong>因数魔法</strong>:不列举求个数</li>
<li>⚔️ <strong>短除大神</strong>:GCD 与 LCM</li>
</ul>`,
btnText: "先复习整除"
},
{
title: "⚡ 快速复习:整除特征",
html: `<div class="card" style="background:var(--bg)">
<p><strong>看尾巴 (末位):</strong></p>
<ul>
<li>÷2: 偶数 (0,2,4,6,8)</li>
<li>÷5: 0 或 5</li>
</ul>
<hr>
<p><strong>数字和 (求和):</strong></p>
<ul>
<li>÷3: 数字和能被3整除</li>
<li>÷9: 数字和能被9整除</li>
</ul>
</div>`,
btnText: "去学新魔法:因数"
}
],
// --- 模块1: 因数个数公式 ---
'factors': [
{
title: "🌟 任务:求 72 的因数个数",
html: `<p class="explanation">如果用老办法一个个列出来...</p>
<div class="math-block" style="font-size:1rem">
1, 2, 3, 4, 6, 8, 9, 12, 18, 24, 36, 72
</div>
<p class="explanation">太累了!万一漏掉一个就全错了。有没有<strong>不列举</strong>就能算出有多少个的方法?</p>`,
btnText: "启动魔法!"
},
{
title: "Step 1: 拆成质数积木",
html: `<p class="explanation">我们先把 72 炸开,变成质数相乘:</p>
<div class="math-block">
72 = 8 × 9<br>
↓<br>
<span class="highlight">2³</span> × <span class="highlight" style="background:var(--blue)">3²</span>
</div>
<p class="explanation">看!72 是由 <strong>3个2</strong> 和 <strong>2个3</strong> 组成的。</p>`,
btnText: "Step 2: 提取指数"
},
{
title: "Step 2 & 3: 指数加一",
html: `<p class="explanation">观察质数的“指数”(头上的小数字):</p>
<div style="font-size:1.5rem; text-align:center; margin:10px;">
2<sup style="color:var(--primary)">3</sup> × 3<sup style="color:var(--blue)">2</sup>
</div>
<p class="explanation">魔法公式说:<strong>把指数统统 +1</strong>。</p>
<div class="math-block">
( <span style="color:var(--primary)">3</span> + 1 ) × ( <span style="color:var(--blue)">2</span> + 1 )
</div>
<p class="explanation">为什么要 +1 呢?🤔</p>`,
btnText: "揭秘 +1 的含义"
},
{
title: "🔍 原理:隐形的 0 次方",
html: `<p class="explanation">对于 2³,我们在组装因数时,有 <strong>4种</strong> 选择(不是3种!):</p>
<div class="exp-card-container">
<div class="exp-card">2⁰<br>(1)</div>
<div class="exp-card">2¹<br>(2)</div>
<div class="exp-card">2²<br>(4)</div>
<div class="exp-card">2³<br>(8)</div>
</div>
<p class="explanation" style="margin-top:10px">那个 2⁰ (就是1) 也就是“不选2”,也是一种选择!<br><strong>所以 3个2 提供了 3+1=4 种可能。</strong></p>`,
btnText: "最后一步"
},
{
title: "✨ 见证奇迹",
html: `<p class="explanation">根据乘法原理(搭配衣服的道理):</p>
<div class="math-block">
<span style="color:var(--primary)">2的家族 (4种)</span><br>
×<br>
<span style="color:var(--blue)">3的家族 (3种)</span><br>
=<br>
<strong>12 个因数</strong>
</div>
<div class="card" style="background:var(--bg)">
<strong>口诀:</strong><br>
质数分解看指数,<br>
每个指数都加一,<br>
乘在一起是总数。
</div>`,
btnText: "去学短除法"
}
],
// --- 模块2: 短除法 GCD & LCM ---
'gcd': [
{
title: "⚔️ 短除大神来了",
html: `<p class="explanation">我们要同时找出 12 和 18 的:</p>
<ul>
<li>最大公约数 (GCD)</li>
<li>最小公倍数 (LCM)</li>
</ul>
<p class="explanation">这就需要请出神器——<strong>短除法</strong>!</p>
<div class="short-division">
<div class="sd-row">
<div class="sd-dividend" style="border:none">12 18</div>
</div>
</div>`,
btnText: "第一刀:除以 2"
},
{
title: "🗡️ 第一轮攻击",
html: `<p class="explanation">找到它们共同的质因数 <strong>2</strong>:</p>
<div class="short-division">
<div class="sd-row">
<div class="sd-divisor">2</div>
<div class="sd-dividend">12 18</div>
</div>
<div class="sd-row">
<div class="sd-divisor" style="border:none; opacity:0"></div>
<div class="sd-dividend" style="border:none">6 9</div>
</div>
</div>
<p class="explanation">商分别是 6 和 9。还能继续除吗?</p>`,
btnText: "第二刀:除以 3"
},
{
title: "🗡️ 第二轮攻击",
html: `<p class="explanation">6 和 9 还能被 <strong>3</strong> 整除:</p>
<div class="short-division">
<div class="sd-row">
<div class="sd-divisor">2</div>
<div class="sd-dividend">12 18</div>
</div>
<div class="sd-row">
<div class="sd-divisor">3</div>
<div class="sd-dividend">6 9</div>
</div>
<div class="sd-row sd-last">
<div class="sd-divisor" style="border:none; opacity:0"></div>
<div class="sd-dividend">2 3</div>
</div>
</div>
<p class="explanation">剩下的 2 和 3 互质(只有公约数1),<strong>收工!</strong></p>`,
btnText: "如何算 GCD?"
},
{
title: "📏 最大公约数 (GCD)",
html: `<div class="short-division">
<div class="sd-row">
<div class="sd-divisor" style="background:var(--accent); color:white">2</div>
<div class="sd-dividend">12 18</div>
</div>
<div class="sd-row">
<div class="sd-divisor" style="background:var(--accent); color:white">3</div>
<div class="sd-dividend">6 9</div>
</div>
<div class="sd-row sd-last">
<div class="sd-divisor" style="border:none; opacity:0"></div>
<div class="sd-dividend">2 3</div>
</div>
</div>
<p class="explanation">GCD 只看<strong>侧边</strong>(墙壁上)的数字:</p>
<div class="math-block" style="color:var(--accent)">
2 × 3 = 6
</div>`,
btnText: "那 LCM 呢?"
},
{
title: "📐 最小公倍数 (LCM)",
html: `<p class="explanation">LCM 要画一个大大的 <strong>"L"</strong>:</p>
<div class="short-division">
<div class="sd-row">
<div class="sd-divisor" style="background:var(--purple); color:white">2</div>
<div class="sd-dividend">12 18</div>
</div>
<div class="sd-row">
<div class="sd-divisor" style="background:var(--purple); color:white">3</div>
<div class="sd-dividend">6 9</div>
</div>
<div class="sd-row sd-last">
<div class="sd-divisor" style="border:none; opacity:0"></div>
<div class="sd-dividend" style="background:var(--purple); color:white; border-radius:0 0 5px 5px;">2 3</div>
</div>
</div>
<p class="explanation">侧边 × 底部(扫荡所有数字):</p>
<div class="math-block" style="color:var(--purple)">
(2×3) × (2×3) = 36
</div>`,
btnText: "去闯关!"
}
]
};
// --- 核心逻辑 ---
function init() {
renderCurrentStep();
}
function switchModule(moduleName) {
currentModule = moduleName;
currentStep = 0;
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
// 简单映射 active 状态
const map = {'tail':0, 'factors':1, 'gcd':2, 'quiz':3};
if(document.querySelectorAll('.tab-btn')[map[moduleName]]) {
document.querySelectorAll('.tab-btn')[map[moduleName]].classList.add('active');
}
if (moduleName === 'quiz') {
startQuiz();
} else {
renderCurrentStep();
}
}
function renderCurrentStep() {
const contentDiv = document.getElementById('content-area');
const data = lessons[currentModule][currentStep];
let html = `
<div class="card">
<h2>${data.title}</h2>
${data.html}
</div>
<button class="action-btn" onclick="nextStep()">${data.btnText} ➡️</button>
`;
// 引导逻辑
if (currentStep === lessons[currentModule].length - 1) {
let nextMod = '';
if(currentModule === 'tail') nextMod = "'factors'";
if(currentModule === 'factors') nextMod = "'gcd'";
if(currentModule === 'gcd') nextMod = "'quiz'";
if(nextMod) {
html = html.replace('nextStep()', `switchModule(${nextMod})`);
}
}
contentDiv.innerHTML = html;
contentDiv.scrollTop = 0;
}
function nextStep() {
if (currentStep < lessons[currentModule].length - 1) {
currentStep++;
renderCurrentStep();
}
}
// --- 智能题库系统 ---
function startQuiz() {
quizScore = 0;
quizTotal = 0;
generateQuestion();
}
// 辅助函数:求GCD
function gcd(a, b) {
return b === 0 ? a : gcd(b, a % b);
}
function generateQuestion() {
const contentDiv = document.getElementById('content-area');
// 随机题型:0=整除, 1=因数个数, 2=GCD/LCM
const type = Math.floor(Math.random() * 3);
let qHtml = "";
let correct = false;
let explanation = "";
// 题型1:因数个数
if (type === 1) {
// 生成 p^a * q^b 形式的数
const p = [2, 3, 5][Math.floor(Math.random()*3)];
const q = [2, 3, 5, 7].filter(x => x!==p)[Math.floor(Math.random()*3)];
const a = Math.floor(Math.random() * 3) + 1; // 1-3
const b = Math.floor(Math.random() * 2) + 1; // 1-2
const num = Math.pow(p, a) * Math.pow(q, b);
const realCount = (a+1)*(b+1);
// 构造问题
const isTrue = Math.random() > 0.5;
const askCount = isTrue ? realCount : realCount + Math.floor(Math.random()*2)*2 -1; // 错误答案
correct = isTrue;
currentQuestion = { type: 'factors', correct, explanation: `分解:${p}^${a} × ${q}^${b}<br>公式:(${a}+1)×(${b}+1) = ${realCount}` };
qHtml = `
<div style="text-align:center; margin: 20px 0;">
<span style="font-size:2.5rem; font-weight:bold; color:var(--dark)">${num}</span>
<p style="font-size:1.2rem;">共有 <strong>${askCount}</strong> 个因数?</p>
</div>`;
}
// 题型2:GCD / LCM
else if (type === 2) {
const base = Math.floor(Math.random() * 5) + 2; // 公因数
const x = Math.floor(Math.random() * 4) + 2;
const y = x + (Math.floor(Math.random() * 3) + 1); // 互质部分简单模拟
// 简单处理,不严格保证xy互质,但保证有公约数
const num1 = base * x;
const num2 = base * y;
const realGCD = gcd(num1, num2);
const realLCM = (num1 * num2) / realGCD;
const askGCD = Math.random() > 0.5; // 问GCD还是LCM
const isTrue = Math.random() > 0.5;
let targetVal, label;
if (askGCD) {
label = "最大公约数 (GCD)";
targetVal = isTrue ? realGCD : (Math.random()>0.5 ? base : 1);
} else {
label = "最小公倍数 (LCM)";
targetVal = isTrue ? realLCM : realLCM * 2;
}
correct = isTrue;
currentQuestion = { type: 'gcd', correct, explanation: `${num1}和${num2}<br>GCD=${realGCD}, LCM=${realLCM}` };
qHtml = `
<div style="text-align:center; margin: 20px 0;">
<span style="font-size:2rem; font-weight:bold; color:var(--dark)">${num1}, ${num2}</span>
<p style="font-size:1.1rem;">它们的 ${label} 是 <strong>${targetVal}</strong>?</p>
</div>`;
}
// 题型0:保留少量整除判定
else {
const rule = [3, 9, 4][Math.floor(Math.random()*3)];
let num = Math.floor(Math.random() * 800) + 100;
const isDivisible = (num % rule === 0);
const userExpect = Math.random() > 0.5; // 题目问“能不能整除”
// 构造:数字 num 能被 rule 整除吗?
correct = isDivisible;
currentQuestion = { type: 'div', correct, explanation: `${num} ÷ ${rule} = ${(num/rule).toFixed(1)}` };
qHtml = `
<div style="text-align:center; margin: 20px 0;">
<span style="font-size:2.5rem; font-weight:bold; color:var(--dark)">${num}</span>
<p style="font-size:1.2rem;">能被 <strong>${rule}</strong> 整除吗?</p>
</div>`;
}
// 渲染外壳
let html = `
<div class="card">
<h2>🏆 综合闯关 (第 ${quizTotal + 1} 题)</h2>
${qHtml}
<div id="feedback-area" style="text-align:center; min-height: 80px; padding:10px;"></div>
<div class="quiz-option">
<button id="btn-yes" class="quiz-btn" onclick="checkAnswer(true)">✅ 是/能</button>
<button id="btn-no" class="quiz-btn" onclick="checkAnswer(false)">❌ 否/不能</button>
</div>
</div>
<button id="next-q-btn" class="action-btn" style="display:none;" onclick="generateQuestion()">下一题 ➡️</button>
`;
contentDiv.innerHTML = html;
}
function checkAnswer(userYes) {
// 逻辑修正:如果题目是“是...吗”,用户选yes,且正确答案是yes -> 对
// 如果题目是“是...吗”,用户选no,且正确答案是no -> 对
const isCorrect = (userYes === currentQuestion.correct);
const feedbackDiv = document.getElementById('feedback-area');
const nextBtn = document.getElementById('next-q-btn');
const yesBtn = document.getElementById('btn-yes');
const noBtn = document.getElementById('btn-no');
yesBtn.disabled = true;
noBtn.disabled = true;
if (isCorrect) {
quizScore++;
feedbackDiv.innerHTML = `<h3 style="color:#28a745; margin:0">🎉 答对啦!</h3><p>${currentQuestion.explanation}</p>`;
if(userYes) yesBtn.classList.add('correct');
else noBtn.classList.add('correct');
} else {
feedbackDiv.innerHTML = `<h3 style="color:#dc3545; margin:0">😅 答错咯</h3><p>${currentQuestion.explanation}</p>`;
if(userYes) yesBtn.classList.add('wrong');
else noBtn.classList.add('wrong');
}
quizTotal++;
nextBtn.style.display = 'block';
}
// 启动
init();
</script>
</body>
</html>
💡 这段代码完全由 gemini 生成。
登录后可复制完整代码