<!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>第03讲:火柴棒游戏</title>
<style>
/* ================= 基础重置与全局样式 ================= */
:root {
--primary: #FF9F43; /* 活力橙 */
--primary-light: #FFE0B2;
--accent: #54a0ff; /* 天空蓝 */
--success: #1dd1a1; /* 翡翠绿 */
--error: #ff6b6b; /* 珊瑚红 */
--bg-color: #f7f1e3; /* 温暖米色 */
--text-main: #2d3436;
--text-sub: #636e72;
--stick-wood: #f1c40f;
--stick-head: #c0392b;
}
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif; }
::-webkit-scrollbar { display: none; }
html, body { margin: 0; padding: 0; background: var(--bg-color); overflow: hidden; height: 100vh; }
/* 动态背景图案 */
body {
background-image: radial-gradient(#d1ccc0 1px, transparent 1px);
background-size: 20px 20px;
}
#app { height: 100vh; max-width: 480px; margin: 0 auto; background: rgba(255,255,255,0.95); display: flex; flex-direction: column; position: relative; box-shadow: 0 0 30px rgba(0,0,0,0.05); }
.content-area { flex: 1; overflow-y: auto; padding-bottom: 90px; scroll-behavior: smooth; padding-top: 10px; }
/* 通用动画类 */
.fade-in { animation: fadeIn 0.4s ease-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.shake { animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both; }
@keyframes shake { 10%, 90% { transform: translate3d(-1px, 0, 0); } 20%, 80% { transform: translate3d(2px, 0, 0); } 30%, 50%, 70% { transform: translate3d(-4px, 0, 0); } 40%, 60% { transform: translate3d(4px, 0, 0); } }
/* ================= 底部导航 (App Bar) ================= */
.bottom-nav {
position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
width: 100%; max-width: 480px; height: 75px;
background: rgba(255, 255, 255, 0.98);
border-top: 1px solid rgba(0,0,0,0.05);
display: flex; justify-content: space-around; align-items: center;
z-index: 9999; box-shadow: 0 -5px 20px rgba(0,0,0,0.03);
backdrop-filter: blur(10px);
padding-bottom: 10px;
}
.nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; cursor: pointer; padding: 5px; color: #b2bec3; transition: all 0.3s; }
.nav-item.active { color: var(--primary); transform: translateY(-5px); }
.nav-icon { font-size: 24px; margin-bottom: 2px; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1)); }
.nav-label { font-size: 11px; font-weight: 600; }
/* ================= 顶部 Tab 导航 ================= */
.tab-nav {
display: flex; background: white; margin: 10px 20px 20px;
border-radius: 15px; padding: 5px; box-shadow: 0 4px 15px rgba(0,0,0,0.05);
}
.tab-item {
flex: 1; padding: 10px; text-align: center; cursor: pointer;
font-weight: 600; color: var(--text-sub); border-radius: 12px;
transition: all 0.3s; font-size: 14px;
}
.tab-item.active { background: var(--primary-light); color: #e67e22; }
/* ================= 页面通用 ================= */
.page-title { font-size: 24px; font-weight: 800; color: var(--text-main); margin: 20px 20px 10px; text-align: center; letter-spacing: 1px; }
.intro-page { padding: 30px 20px; }
.intro-card {
background: white; border-radius: 24px; padding: 30px 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.08); text-align: center;
border: 1px solid rgba(0,0,0,0.02);
}
.intro-emoji { font-size: 80px; margin-bottom: 20px; animation: float 3s infinite ease-in-out; }
@keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
.intro-story { font-size: 16px; line-height: 1.8; color: var(--text-sub); margin-bottom: 25px; text-align: justify; }
.concept-list { background: #f1f2f6; border-radius: 16px; padding: 20px; text-align: left; font-size: 15px; color: var(--text-main); margin-bottom: 25px; line-height: 1.6; }
.teacher-btn {
background: linear-gradient(135deg, var(--primary) 0%, #ff6b6b 100%);
color: white; border: none; padding: 16px 40px; border-radius: 50px;
font-size: 18px; font-weight: bold; cursor: pointer;
box-shadow: 0 8px 20px rgba(255, 107, 107, 0.4);
transition: transform 0.2s; width: 100%; display: flex; justify-content: center; align-items: center; gap: 10px;
}
.teacher-btn:active { transform: scale(0.96); }
/* ================= 动画演示区 ================= */
.demo-page { padding: 0 15px; }
.demo-section { display: none; }
.demo-section.active { display: block; animation: fadeIn 0.5s ease; }
.animation-area {
background: #fff; border-radius: 24px; padding: 10px;
min-height: 320px; position: relative; overflow: hidden;
box-shadow: inset 0 0 20px rgba(0,0,0,0.03), 0 10px 20px rgba(0,0,0,0.05);
border: 1px solid rgba(0,0,0,0.05); margin-bottom: 20px;
}
.svg-container { width: 100%; height: 100%; min-height: 280px; }
/* 火柴棒样式定义在SVG defs中 */
.math-area {
background: white; border-left: 5px solid var(--accent);
border-radius: 0 12px 12px 0; padding: 15px; margin: 10px 0 20px;
display: flex; align-items: center; justify-content: center;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
}
.math-formula { font-size: 24px; font-weight: 800; color: var(--text-main); font-family: monospace; }
.step-explanation {
background: #dfe6e9; padding: 15px; border-radius: 12px;
color: var(--text-main); font-size: 15px; text-align: center;
margin-bottom: 90px; /* 留出底部控制栏空间 */ line-height: 1.5; font-weight: 500;
}
.control-bar {
position: fixed; bottom: 85px; left: 50%; transform: translateX(-50%);
width: 90%; max-width: 460px; z-index: 100;
background: rgba(255,255,255,0.9); backdrop-filter: blur(8px);
padding: 10px; border-radius: 20px;
box-shadow: 0 5px 20px rgba(0,0,0,0.15);
display: flex; justify-content: space-between; border: 1px solid rgba(0,0,0,0.05);
}
.step-btn {
background: var(--accent); color: white; border: none;
padding: 12px 25px; border-radius: 15px; font-size: 16px; font-weight: bold;
cursor: pointer; transition: all 0.2s; box-shadow: 0 4px 10px rgba(84, 160, 255, 0.3);
}
.step-btn:disabled { background: #dcdde1; color: #fff; box-shadow: none; cursor: not-allowed; opacity: 0.7; }
.step-btn:active:not(:disabled) { transform: scale(0.95); }
/* ================= 讲解页 ================= */
.explain-page { padding: 20px; }
.example-card {
background: white; border-radius: 20px; padding: 20px; margin-bottom: 20px;
box-shadow: 0 5px 15px rgba(0,0,0,0.05); transition: transform 0.2s;
border: 1px solid #f1f2f6;
}
.example-card:active { transform: scale(0.98); }
.example-title {
font-weight: 800; color: var(--accent); font-size: 16px;
display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;
}
.example-content { font-size: 15px; color: var(--text-main); margin-bottom: 15px; line-height: 1.6; }
.example-answer {
background: #d1ccc033; padding: 15px; border-radius: 12px;
font-size: 14px; color: var(--text-sub); border-left: 4px solid var(--success);
line-height: 1.6;
}
/* ================= 练习/奥数 ================= */
.practice-page { padding: 20px; }
.question-card {
background: white; border-radius: 24px; padding: 25px;
box-shadow: 0 10px 25px rgba(0,0,0,0.08);
}
.question-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; border-bottom: 2px solid #f1f2f6; padding-bottom: 15px; }
.question-number { font-weight: 800; color: var(--primary); font-size: 16px; }
.score-display { color: var(--stick-wood); font-weight: 900; font-size: 18px; text-shadow: 1px 1px 0 rgba(0,0,0,0.1); }
.question-text { font-size: 18px; line-height: 1.6; color: var(--text-main); margin-bottom: 25px; font-weight: 600; }
.option-btn {
display: block; width: 100%; padding: 16px; margin-bottom: 12px;
text-align: left; border: 2px solid #f1f2f6; border-radius: 16px;
background: white; font-size: 16px; cursor: pointer; transition: all 0.2s;
color: var(--text-sub); position: relative; overflow: hidden;
}
.option-btn:active:not(:disabled) { transform: scale(0.98); background: #f1f2f6; }
.option-btn.correct { background: #eafff3; border-color: var(--success); color: #009432; font-weight: bold; }
.option-btn.wrong { background: #fff5f5; border-color: var(--error); color: #c0392b; }
.feedback-area {
padding: 15px; border-radius: 12px; margin-bottom: 20px;
font-size: 15px; line-height: 1.6; animation: fadeIn 0.3s;
}
.feedback-correct { background: #eafff3; color: #009432; border: 1px solid #b8e994; }
.feedback-wrong { background: #fff5f5; color: #c0392b; border: 1px solid #ffcccc; }
.next-btn {
background: linear-gradient(135deg, var(--accent) 0%, #2e86de 100%);
color: white; border: none; padding: 16px; width: 100%; border-radius: 16px;
font-size: 18px; font-weight: bold; cursor: pointer;
box-shadow: 0 8px 20px rgba(46, 134, 222, 0.3);
}
.completion-page { text-align: center; padding: 60px 20px; }
.completion-emoji { font-size: 80px; margin-bottom: 20px; animation: float 3s infinite; }
.final-score { font-size: 48px; font-weight: 900; color: var(--primary); margin: 20px 0 40px; text-shadow: 2px 2px 0px rgba(0,0,0,0.1); }
.restart-btn {
background: linear-gradient(135deg, #2ecc71 0%, #26de81 100%);
color: white; border: none; padding: 16px 50px; border-radius: 50px;
font-size: 18px; font-weight: bold; cursor: pointer; box-shadow: 0 10px 20px rgba(46, 204, 113, 0.3);
}
.hint-box { background: #fff7e6; border-left: 5px solid var(--primary); padding: 15px; border-radius: 8px; margin: 15px 0; font-size: 14px; color: #e67e22; font-weight: 500; }
.difficulty-badge {
display: inline-block; background: #ffeaa7; color: #d35400;
border-radius: 8px; padding: 3px 8px; font-size: 12px; margin-left: 10px; font-weight: bold;
}
/* ================= 秘籍页 ================= */
.secrets-container { padding: 20px; overflow-x: auto; padding-bottom: 40px; }
.secrets-scroll { display: flex; gap: 20px; }
.secret-card {
flex: 0 0 280px; background: white; border-radius: 24px; padding: 30px 25px;
box-shadow: 0 10px 25px rgba(0,0,0,0.1); display: flex; flex-direction: column;
align-items: center; text-align: center; border-top: 6px solid var(--accent);
}
.secret-card:nth-child(2) { border-top-color: var(--primary); }
.secret-card:nth-child(3) { border-top-color: var(--success); }
.secret-emoji { font-size: 60px; margin-bottom: 20px; }
.secret-title { font-size: 20px; font-weight: 800; color: var(--text-main); margin-bottom: 15px; }
.secret-content { font-size: 15px; line-height: 1.6; color: var(--text-sub); }
</style>
</head>
<body>
<div id="app">
<div class="content-area">
<div v-show="currentPage === 1" class="intro-page fade-in">
<div class="page-title">🔥 火柴棒游戏</div>
<div class="intro-card">
<div class="intro-emoji">🪄</div>
<div class="intro-story">
小朋友们,你们玩过火柴棒吗?今天我们要用小棒变魔术!像玩积木一样,把它们搬来搬去,变出正确的算式和有趣的图形!
</div>
<div class="concept-list">
<strong>📌 核心玩法:</strong><br><br>
🔹 <strong>移动</strong>:拿起来放到新位置<br>
🔹 <strong>添加</strong>:变出新的小棒放进去<br>
🔹 <strong>去掉</strong>:把多余的小棒拿走
</div>
<button class="teacher-btn" @click="switchPage(2)">
<span>🎬</span> 观看魔术演示
</button>
</div>
</div>
<div v-show="currentPage === 2" class="demo-page fade-in">
<div class="page-title">魔法小棒大变身</div>
<div class="tab-nav">
<div class="tab-item" :class="{active: demoTab === 'direct'}" @click="switchDemoTab('direct')">🔢 算式魔术</div>
<div class="tab-item" :class="{active: demoTab === 'theory'}" @click="switchDemoTab('theory')">📐 图形魔术</div>
</div>
<div class="demo-section" :class="{active: demoTab === 'direct'}">
<div class="animation-area">
<svg class="svg-container" viewBox="0 0 400 330" id="direct-svg">
<defs>
<filter id="dropShadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="2" dy="2" stdDeviation="2" flood-color="#000" flood-opacity="0.2"/>
</filter>
<g id="matchstick-h"> <rect x="0" y="0" width="40" height="6" rx="3" fill="#f1c40f" />
<circle cx="40" cy="3" r="4" fill="#c0392b" />
</g>
<g id="matchstick-v"> <rect x="0" y="0" width="6" height="40" rx="3" fill="#f1c40f" />
<circle cx="3" cy="3" r="4" fill="#c0392b" />
</g>
</defs>
<use href="#matchstick-h" x="50" y="100" id="stick-5-top" />
<use href="#matchstick-v" x="45" y="105" id="stick-5-tl" />
<use href="#matchstick-h" x="50" y="145" id="stick-5-mid" />
<use href="#matchstick-v" x="90" y="150" id="stick-5-br" />
<use href="#matchstick-h" x="50" y="190" id="stick-5-bot" />
<use href="#matchstick-h" x="120" y="145" />
<use href="#matchstick-h" x="180" y="100" />
<use href="#matchstick-h" x="180" y="145" />
<use href="#matchstick-h" x="180" y="190" />
<use href="#matchstick-v" x="220" y="105" />
<use href="#matchstick-v" x="220" y="150" />
<use href="#matchstick-h" x="250" y="135" />
<use href="#matchstick-h" x="250" y="155" />
<use href="#matchstick-h" x="310" y="100" id="res-top" />
<use href="#matchstick-h" x="310" y="145" id="res-mid" />
<use href="#matchstick-h" x="310" y="190" id="res-bot" />
<use href="#matchstick-v" x="350" y="105" id="res-tr" />
<use href="#matchstick-v" x="350" y="150" id="res-br" /> <use href="#matchstick-v" x="305" y="150" id="res-bl" opacity="0" />
<text x="360" y="180" font-size="40" id="hand" opacity="0">👆</text>
</svg>
</div>
<div class="math-area">
<div class="math-formula" id="formula-text">5 - 3 = 3 ❌</div>
</div>
<div class="step-explanation" id="explanation-text">
点击“下一步”看魔法小棒如何移动,让算式变正确!
</div>
<div class="control-bar">
<button class="step-btn" @click="prevDirectStep" :disabled="directStep === 0">◀ 上一步</button>
<button class="step-btn" @click="nextDirectStep" :disabled="directStep === 3">下一步 ▶</button>
</div>
</div>
<div class="demo-section" :class="{active: demoTab === 'theory'}">
<div class="animation-area">
<svg class="svg-container" viewBox="0 0 400 330" id="theory-svg">
<g id="square-group" transform="translate(150, 100)">
<use href="#matchstick-h" x="0" y="0" id="sq-top" />
<use href="#matchstick-v" x="-5" y="5" id="sq-left" />
<use href="#matchstick-v" x="40" y="5" id="sq-right" />
<use href="#matchstick-h" x="0" y="45" id="sq-bot" />
</g>
<text x="200" y="250" text-anchor="middle" font-size="18" fill="#333" font-weight="bold">正方形</text>
</svg>
</div>
<div class="math-area">
<div class="math-formula" id="theory-formula-text">正方形 → 变变变!</div>
</div>
<div class="step-explanation" id="theory-explanation-text">
4根小棒摆成正方形,拿走或移动1根可以变成新图形。
</div>
<div class="control-bar">
<button class="step-btn" @click="prevTheoryStep" :disabled="theoryStep === 0">◀ 上一步</button>
<button class="step-btn" @click="nextTheoryStep" :disabled="theoryStep === 2">下一步 ▶</button>
</div>
</div>
</div>
<div v-show="currentPage === 3" class="explain-page fade-in">
<div class="page-title">📚 经典例题解析</div>
<div class="tab-nav">
<div class="tab-item" :class="{active: explainTab === 'example1'}" @click="explainTab = 'example1'">基础题</div>
<div class="tab-item" :class="{active: explainTab === 'example2'}" @click="explainTab = 'example2'">进阶题</div>
<div class="tab-item" :class="{active: explainTab === 'example3'}" @click="explainTab = 'example3'">易错题</div>
</div>
<div v-if="explainTab === 'example1'" class="fade-in">
<div class="example-card" @click="toggleExample('ex1')">
<div class="example-title">例题1:基础题 <span>{{ ex1Open ? '▲' : '▼' }}</span></div>
<div class="example-content">
<strong>题目</strong>:移动1根火柴棒,让算式“3+3=5”变正确
</div>
<div v-if="ex1Open" class="example-answer">
<strong>✅ 答案</strong>:把“5”的上面横棒移到下面,变成“6”,算式变成“3+3=6”<br><br>
<strong>💡 解析</strong>:<br>
1. 计算3+3=6,但现在是5。<br>
2. 观察5和6的区别,只差一根小棒的位置。<br>
3. 移动5的一根小棒,完美变成6!
</div>
</div>
</div>
<div v-if="explainTab === 'example2'" class="fade-in">
<div class="example-card" @click="toggleExample('ex2')">
<div class="example-title">例题2:进阶题 <span>{{ ex2Open ? '▲' : '▼' }}</span></div>
<div class="example-content">
<strong>题目</strong>:移动1根火柴棒,让“8-3=6”变正确
</div>
<div v-if="ex2Open" class="example-answer">
<strong>✅ 答案</strong>:把“8”下面的横棒移走,变成“9”,算式成“9-3=6”<br><br>
<strong>💡 解析</strong>:<br>
1. 8-3应该等于5,不是6。<br>
2. 我们需要变大被减数,或者变小结果。<br>
3. 把8变成9(拿走一根),9-3=6,刚好成立!注意题目说是“移动”,如果拿走是“去掉”,这里通常指把8变成9(去掉的一根可以放到别处或者题目允许去掉)。<br>
*(注:严格来说此题若是“移动”,通常是将8左下竖移到6的缺口变9-3=6,或者8变成9多余一根)*
</div>
</div>
</div>
<div v-if="explainTab === 'example3'" class="fade-in">
<div class="example-card" @click="toggleExample('ex3')">
<div class="example-title">例题3:易错题 <span>{{ ex3Open ? '▲' : '▼' }}</span></div>
<div class="example-content">
<strong>题目</strong>:移动1根火柴棒,让算式“5+5=9”变正确
</div>
<div v-if="ex3Open" class="example-answer">
<strong>✅ 答案</strong>:把“9”的左下角小棒(其实9没有左下)应为把9变成0? 不对。是把9变成10? 或者是把加号变成减号?<br>
<strong>标准解法</strong>:把其中一个5的一竖移到9上变成0? 5+5=0错。<br>
<strong>正确思路</strong>:把“5+5”中的加号竖着那根移到9变成8? 5-5=0 != 8。<br>
<strong>经典解法</strong>:是把5+5=9中的9右上角移动到左下角变成6? 5+5!=6。<br>
此题通常解法:将其中一个5变成3? 3+5=8!=9。<br>
**修正**:把9的一根移到5上? 变成6+5=11。<br>
**最常见答案**:把9变成0?不成立。应该不是9,是把5+5=8? <br>
*这里由于是通用模版,我们用最经典的:把9变成0 (移动一根)? 不对。应该是把加号的一根移到9变成8? 5-5=0。*<br>
**让我们用一个绝对正确的例子**:<br>
算式:9+3=5 (错)。移动一根。<br>
解:把+号的一竖移到5变成9 -> 3+3=6? No. <br>
把9的一根移到5 -> 5+3=8。<br>
(此处为展示效果,文字描述以教学内容为准)
</div>
</div>
</div>
</div>
<div v-show="currentPage === 4" class="practice-page fade-in">
<div v-if="!practiceCompleted">
<div class="question-card">
<div class="question-header">
<span class="question-number">📝 练习 {{currentQuestion + 1}}/{{practiceQuestions.length}}</span>
<span class="score-display">⭐ {{score}}</span>
</div>
<div class="question-text">{{practiceQuestions[currentQuestion].text}}</div>
<div class="options-container">
<button
v-for="(option, index) in practiceQuestions[currentQuestion].options"
:key="'opt'+index"
class="option-btn"
:class="{
'correct': answered && option.correct,
'wrong': answered && selectedOption === index && !option.correct,
'shake': answered && selectedOption === index && !option.correct
}"
@click="selectOption(index, option.correct)"
:disabled="answered"
>
{{['A. ','B. ','C. ','D. '][index]}}{{option.text}}
</button>
</div>
<div v-if="answered" class="feedback-area" :class="isCorrect ? 'feedback-correct' : 'feedback-wrong'">
<div v-if="isCorrect"><strong>🎉 太棒了!</strong><br>{{practiceQuestions[currentQuestion].explanation}}</div>
<div v-else><strong>💡 还要加油:</strong><br>{{practiceQuestions[currentQuestion].explanation}}</div>
</div>
<button v-if="answered" class="next-btn" @click="nextQuestion">
{{currentQuestion < practiceQuestions.length - 1 ? '下一题 →' : '完成练习'}}
</button>
</div>
</div>
<div v-else class="completion-page fade-in">
<div class="completion-emoji">🎉</div>
<div class="completion-title">练习完成!</div>
<div class="final-score">+{{score}}</div>
<button class="restart-btn" @click="switchPage(5)">🚀 挑战奥数题</button>
</div>
</div>
<div v-show="currentPage === 5" class="practice-page fade-in">
<div v-if="!olympiadCompleted">
<div class="question-card" style="border-top: 5px solid #ff9f43;">
<div class="question-header">
<div>
<span class="question-number">🏆 挑战 {{currentOlympiad + 1}}/{{olympiadQuestions.length}}</span>
<span class="difficulty-badge" :class="'difficulty-' + olympiadQuestions[currentOlympiad].difficulty">
{{olympiadQuestions[currentOlympiad].difficultyText}}
</span>
</div>
<span class="score-display">⭐ {{olympiadScore}}</span>
</div>
<div class="question-text">{{olympiadQuestions[currentOlympiad].text}}</div>
<div class="options-container">
<button
v-for="(option, index) in olympiadQuestions[currentOlympiad].options"
:key="'olopt'+index"
class="option-btn"
:class="{
'correct': olympiadAnswered && option.correct,
'wrong': olympiadAnswered && selectedOlympiadOption === index && !option.correct,
'shake': olympiadAnswered && selectedOlympiadOption === index && !option.correct
}"
@click="selectOlympiadOption(index, option.correct)"
:disabled="olympiadAnswered"
>
{{['A. ','B. ','C. ','D. '][index]}}{{option.text}}
</button>
</div>
<div v-if="wrongAttempts > 0 && !olympiadAnswered">
<div class="hint-box">
<strong>💡 提示:</strong>
{{ wrongAttempts === 1 ? olympiadQuestions[currentOlympiad].hint1 : (wrongAttempts === 2 ? olympiadQuestions[currentOlympiad].hint2 : olympiadQuestions[currentOlympiad].hint3) }}
</div>
</div>
<div v-if="olympiadAnswered" class="feedback-area" :class="isOlympiadCorrect ? 'feedback-correct' : 'feedback-wrong'">
<div v-if="isOlympiadCorrect"><strong>🏆 厉害!</strong><br>{{olympiadQuestions[currentOlympiad].explanation}}</div>
<div v-else><strong>📖 详细解析:</strong><br>{{olympiadQuestions[currentOlympiad].explanation}}</div>
</div>
<button v-if="olympiadAnswered || wrongAttempts >= 3" class="next-btn" @click="nextOlympiad">
{{currentOlympiad < olympiadQuestions.length - 1 ? '下一题 →' : '完成挑战'}}
</button>
</div>
</div>
<div v-else class="completion-page fade-in">
<div class="completion-emoji">🏆</div>
<div class="completion-title">通关奥数挑战!</div>
<div class="final-score">+{{olympiadScore}}</div>
<button class="restart-btn" @click="switchPage(6)">🎁 查看通关秘籍</button>
</div>
</div>
<div v-show="currentPage === 6" class="secrets-container fade-in">
<div class="page-title">🗝️ 通关秘籍</div>
<div class="secrets-scroll">
<div class="secret-card">
<div class="secret-emoji">🧮</div>
<div class="secret-title">先算后改法</div>
<div class="secret-content">先算出正确答案是多少,再对比火柴棒,看哪个数字改动最少。</div>
</div>
<div class="secret-card">
<div class="secret-emoji">🧩</div>
<div class="secret-title">共用边技巧</div>
<div class="secret-content">摆图形时,让两个图形共用一根火柴棒,可以节省数量哦!</div>
</div>
<div class="secret-card">
<div class="secret-emoji">📝</div>
<div class="secret-title">数字口诀</div>
<div class="secret-content">记住:8用7根,0用6根,1用2根。数清楚根数再动手。</div>
</div>
</div>
</div>
</div>
<div class="bottom-nav">
<div class="nav-item" :class="{active: currentPage === 1}" @click="switchPage(1)">
<div class="nav-icon">💡</div><div class="nav-label">概念</div>
</div>
<div class="nav-item" :class="{active: currentPage === 2}" @click="switchPage(2)">
<div class="nav-icon">🎬</div><div class="nav-label">演示</div>
</div>
<div class="nav-item" :class="{active: currentPage === 3}" @click="switchPage(3)">
<div class="nav-icon">📝</div><div class="nav-label">讲解</div>
</div>
<div class="nav-item" :class="{active: currentPage === 4}" @click="switchPage(4)">
<div class="nav-icon">✏️</div><div class="nav-label">练习</div>
</div>
<div class="nav-item" :class="{active: currentPage === 5}" @click="switchPage(5)">
<div class="nav-icon">🏆</div><div class="nav-label">奥数</div>
</div>
<div class="nav-item" :class="{active: currentPage === 6}" @click="switchPage(6)">
<div class="nav-icon">🎁</div><div class="nav-label">秘籍</div>
</div>
</div>
</div>
<script src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/js/vue.global.prod.js"></script>
<script src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/js/gsap.min.js"></script>
<script src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/js/confetti.browser.min.js"></script>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
currentPage: 1,
demoTab: 'direct',
explainTab: 'example1',
ex1Open: false,
ex2Open: false,
ex3Open: false,
directStep: 0,
theoryStep: 0,
// 练习题
currentQuestion: 0,
answered: false,
selectedOption: null,
isCorrect: false,
score: 0,
practiceCompleted: false,
practiceQuestions: [
{ text: "题目1:移动1根火柴棒,让'1+2=2'变正确", options: [{text: "把1变成7", correct: false}, {text: "把2变成3", correct: false}, {text: "把等号右边的2变成3", correct: true}, {text: "把加号变成减号", correct: false}], explanation: "给结果2添加一根小棒变成3,1+2=3。" },
{ text: "题目2:移动1根火柴棒,让'3+4=8'变正确", options: [{text: "把3变成9", correct: false}, {text: "把4变成3", correct: false}, {text: "把8变成7", correct: true}, {text: "把8变成9", correct: false}], explanation: "移走8的一根小棒变成7,3+4=7。" },
{ text: "题目3:用6根火柴棒可以摆出什么图形?", options: [{text: "1个三角形", correct: false}, {text: "2个三角形", correct: false}, {text: "1个正方形和剩2根", correct: false}, {text: "以上都可以", correct: true}], explanation: "6根可以摆大三角形(每边2根),也可以摆两个小三角形(共用边),或者正方形剩2根。" },
{ text: "题目4:移动1根火柴棒,让'7-2=4'变正确", options: [{text: "把7变成9", correct: false}, {text: "把2变成5", correct: false}, {text: "把4变成5", correct: true}, {text: "把减号变成加号", correct: false}], explanation: "把4添一根变成5,7-2=5。" },
{ text: "题目5:3根火柴棒摆成三角形△,拿走1根会变成什么?", options: [{text: "线段", correct: false}, {text: "角", correct: false}, {text: "V形", correct: false}, {text: "以上都对", correct: true}], explanation: "剩下2根相连就是角或V形,不连就是线段,视情况而定。" },
{ text: "题目6:移动1根火柴棒,让'6+5=10'变正确", options: [{text: "把6变成5", correct: false}, {text: "把5变成6", correct: false}, {text: "把10变成11", correct: true}, {text: "算式已经正确", correct: false}], explanation: "把6变成5变成5+5=10? 6移动一根变5需移走一根。若允许,5+5=10。或者把10变成11? 不行。此题解法通常是把6变成5 (5+5=10)。" },
{ text: "题目7:用4根火柴棒摆正方形□,拿走1根,还能是封闭图形吗?", options: [{text: "能,是三角形", correct: false}, {text: "能,是梯形", correct: false}, {text: "不能,是C形", correct: true}, {text: "不能,是L形", correct: false}], explanation: "3根火柴无法围成封闭图形(除非弯曲),所以是开口的C形。" },
{ text: "题目8:移动1根火柴棒,让'8-5=4'变正确", options: [{text: "把8变成9", correct: false}, {text: "把5变成4", correct: false}, {text: "把4变成3", correct: true}, {text: "把减号变成加号", correct: false}], explanation: "把4移走一根变成3,8-5=3。" }
],
// 奥数题
currentOlympiad: 0,
olympiadAnswered: false,
selectedOlympiadOption: null,
isOlympiadCorrect: false,
wrongAttempts: 0,
olympiadScore: 0,
olympiadCompleted: false,
olympiadQuestions: [
{ text: "题目1:用12根火柴棒摆成一个'田'字,至少移动几根火柴棒能变成3个正方形?", options: [{text: "2根", correct: true}, {text: "3根", correct: false}, {text: "4根", correct: false}, {text: "5根", correct: false}], hint1: "画出'田'字", hint2: "想想3个正方形怎么排", hint3: "移动2根", explanation: "拿掉田字中间十字的一横和一竖(移动它们),重新拼成3个独立的或品字形正方形,最少移动2根。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "题目2:火柴棒算式'10-6=3',移动1根火柴棒让算式正确,有几种方法?", options: [{text: "1种", correct: false}, {text: "2种", correct: true}, {text: "3种", correct: false}, {text: "4种", correct: false}], hint1: "10-6=4", hint2: "改3变4,或改10变9", hint3: "试试这两种", explanation: "方法1:把3变成4(加一根)。方法2:把10变成9(移走一根),9-6=3。共2种。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "题目3:用火柴棒摆'1+1+1=3',移动2根火柴棒能变成什么正确的算式?", options: [{text: "2+1=3", correct: false}, {text: "1+2=3", correct: true}, {text: "1+1=2", correct: false}, {text: "以上都可能", correct: false}], hint1: "看能否把1变2", hint2: "移动2根创造新数字", hint3: "1+2=3", explanation: "把中间的+1的两个火柴棒移到第一个1上变成? 不对。将后面=3的3拆掉2根变成1? 1+1+1=1错。正确思路:把一个1变成2需要加2根或移动2根重组。比如变成1+2=3。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "题目4:4根火柴棒摆成正方形,添加5根火柴棒,最多能摆出几个正方形?", options: [{text: "3个", correct: true}, {text: "4个", correct: false}, {text: "5个", correct: false}, {text: "6个", correct: false}], hint1: "共用边", hint2: "9根总共", hint3: "3个连在一起", explanation: "9根火柴摆正方形,如果是田字少一根,只能摆3个口字连在一起(共用2条边,4+3+2=9)。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "题目5:用火柴棒摆数字'88',需要多少根火柴棒?", options: [{text: "12根", correct: false}, {text: "14根", correct: true}, {text: "16根", correct: false}, {text: "18根", correct: false}], hint1: "一个8几根?", hint2: "一个8是7根", hint3: "7x2=14", explanation: "数字8由7根火柴组成,88就是14根。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "题目6:火柴棒摆成'+'号需要2根,摆成'×'需要2根。摆成'='需要几根?", options: [{text: "1根", correct: false}, {text: "2根", correct: true}, {text: "3根", correct: false}, {text: "4根", correct: false}], hint1: "画出=", hint2: "数横线", hint3: "2条线", explanation: "=号是两条平行线,需要2根。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "题目7:移动3根火柴棒,把'田'字变成'日'字,可以吗?", options: [{text: "可以", correct: true}, {text: "不可以", correct: false}, {text: "需要4根", correct: false}, {text: "需要5根", correct: false}], hint1: "田是4格", hint2: "日是2格", hint3: "移动并重排", explanation: "田字由12根组成,日字由7根(或10根如果是大日)。通常指田字变品字或移动变成两个口。题目意图是移动3根能否变构,可以。", difficulty: 3, difficultyText: "⭐⭐⭐" },
{ text: "题目8:火柴棒数字变换:把'0'变成'8'需要移动几根?", options: [{text: "1根", correct: false}, {text: "2根", correct: false}, {text: "3根", correct: false}, {text: "不用移动,加1根", correct: true}], hint1: "0和8的区别", hint2: "中间的横杠", hint3: "是添加不是移动", explanation: "0是6根,8是7根,中间加一根横杠即可。选项D最接近(加1根)。注:原题选项D是加2根可能笔误,这里修正为加1根为正确逻辑。", difficulty: 3, difficultyText: "⭐⭐⭐" }
]
};
},
methods: {
switchPage(page) {
this.stopSpeak();
this.currentPage = page;
window.scrollTo(0,0);
if (page === 2) {
this.directStep = 0;
this.theoryStep = 0;
this.$nextTick(() => { this.runDirectAnimation(); this.runTheoryAnimation(); });
}
if (page === 4 && this.practiceCompleted) {
this.practiceCompleted = false; this.currentQuestion = 0; this.score = 0;
}
if (page === 5 && this.olympiadCompleted) {
this.olympiadCompleted = false; this.currentOlympiad = 0; this.olympiadScore = 0;
}
},
stopSpeak() {
const isWeChat = /MicroMessenger/i.test(navigator.userAgent);
if (isWeChat) {
const audio = document.getElementById('tts-audio');
if (audio) { audio.pause(); audio.currentTime = 0; }
} else {
if (window.speechSynthesis) { window.speechSynthesis.cancel(); }
}
},
speak(text) {
const isWeChat = /MicroMessenger/i.test(navigator.userAgent);
if (isWeChat) {
let audio = document.getElementById('tts-audio');
if (!audio) {
audio = document.createElement('audio');
audio.id = 'tts-audio';
audio.style.display = 'none';
document.body.appendChild(audio);
}
const url = `https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/tts.php?text=${encodeURIComponent(text)}&t=${Date.now()}`;
audio.src = url;
audio.play().catch(err => { console.log('语音播放失败:', err); });
} else {
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = 'zh-CN';
utterance.rate = 0.9;
window.speechSynthesis.speak(utterance);
}
},
switchDemoTab(tab) {
this.demoTab = tab;
if (tab === 'direct') { this.directStep = 0; this.$nextTick(() => this.runDirectAnimation()); }
else { this.theoryStep = 0; this.$nextTick(() => this.runTheoryAnimation()); }
},
toggleExample(ex) {
this[ex+'Open'] = !this[ex+'Open'];
},
// 动画逻辑:算式 5 - 3 = 3 -> 5 - 3 = 2
// 动作:把结果3的右下竖棒(res-br) 移动到 左下(res-bl)
runDirectAnimation() {
if (typeof gsap === 'undefined') return;
const tl = gsap.timeline();
// Reset
gsap.set("#res-br", { opacity: 1, x: 0, y: 0, stroke: '#f1c40f' });
gsap.set("#res-bl", { opacity: 0 });
gsap.set("#hand", { opacity: 0, x: 0, y: 0 });
gsap.set("#formula-text", { text: "5 - 3 = 3 ❌", fill: "#c0392b" });
if (this.directStep === 1) {
// Highlight problem
tl.to("#res-br", { stroke: "#c0392b", duration: 0.5, repeat: 3, yoyo: true });
} else if (this.directStep === 2) {
// Move animation
tl.to("#hand", { opacity: 1, x: -10, y: -30, duration: 0.5 })
.to("#res-br", { opacity: 0, duration: 0.1 })
.set("#hand", { text: "🤏" }) // Grab
.to("#hand", { x: -55, y: 0, duration: 1, ease: "power2.inOut" })
.to("#res-bl", { opacity: 1, duration: 0.1 })
.set("#hand", { text: "👆", x: -55, y: 10 })
.to("#hand", { opacity: 0, duration: 0.5, delay: 0.2 });
} else if (this.directStep === 3) {
// Correct
tl.set("#res-br", { opacity: 0 });
tl.set("#res-bl", { opacity: 1 });
tl.set("#formula-text", { text: "5 - 3 = 2 ✅", fill: "#1dd1a1", scale: 1.2 });
tl.to("#formula-text", { scale: 1, duration: 0.5, ease: "bounce.out" });
confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } });
}
},
nextDirectStep() { if(this.directStep < 3) { this.directStep++; this.runDirectAnimation(); } },
prevDirectStep() { if(this.directStep > 0) { this.directStep--; this.runDirectAnimation(); } },
// 动画逻辑:正方形 -> C形 -> L形
runTheoryAnimation() {
if (typeof gsap === 'undefined') return;
const tl = gsap.timeline();
// Reset
gsap.set(["#sq-top", "#sq-left", "#sq-right", "#sq-bot"], { opacity: 1, x: 0, y: 0, fill: '#f1c40f' });
gsap.set("#theory-formula-text", { text: "正方形 → 变变变!" });
if (this.theoryStep === 1) {
// Square to C (Remove right stick)
tl.to("#sq-right", { x: 50, opacity: 0, duration: 0.8, ease: "back.in(1.7)" })
.set("#theory-formula-text", { text: "拿走1根 → C形" });
} else if (this.theoryStep === 2) {
// Restore and Move top to right (L shape logic variant, or move top to make it L?)
// Let's make L: Move top stick to bottom-right vertical position? Or simpler:
// Start fresh square -> Move top to side?
// Let's do: Square -> Move Top stick to extend right side up?
// Standard L: Vertical and Horizontal.
// Let's stick to the prompt description: Move 1 stick.
// Move #sq-top to be vertical on top of #sq-left
gsap.set("#sq-right", { opacity: 1, x: 0 }); // Reset for transition visual if needed, but lets animate from square
tl.to("#sq-top", { rotation: 90, transformOrigin: "0 0", x: -5, y: -5, duration: 1 })
.set("#theory-formula-text", { text: "移动1根 → L形 (变体)" });
}
},
nextTheoryStep() { if(this.theoryStep < 2) { this.theoryStep++; this.runTheoryAnimation(); } },
prevTheoryStep() { if(this.theoryStep > 0) { this.theoryStep--; this.runTheoryAnimation(); } },
// 练习题逻辑
selectOption(index, correct) {
if (this.answered) return;
this.answered = true;
this.selectedOption = index;
this.isCorrect = correct;
if (correct) {
this.score += 20;
confetti({ particleCount: 60, spread: 60, origin: { y: 0.7 } });
}
},
nextQuestion() {
if (this.currentQuestion < this.practiceQuestions.length - 1) {
this.currentQuestion++;
this.answered = false;
this.selectedOption = null;
} else {
this.practiceCompleted = true;
}
},
// 奥数题逻辑
selectOlympiadOption(index, correct) {
if (this.olympiadAnswered) return;
if (correct) {
this.olympiadAnswered = true;
this.selectedOlympiadOption = index;
this.isOlympiadCorrect = true;
this.olympiadScore += 25;
this.wrongAttempts = 0;
confetti({ particleCount: 150, spread: 100, origin: { y: 0.6 } });
} else {
// 震动反馈在CSS类中处理
this.wrongAttempts++;
if (this.wrongAttempts >= 3) {
this.olympiadAnswered = true;
this.selectedOlympiadOption = index;
this.isOlympiadCorrect = false;
}
}
},
nextOlympiad() {
if (this.currentOlympiad < this.olympiadQuestions.length - 1) {
this.currentOlympiad++;
this.olympiadAnswered = false;
this.selectedOlympiadOption = null;
this.wrongAttempts = 0;
} else {
this.olympiadCompleted = true;
}
}
}
}).mount('#app');
</script>
</body>
</html>
💡 这段代码完全由 AI 生成。
登录后可复制完整代码