
最近给孩子做了一个小工具:TimesTableGO,一个安卓端乘法口诀背诵 App。
它最初的目标很朴素: 孩子背乘法口诀时,家长不一定时时有空陪练;纸面刷题又容易枯燥;单纯点选答案虽然方便,但和真实背诵场景有距离。所以我想做一个更接近“真人陪练”的 App:它能出题、能读题、能听孩子回答、能判断对错,还能把错题和练习表现记录下来。
简单说,它不是一个“选择题刷题器”,而是一个语音版乘法口诀陪练小老师。
很多孩子学习乘法口诀时,会遇到几个典型问题:
第一,背得出来不等于反应快。 孩子可能会背“二三得六、三四十二”,但一旦随机问“7×8 等于多少”,就容易卡壳。
第二,家长陪练成本高。 乘法口诀练习本身不复杂,但需要大量重复。家长需要不断出题、判断、纠错、鼓励,这件事看似简单,长期坚持其实很消耗精力。
第三,错题容易被忽略。 孩子不是每一道都不会,而是常常卡在少数几道题上,比如 6×7、7×8、8×9。传统练习很容易“一遍过”,但真正需要的是反复命中薄弱点。
第四,练习体验需要更像“背诵”,而不是“点按钮”。 乘法口诀本质上是口头熟练度训练。让孩子“说出来”,比让孩子“点出来”,更接近真实掌握。
于是我做了 TimesTableGO:一个面向孩子的乘法口诀语音陪练 App。
当前版本是一个 Android MVP,核心能力包括:
随机出题App 会随机生成 1 到 9 的乘法题,例如:
7 x 8 = ?
开始 / 停止练习孩子可以进入连续练习模式,也可以随时停止。停止后,本次练习结果会保存。
语音读题App 可以把题目读出来,例如“7 乘以 8 等于多少”。这让孩子可以像被老师或家长提问一样练习。
语音作答孩子在限定时间内直接说出答案。App 会通过语音识别拿到转写结果。
多种语音识别方式当前支持三类 ASR 模式:
本地答案校验 + 可选大模型校验对于“我说的是五十六”“五十六”“56”这类回答,App 会尽量从语音转写中提取数字。 如果开启大模型校验,也可以调用 OpenAI 兼容接口,让模型帮助从转写文本中提取答案。
本地统计练习历史App 会记录每次作答情况,包括题目、识别文本、提取答案、是否正确、校验方式等。
高频错题与正确率反馈它不仅记录“答对几题”,还会关注哪些题更容易错,后续练习时会提高这些题出现的概率。
老师寄语如果配置了大模型 API,App 可以根据孩子的练习统计生成一段鼓励性、具体、温暖的中文寄语。它不是冷冰冰地说“错了”,而是像一个小老师一样告诉孩子:哪里进步了,下一步可以练什么。
一次练习大致是这样的:
点击开始
↓
生成一道乘法题
↓
更新 UI:显示题目
↓
TTS 读题
↓
开启语音作答窗口
↓
系统 ASR / 百度 ASR / Azure Speech 获取转写文本
↓
从转写文本中提取答案
↓
本地校验或大模型校验
↓
给出反馈:答对 / 答错 / 正确答案
↓
保存本次 Attempt
↓
更新统计
↓
进入下一题
这个流程的关键点不在于“能不能算出 7×8=56”。 这个当然很简单。
真正关键的是:如何把一个儿童练习场景做成稳定、可持续、可反馈的闭环。
也就是:
出题 → 听答 → 判题 → 反馈 → 统计 → 针对性复习
这才是这个 App 的核心价值。
项目里有几个很关键的数据模型。
data class Problem(val a: Int, val b: Int) {
val answer: Int = a * b
val label: String = "$a x $b"
val prompt: String = "$a 乘以 $b 等于多少"
}
它不仅保存 a 和 b,还保存:
这样做的好处是: 题目不只是一个数学表达式,而是一个可以展示、朗读、订正的练习对象。
data class Attempt(
val a: Int,
val b: Int,
val expected: Int,
val transcript: String,
val extractedAnswer: Int?,
val correct: Boolean,
val checkedBy: String,
val timestamp: Long = System.currentTimeMillis()
)
这个结构记录了孩子每一次作答的完整信息:
有了这些数据,后面才能做错题统计、正确率趋势、老师寄语和针对性复习。
data class PracticeSession(
val total: Int,
val correct: Int,
val timestamp: Long = System.currentTimeMillis()
)
这个结构用于记录一次完整练习的总体表现,比如本次练了多少题、答对多少题。 它适合用来做“最近练习记录”和“正确率变化”。
AppSettings 里保存了语音和模型相关配置,例如:
这让 App 不必把外部服务写死,用户可以在设置里灵活切换。
如果每次都完全随机,孩子可能会反复遇到已经很熟的题,而真正容易错的题出现频率不够。
所以 App 里做了一个简单但很实用的策略:错题加权。
核心思想是:
题目权重 = 基础权重
+ 历史错误次数 × 3
+ 最近一次答错奖励
+ 从未练过奖励
再把权重限制在一个合理范围内,避免某一道题无限放大。
伪代码可以理解为:
fun problemWeight(problem: Problem): Int {
val rows = attempts.filter { it.a == problem.a && it.b == problem.b }
val wrongCount = rows.count { !it.correct }
val recentWrongBonus = if (rows.firstOrNull()?.correct == false) 4 else 0
val neverPracticedBonus = if (rows.isEmpty()) 1 else 0
return (1 + wrongCount * 3 + recentWrongBonus + neverPracticedBonus)
.coerceIn(1, 20)
}
这样一来,孩子不是机械刷题,而是在不断被引导回到薄弱点上。
从学习效果角度看,这比“纯随机”更接近刻意练习:
会的题保持熟练
不会的题提高出现概率
刚错的题尽快复现
长期目标是整张乘法表都稳定答对
这也是我觉得这个 App 最有意义的地方之一。
乘法口诀不是只会选答案,而是要脱口而出。
所以我把语音交互作为核心体验,而不是附加功能。
当前支持三种识别路径:
系统 ASR
百度 ASR
Azure Speech
如果只是自己家里使用,系统 ASR 通常最方便,不需要配置密钥。 如果想提高可控性,可以配置百度或 Azure。
语音作答流程大致如下:
进入答题阶段
↓
倒计时
↓
录音或调用系统语音识别
↓
拿到转写结果
↓
提取数字
↓
判题
比如孩子说:
“五十六”
ASR 可能转写成:
五十六
或者:
56
App 会尽量从转写结果里提取出数字,再和标准答案比较。
这让练习方式从“我点一个按钮”变成了“我真的说出了答案”。 对于背诵类训练,这一点很重要。
对于乘法口诀,绝大多数情况下本地校验就够了。 比如识别到 56,直接判断是否等于 a*b。
但现实语音转写可能会出现各种情况:
“五十六”
“应该是五十六”
“我觉得是五十六”
“呃……五十六”
这时候,如果只用正则或简单规则,可能会有边界问题。
所以 App 里提供了可选的大模型校验能力。 它不是让大模型去算乘法,而是让大模型做一件更适合它的事:
从学生语音转写里提取一个整数答案。
这是一个很实用的设计: 大模型不是为了炫技,而是放在最容易产生歧义的“自然语言理解”环节。
整个校验可以分成两级:
优先本地提取数字
↓
如果开启大模型,则让模型从转写文本中提取答案
↓
再和标准答案比较
这样既保留了本地逻辑的稳定性,也给复杂转写场景留了扩展空间。
孩子练习时,反馈很重要。
如果 App 只是冷冰冰地说:
答错了。
那它很快就会变成一个有压力的刷题工具。
所以我在里面加入了“老师寄语”思路: 根据孩子的练习统计,生成一段积极、具体、温暖的中文鼓励。
比如它可以围绕这些信息生成反馈:
它的目标不是替代老师,而是让孩子在练习后得到一个更人性化的总结:
你今天已经能稳定答对很多题了,特别是 2、3、4 的口诀很熟练。
下一步可以重点练 7×8 和 8×9,慢慢来,你会越来越快。
这类反馈对于低龄孩子很有意义。 他们需要的不只是判分,还需要被看见、被鼓励、被引导。
App 会保存最近的作答记录和练习会话。
这些数据可以用来回答几个关键问题:
今天练了多少题?
答对了多少?
哪些题经常错?
最近有没有进步?
整张乘法表是否已经掌握?
这对家长也很有帮助。
因为家长不一定要全程盯着孩子练习,只要看统计,就能知道孩子到底卡在哪里。
例如:
高频错题:7×8、6×7、8×9
最近正确率:82%
本次练习:30 题,答对 26 题
这比一句“孩子还不熟”更具体,也更方便安排后续练习。
虽然这是一个给孩子用的小 App,但我还是给它加了 GitHub Actions 自动构建流程。
大致流程是:
push 到 main
↓
GitHub Actions 拉取代码
↓
配置 JDK 17
↓
配置 Android SDK
↓
配置 Gradle
↓
读取签名密钥
↓
构建 release APK
↓
上传 artifact
↓
发布到 latest Release
这样做有几个好处:
第一,避免本地环境污染。 只要代码能在 GitHub Actions 上构建,就说明项目可复现。
第二,方便给别人体验。 朋友或家长想试用时,可以直接下载 APK。
第三,签名一致。 后续更新 App 时,不会因为签名不同导致必须卸载重装。
第四,工程更规范。 哪怕是一个小工具,也可以按正式项目的方式维护。
我觉得 TimesTableGO 特别适合几类场景:
尤其是刚开始从“会背顺口溜”过渡到“随机问答”的阶段。
App 可以承担一部分重复提问和即时反馈工作。
不是看题点答案,而是直接说出来。
这个 App 它不是为了做 AI 而做 AI,也不是为了炫技而堆功能。 它解决的是一个很真实的问题:
孩子要背乘法口诀,
家长想陪练,
但重复练习很消耗时间,
孩子又需要及时反馈和鼓励。
所以它的设计路线也很明确:
能本地解决的,本地解决;
语音交互必要的,接入 ASR;
自然语言有歧义的,交给大模型;
学习表现要长期观察,就做本地统计;
孩子需要正反馈,就做老师寄语。
技术最终还是要回到人。 对我来说,这个项目就是一次很小但很有成就感的实践:把 Android、语音识别、大模型和家庭学习场景结合起来,做成一个孩子真的能用的小工具。
演示视频:https://www.bilibili.com/video/BV1A8LR6KEgE
项目名:TimesTableGO项目类型:Android 乘法口诀背诵 App 技术栈:Kotlin + Jetpack Compose 适用场景:孩子乘法口诀随机背诵、语音陪练、错题复习、家长辅助练习
可以在 GitHub 搜索:
kobe24o/TimesTableGO
安卓apk 下载地址:https://github.com/kobe24o/TimesTableGO/releases/tag/latest
如果你家里也有正在背乘法口诀的小朋友,可以试试看。 也欢迎给项目点个 Star,提 Issue,或者直接 Fork 一份改造成适合自己孩子的版本。
一个小 App,也许不能替代家长和老师, 但它可以帮孩子多练几遍,帮家长少重复几句, 帮学习这件事变得更轻松一点。
这就是 TimesTableGO 的初衷。