带过几轮等级考试集训之后,我越来越确认一件事:Scratch入门阶段的“封神题”不是那些花哨的动画作品,而是陶陶摘苹果。这道题几乎把顺序、分支、循环、列表四类核心知识点全揉在了一起,题目本身却简单到一句话就能说清,特别适合用来检验学员到底是真的理解了编程逻辑,还是只是会拖积木。青少年等级考试图形化编程一级、二级的真题里,隔三差五就能见到它的身影。
很多孩子第一次拿到这道题,第一反应是兴奋地开始画苹果树、设计陶陶的角色造型。但真正动手之后才发现,难的不是画角色,而是怎么把“陶陶最终能摘到几个苹果”这件事准确算出来。这篇文章我会从最朴素的顺序结构版本讲起,逐步升级到“列表+循环”的标准解法,再聊到带交互反馈的动画版,最后把学员最容易踩的坑和考试里常见的变体一起梳理一遍。无论你是正在备考的学员,还是带学生的老师,都可以照着完整做一遍。
1. 先看懂题目:陶陶摘苹果到底在考什么
1.1 题目描述与数学建模
陶陶摘苹果的原始题面很简洁,大意是:陶陶家的院子里有一棵苹果树,每年秋天树上会结出10个苹果。陶陶有一个30厘米高的板凳,身高是150厘米。当苹果离地高度不超过“身高+板凳高度”时,陶陶就能摘到。现在给出10个苹果离地的高度,要求统计陶陶能摘到几个苹果。
我特意把题面重新组织了一遍,因为它正好对应编程里的“输入-处理-输出”三步。题目给定的10个苹果高度就是输入,判断规则就是处理过程,最终要输出的则是摘到的苹果数量。
把这件事抽象成数学表达式会更清晰:设陶陶身高为h,板凳高度为b,某个苹果离地高度为a,那么能摘到的条件是 h + b >= a。成立一次,计数就加1。下面这个表格把输入、变量和规则拆开了,方便初学的孩子对照:
| 项目 | 含义 | 示例值 |
|---|---|---|
| h | 陶陶的身高 | 150 cm |
| b | 板凳的高度 | 30 cm |
| h+b | 陶陶伸手能达到的最大高度 | 180 cm |
| a | 单个苹果离地高度 | 100~200 cm |
| 判断规则 | 苹果高度 a 是否 <= h+b | 例如 170 <= 180,能摘到 |
教学时我强调得最多的一个关键点是:不要把“板凳”“身高”当成两个独立变量反复去比较,而是先算出陶陶伸手能达到的最大高度,也就是 h+b,然后让每个苹果的高度去和这个最大值比大小。这个简化几乎直接决定了后面积木搭建的简洁程度。如果每个苹果都单独去算身高加板凳再比较,代码会冗余,也更容易出错。
1.2 三个审题陷阱
哪怕学员说“我看懂题意了”,也常常会在三个地方出错。
第一个陷阱是高度比较的方向。题面说的是苹果离地面的高度,不是苹果离陶陶手的位置的高度。有些孩子会写出“150 - 苹果高度 >= 30”这类错误不等式,把方向搞反了。正确的逻辑不是用身高去减苹果高度,而是把身高和板凳加在一起形成“可摘上限”,再和苹果高度比较。
第二个陷阱是等于号的处理。当 h+b 刚好等于 a 时,陶陶正好能够到,应该算能摘到。所以判断条件必须是 h+b >= a,而不是 h+b > a。这个细节虽然只差一个符号,但在严格判分的环境中就是0分和满分的差别。
第三个陷阱出现在“最多能摘到几个”这句表述上。个别题面会写“陶陶最多能摘到几个苹果”,这并不意味着要去做选择,优先摘哪些不摘哪些。因为题目没有设置“摘了这个就不能摘那个”的限制,能摘到的都会摘,本质仍然是对全部苹果做一次遍历统计。
我在正式搭积木之前,一定会让学生先在白板上把判断条件写对。代码可以慢慢调,条件要是错了,后面全是无用功。
1.3 动手之前先规划变量
Scratch里拖积木之前,先把需要用到的变量列出来,这个习惯对初学者特别有帮助。陶陶摘苹果这道题,最少需要三个变量:
| 变量名 | 作用 | 初始值 |
|---|---|---|
| 可摘高度 | 存放 h+b 的计算结果 | 150+30 |
| 摘到数量 | 统计满足条件的苹果个数 | 0 |
| 序号 | 列表循环时记录当前读取第几项 | 1 |
有些学员会困惑为什么要单独设一个“可摘高度”,直接每次判断时写“150 + 30 >= 苹果高度”不行吗?答案是可以,但可读性差,而且如果题目改成运行时输入板凳高度,你就得在每个判断里都改一次。用变量把“可摘高度”提前算出来,整个程序的逻辑就清晰了:先是准备阶段,再是判断阶段,最后是输出阶段。
2. 第一版实现:顺序结构逐条比较,先把逻辑跑通
2.1 初始化和询问输入
第一版不追求代码精简,只求把判断逻辑跑通。我一般要求学员在舞台上创建好变量之后,按以下顺序搭积木:
- 当绿旗被点击
- 将“摘到数量”设为 0
- 将“可摘高度”设为 150 + 30
- 询问“请输入第1个苹果的高度”并等待
- 如果 回答 <= 可摘高度,那么 将“摘到数量”增加 1
- 重复第4步和第5步,一直处理到第10个苹果
- 说“可以摘到 [摘到数量] 个苹果”
这套逻辑主要用到Scratch里的“询问并等待”和“回答”两个积木。“询问并等待”是一个交互积木,程序运行到这一行时,舞台下方会弹出输入框,用户输入数字后点击对勾,输入的内容就存进“回答”这个内置变量里。需要说明的是,“回答”变量不需要手动创建,Scratch会自动维护,但它的值会随着每一次询问变化,所以每次判断都要紧跟在那次询问之后。
2.2 十个条件的“笨办法”积木搭法
十个苹果就需要写十组“询问-判断”积木。虽然看起来冗长,但我刻意不让学员直接跳到循环。原因是:先亲眼看懂“重复做同一件事”的过程,后面引入循环时,他才知道循环到底替代了什么。
这十组积木结构上完全一样,唯一的区别是“询问”里的提示文字从“第1个苹果”变成了“第10个苹果”。判断部分用到的一律是“可摘高度”和“回答”。
这里有一个我强烈建议的操作细节:把第一组积木复制成十份之后,一定让学员自己手动去改掉每一条“询问”里的编号文字。这个动作看着不起眼,却能让人在改文字的过程中潜意识地感受到:“这十段东西几乎一模一样,明明应该有办法只写一次。”等到讲循环的时候,学员的接受度会高很多,因为他自己已经产生了“想要偷懒”的念头,这时候再给他一个合理的偷懒方式,他会非常愿意接受。
全部搭完之后,运行一遍,依次输入10个数字,比如:100、200、150、140、129、134、167、198、200、111。手算一下,可摘高度是180,那么100、150、140、129、134、167、111这7个都能摘到。程序说出7,就说明这一版逻辑跑通了。
2.3 为什么我还要让学员先写笨办法
有些同行会觉得顺序结构版太低级,不如直接上列表和循环。但按我的经验,直接上抽象结构的结果往往是:学员确实能把积木拖出来,可一旦判断条件变化、苹果个数增加,就完全不会改了。顺序结构版虽然笨,但它的每一步都对应题面的一句话,学员能指着积木说清楚“这是在判断第一个苹果”。这个“能说清楚”比“能拖出来”重要得多。
另外,顺序结构版也方便调试。如果统计结果多了或者少了,直接从第一组判断开始人工模拟,手动算一遍答案,马上就能定位到是哪一组积木出了问题。这对初学阶段来说,是非常有价值的排错训练。
3. 第二版实现:用列表和循环消除重复代码
3.1 列表在这里解决了什么问题
顺序结构版跑通之后,我会接着问学员一个问题:如果树上不是10个苹果,而是100个呢?顺序结构版就得写100组一模一样的积木,这显然不合理。
这时候列表就该登场了。可以把Scratch的列表理解成一串带编号的盒子,每个盒子里放一个数据。苹果的高度数据可以提前存进列表,然后用循环从第1项一路遍历到第10项,每一项执行同样的判断。判断逻辑只写一次,却执行了10次。这就是“数据与操作分离”的雏形,也是很多复杂作品的基础。
3.2 完整积木逻辑:录入、遍历、判断、计数
第二版的搭建可以拆成四步。
第一步,创建列表“苹果高度”,把10个数据录入进去。录入有两种常见方式:一种是用“将 100 加入 苹果高度”这类积木,把数据直接写在代码里;另一种是用询问,让用户运行程序时手动输入。如果是准备等级考试,我建议用第一种,因为数据是题目给定的,提前写死在列表里更稳定,完全避开手动输入可能出现的格式问题。
第二步,设置初始变量。把“摘到数量”设为0,把“可摘高度”设为150+30,再把“序号”设为1。这个“序号”变量用来指定当前读取列表的第几项。
第三步,重复执行直到“序号 > 10”。循环体内先取出“苹果高度”的第“序号”项,判断它是否小于等于“可摘高度”,如果是,就把“摘到数量”增加1。最后一步非常关键,一定要让“序号”增加1。漏掉这一步,程序会永远停留在这个判断上,形成死循环,列表第1项被反复判断,计数疯狂上涨。
第四步,循环结束之后,让角色说出“可以摘到 [摘到数量] 个苹果”。
这里有个很容易混淆的点:Scratch提供了多种循环积木,这道题适合用“重复执行直到”而不是“重复执行10次”。原因在于“重复执行直到”把结束条件写得特别明确,当数据量从10变成20时,只需要把“序号 > 10”改成“序号 > 20”,对初学者来说更好理解。而“重复执行10次”虽然也能实现,但要额外处理序号,逻辑上绕了一层。
3.3 判断条件的边界:>= 还是 >
这一步我每次都要专门停下来强调。在Scratch的运算积木里,“<=”表示小于等于。如果误用成“<”,当苹果高度恰好等于可摘高度时,陶陶本可以摘到,程序却会判为摘不到。边界条件在等级考试里经常被用来设置干扰项,题目给出的数据很可能就包含一个“刚好等于可摘高度”的苹果,用来检验你有没有把等号考虑进去。
还有一个容易忽略的点:如果题面把身高或板凳高度也作为运行时输入的变量,而不是固定数值,那么“可摘高度”这个变量在初始化时要写成“身高 + 板凳高度”的加法表达式,不能直接写成180。这样后续即使题目把板凳高度从30改成50,程序依然正确。
下面用表格对比一下第一版和第二版的差异,方便课程设计时直观参考:
| 维度 | 顺序结构版 | 列表+循环版 |
|---|---|---|
| 判断积木数量 | 10组 | 1组 |
| 数据修改方式 | 改代码 | 改列表 |
| 可扩展性 | 每加一个苹果加一组积木 | 改循环结束条件 |
| 初学者的理解难度 | 低 | 中 |
| 调试便利度 | 适合逐条人工核对 | 适合整体观察 |
4. 第三版进阶:把“算题”变成“摘苹果”——动画与克隆
4.1 舞台布局与角色设计
前两个版本本质上是个计算器,结果对但视觉效果很差。到了进阶阶段,可以把它真正做成一个小游戏:树上挂着10个苹果,陶陶站在树旁,点击绿旗后,陶陶开始判断,摘到的苹果从树上消失或者切换成被咬了一口的造型。
舞台布局要做三件事:选一张合适的院子背景,创建一个陶陶角色,再创建一个苹果角色。苹果不需要复制出10个角色,直接用克隆体生成就行。舞台上只需要放一个“苹果”作为原型,运行时通过Scratch的“克隆自己”积木产生10个副本,这样既简洁又方便统一管理。
4.2 克隆体编号与坐标映射
这个版本里,列表依然保存每个苹果的高度数据,但每个克隆体要代表一个特定编号的苹果。关键点在于:克隆体必须知道自己是第几个苹果。
做法是:给苹果角色创建一个“苹果编号”变量,然后在生成克隆体的循环里,先把“苹果编号”设为当前的循环次数,再执行“克隆自己”。每个克隆体启动后,读取自己的“苹果编号”,就可以根据编号去列表里拿到对应的高度数据。
真正让动画生动起来的,是坐标映射。Scratch舞台的y坐标范围大约是-180到180,苹果离地高度则是100到200左右的数值,不能直接用。我通常会先设定一个“地面y坐标”,比如-150,然后用“地面y坐标 + (苹果高度 - 100)”来换算苹果的显示位置。这样,高度越大的苹果就显示在越高的位置,视觉上看起来和题目描述完全一致。
判断摘取逻辑可以放在陶陶角色上:陶陶根据列表数据依次判断,凡是满足“苹果高度 <= 可摘高度”的编号,就向对应编号的苹果克隆体广播一个“摘取”消息。苹果克隆体收到消息后,判断自己的“苹果编号”是否和消息里携带的编号一致,如果一致,就播放音效并切换造型或隐藏。这种“广播-接收”的写法是Scratch动画开发里非常经典的模式,学会了以后做其他作品也都能用上。
4.3 反馈设计:造型切换、音效与亮度检测
有些老师喜欢在这个版本加入更丰富的反馈,比如让摘下来的苹果变暗、显示得分飘字,或者加一段陶陶移动的动画。
这里有一个非常容易踩的坑:如果克隆体收到消息后同时执行“隐藏”和“停止其他脚本”,会导致下一次点击绿旗时克隆体无法正常显示。正确做法是,克隆体启动时先执行“显示”,摘取后才“隐藏”。而且每次点击绿旗都要先执行“删除此克隆体”相关的清理逻辑,或者重新生成一批克隆体时先让旧的消失干净,避免新旧苹果叠加。
如果想让交互更有意思,还能用Scratch的“亮度”检测积木做入场动作。比如,玩家用手电筒或环境光改变舞台亮度,程序检测到亮度变化后,才让陶陶开始摘苹果。这个玩法适合课程展示和创意编程活动,但在等级考试中不推荐,因为判分环境通常不提供额外外设,而且亮度传感器的稳定性受环境影响较大,容易让程序行为变得不可预期。
5. 学员最容易踩的坑与完整排查思路
5.1 列表索引从1开始带来的混乱
Scratch的列表项从1开始编号,这一点和Python等文本编程语言从0开始完全不同。学员写循环时,如果循环次数设置成10,但起点用了0,或者结束条件多算了一次,最后就会访问到第11项,而第11项根本不存在,程序会报错或者给出错误结果。
排查这类问题,最快的方法是在循环体内临时加一个“说 列表的第(序号)项”积木,运行一遍看看序号是从1递增到10,还是跳到了11。如果发现序号跑出了范围,就检查循环变量的初始值和结束条件。这个“把过程可视化”的排错思路,可以套用到几乎所有Scratch程序里。
5.2 计数器与列表的清零问题
这是最隐蔽的错误之一。“摘到数量”变量如果只在角色刚创建时设为0,而列表数据没有清理,第二次运行程序时计数会从上一次的结果继续累加,导致结果翻倍。
我曾经让学员连续点三次绿旗,每次输入相同数据,结果第一次说7,第二次说14,第三次说21。学员自己也觉得很奇怪,明明什么都没改。问题就出在“摘到数量”没有在绿旗点击后清零。完整的初始化应该是三个动作:摘到数量设为0,序号设为1,列表如果使用了“询问加入”的方式录入,那还要在开始录入前先把列表清空。很多学员只记得清“摘到数量”,忘了清列表,于是列表越积越长,判断也会出错。
5.3 阻塞式询问与输入格式问题
Scratch的“询问并等待”是阻塞积木,意思是程序运行到这里会停下来,一直等用户输入并点击对勾才继续。如果程序里连续出现多个“询问并等待”,用户必须一个一个回答完,程序才能继续往下走。这本身不是问题,但初学者容易因此误以为“回答”是全局的、不会被覆盖的,实际上每次新的询问都会把上一次的回答冲掉。
输入格式是另一个坑。如果用户在输入框里输入了文字,那么在后续数字比较时,Scratch往往会把它当成0处理,或者直接比较失败。所以当“回答”要参与数字运算或比较时,最好先确认输入内容是数字。等级考试中我通常建议直接使用列表预置数据,只有在演示交互功能时才使用询问,这样能把输入格式问题完全挡在门外。
5.4 一个典型的错误排查全流程
我带学员时经常展示这样一个场景:程序跑完说“可以摘到12个苹果”,但手工计算明明只有7个。这时候我会带着学员走一遍完整的排查流程。
第一步,检查列表项数量。在程序里临时加一句“说 列表的项目数”,如果显示20,说明列表没有清空,上一次运行的数据混了进来。
第二步,检查循环起点。让程序说出“序号”的初始值,如果是0,那么第一次判断访问的是第0项,Scratch会把它当作空值处理,计数就会少算或者多算。
第三步,检查判断条件。把“可摘高度”的输出显示出来,看它是不是等于180。如果加法表达式拼接得不对,比如把“150 + 30”写成了字符串“15030”,结果就会完全错乱。
第四步,检查累加时机。看看“摘到数量增加1”是不是被放进了错误的“如果”分支里。有时候学员把增加1的积木放在了判断外面,于是不管能不能摘到,每个苹果都让计数器加1。
这套流程做完,95%的问题都能暴露出来。我建议所有学员都记住这个排查顺序:数据、循环、判断、累加。按照这个顺序走,比东改一下西改一下要高效得多。
6. 当题目变形时:从Scratch到Python的迁移与考试应对
6.1 Python等价实现
陶陶摘苹果的价值不止于Scratch。学员进入Python阶段之后,我会经常让他们把这套逻辑翻译成文本代码。拿Python来写,逻辑几乎是Scratch列表版的一比一映射:
apple_heights = [100, 200, 150, 140, 129, 134, 167, 198, 200, 111] bench_height = 30 body_height = 150 reach = body_height + bench_height count = 0 for h in apple_heights: if h <= reach: count += 1 print(count)这里的for循环、if判断、计数器累加,和Scratch里的“重复执行”“如果那么”“将变量增加1”一一对应。我经常拿这道题作为图形化编程到文本编程的“桥梁题”,因为学员在Scratch里已经理解了逻辑,翻译成Python只是换个语法外壳,接受度特别高。
6.2 输入进阶:空格分隔的数据
如果题目要求输入10个苹果高度,并且数据之间用空格隔开,Python里可以用split方法把字符串拆成列表,这也是等级考试Python方向常见的输入处理方式:
data = input().split() apple_heights = [int(x) for x in data]这段代码先把一行输入按空格拆成若干字符串,再逐个转成整数,存进列表。对应的Scratch理解则是:用户一次性输入一串文本,程序通过“分割字符串”积木把它变成列表项。理解了数据存储在列表里这件事,后面学各种文本编程语言的输入处理都会顺畅很多。
6.3 等级考试里的变体与应对策略
这类题目在青少年等级考试图形化编程一级、二级中很常见,我总结过三种主要变体。
第一种,修改比较条件。把“陶陶摘苹果”改成“小明够书架”,把身高、板凳高度换成书架层高,逻辑完全一样,只是换了个场景。应对策略是把题目里的实际意义剥离掉,提炼出“上限值”和“被比较值”两个抽象概念。只要找到这两个概念,不管题面怎么换场景,代码框架都不用变。
第二种,把固定数据改成运行时输入。题目要求用询问让用户依次输入10个苹果高度,和板凳高度一起参与计算。这时建议用列表存储输入的数据,避免每一次判断都临时询问,导致代码结构混乱。这里也正好考察学员对“阻塞式询问”的理解,以及“回答”变量会被覆盖的意识。
第三种,增加统计维度。比如不仅要统计能摘的总数,还要找出能摘的苹果里最大高度是多少。这时只需在判断成立的内部,再加一个嵌套判断:“如果当前高度 > 已记录的最大值,那么 将最大值设为当前高度”。这个操作能很好地把“分支嵌套”的用法带出来,是进阶的好题目。
6.4 继续扩展:从这道题延伸到排序和九九乘法表
学员一旦掌握了“列表+循环+判断”这个铁三角组合,很多经典题目都可以开始做了。九九乘法表就是双重循环嵌套的入门案例,冒泡排序则是列表操作的高级应用。陶陶摘苹果是这一切的开端,因为它用最少的变量、最简单的条件,完成了最核心的编程结构训练。
我对这道题还有一个特别的执念:它天然带有生活场景,能让学员直观地感受到编程不是在“做数学题”,而是在解决“陶陶到底能不能摘到苹果”的真实问题。这种把抽象逻辑和具体场景绑定在一起的学习方式,比单独讲一百遍“什么是循环”都有效。教学时,我会让学员轮流当“陶陶”,自己报出一个身高和板凳高度,然后让其他同学用程序帮他算能摘到几个苹果。课堂活跃度一下就上来了,而且大家对条件的理解也更深。
在Scratch教学这条路上,陶陶摘苹果这道题我至少带几十个学员做过。每个阶段的孩子都会给出不一样的解法:有人用顺序结构硬算,有人第一时间想到列表,有人在动画版里折腾克隆体玩得不亦乐乎。我从来不会说哪种解法是唯一正确答案,但我一定会要求每个学员解释清楚自己的每一个判断条件为什么这样写。能把条件说清楚,这道题才算真正吃透了。
最后分享一个教学小技巧:如果学员的列表版程序总在累加时出错,可以让他用纸笔把循环执行三次的过程完整写下来。不写代码,只写“第1次取到几号苹果、值是多少、是否满足条件、当前总数是多少”。这个看起来原始到不行的“人肉模拟”过程,往往比反复改代码更能帮他建立对循环和变量变化的理解。等他能在纸上推演正确,再回到Scratch里修改积木,问题往往会自己消失。