ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Mixly图形化编程:while与do...while循环结构和应用详解

Mixly图形化编程:while与do...while循环结构和应用详解 Mixly图形化系列教程写到第七篇了。前面六篇把数字输入输出、模拟量读取、串口通信、分支判断和for循环挨个过了一遍到这个节点还在继续看的朋友基本都是真的在拿Mixly做项目的人了。这篇接着循环往下走目标很明确把while和do...while这两个循环结构一次性讲透。用关键词“while”去搜网上大多是被各种报错刷屏但在图形化编程里while不报错它只负责一件事——让程序在某个条件还没满足的时候老老实实待在一个地方干活。这篇适合三类人带学生上创客课程的老师、自学没入门多久的中小学生以及学完for循环想把它和C语言对应起来的零基础爱好者。看完你不但知道这两个积木在哪还能直接用它们做出按键控制、掷骰子这类小项目并且彻底搞清楚它俩到底差在哪。1. 先搞清楚三种循环到底在解决什么问题1.1 for、while、do...while其实是三种“循环姿势”很多初学者一开始接触for循环觉得“循环就是规定次数跑完拉倒”。这个印象不能说错但容易把思路框死。等做到实际项目就会发现很多时候程序根本不知道要循环几次只知道“什么时候该停”。这时候for循环就不太顺手了。我上课时喜欢用生活场景做类比for循环像“套餐”——说好吃几个菜就做几个菜次数是提前定死的。while循环像“自动售货机找零”——机器一直往外退硬币退到余额为0才停谁也不知道一开始要退几次。do...while循环像“先尝后买”——你先吃一颗葡萄甜就继续买不甜就不买了但无论怎样第一颗葡萄总归是吃过了。这个“先吃一颗”的细节恰恰是do...while和while最核心的区别do...while不管条件成不成立循环体里的代码至少先跑一次。for循环适合次数明确的场景比如让LED闪烁10次while适合条件驱动的场景比如等待按钮松开do...while适合“不管三七二十一先做一次再说”的场景比如先掷一次骰子再决定要不要继续掷。把它们放到一块对比逻辑一下就清晰了循环类型判断时机最少执行次数典型适用场景for先判断次数由循环变量控制0次闪烁N次、遍历一组引脚while先判断条件满足才进入0次等待按键松开、等待传感器越限do...while后判断先执行一次循环体1次先采样再判断、先出结果再问是否继续1.2 为什么学完for循环还要再学while有朋友留言问既然for循环什么都能干为什么Mixly里还要单独给while和do...while留两个积木这个问题问得很到位。for循环看起来万能是因为“循环次数”这个信息在写程序时就得确定下来。但Arduino这类硬件项目里真正的大头是“感知外部世界”一个按键何时被按下、一个传感器数值何时超过阈值、串口何时收到数据。这些事件发生的时间点完全不可预知程序只能一遍遍去查、去等等到条件变化了再行动。这种情况用for循环硬写也能写但代码会非常别扭你得先估算一个最大次数然后在循环体里不停判断条件是否满足写出来的东西又长又绕。while循环天生就是干这个的它把“继续循环的条件”直接摆在明面上程序读起来跟自然语言差不多。另一个原因是衔接未来。Mixly是图形化编程但它的最终目的不是让学生停留在拖积木而是理解程序逻辑为将来写代码做准备。Arduino的C语言里while和do...while是绕不开的语法。在Mixly里先把这两个结构玩熟以后看到大段的C代码就不会发怵。这也是我一直推荐学生用Mixly右上角“代码”按钮的原因——每拖一个积木就切到代码区看一眼图形和代码一一对应这个习惯越早养成越好。2. 在Mixly里找到while和do...while积木2.1 积木在哪、怎么认Mixly的积木分类和Scratch类似循环相关的都在“控制”分类里。打开控制分类往下拉会看到几个长相接近的循环积木有“循环次数”这就是for、有“重复无限次”还有一个条件写在最前面的“当...执行”这就是while循环。while积木的样子很直观顶上一个六边形凹槽用来填判断条件中间一个可以塞其他积木的凹槽是循环体整体看就是“当条件成立的时候反复执行下面的积木”。学生第一次看到这个积木我一般会让他们大声读一遍“当……执行……”——读顺了逻辑也就懂了一半。do...while在Mixly里的积木长这样一段循环体凹槽底部跟着一个六边形条件判断区积木上的文字通常是“执行...直到...”这样的结构。注意观察它的条件判断槽在积木底部而不是顶部这个外观差异恰恰对应了“先执行后判断”的执行顺序。上课的时候我让学生看积木就判断循环顺序他们记得特别牢因为图形把语义画在脸上了。另外控制分类里还有一个“重复无限次”积木它本质上就是while(1)或者while(true)一个永远满足条件的while循环。初学者有时候会把“重复无限次”和“当...执行”搞混其实区别很简单一个是条件永远成立一个是可以变动的条件判断。2.2 展开看代码图形化积木对应的C语言到底长什么样Mixly最终会生成Arduino C代码。切换到“Arduino C”模式while积木生成的核心代码是这样的while (条件) { // 循环体代码 }do...while积木生成的代码是这样的do { // 循环体代码 } while (条件);肉眼可见的区别有两个。第一是条件和循环体的先后顺序第二是do...while在C语言里必须以分号结尾很多人手写代码时容易漏掉这个分号编译直接报错。在Mixly里拖积木不会遇到这种低级错误但看代码时心里要有数。还有一点值得注意Arduino本身的setup()和loop()结构就是一个大循环。loop()函数里的代码会被反复执行它本质上就是一个永不结束的while循环。理解了这一点就能明白为什么很多Mixly例程看起来没有“明显”的循环程序却能一直跑——因为整个loop()就是最大的那个while。这个认知对后面学状态机、学定时器都特别重要。3. 三个能直接抄作业的实操案例3.1 按住按键灯闪松开就停while的入门体验第一个案例我用的是一个按键加一个LED接线非常简单按键模块接数字7脚LED接13脚或者直接用板载LED。要做的事情是按住按键不放LED就一直以0.2秒间隔闪烁一松手LED立刻停止程序继续往下走。Mixly里的积木拼法是这样的先拖一个“当...执行”积木条件填“数字输入 引脚7 高电平”然后在循环体里依次放入“数字输出 13 高电平”“延时200毫秒”“数字输出 13 低电平”“延时200毫秒”。这段程序生成出来的C代码大概是while (digitalRead(7) HIGH) { digitalWrite(13, HIGH); delay(200); digitalWrite(13, LOW); delay(200); }这个案例几乎没有难度但它把while的核心语义讲透了按键按下时条件成立程序被“困”在循环体里反复闪灯按键松开那一瞬间条件变成假程序立刻脱离循环继续往后执行。我建议学生把这段程序后面再加一行“串口打印换行按钮松开”然后打开串口监视器观察松手后才会看到这行字。这个观察过程比任何解释都管用。实操中有一个坑必须提醒按键模块分为“按下输出高”和“按下输出低”两种有的学生把条件写反了结果变成“按住不闪、松开才闪”。遇到这种情况先别急着改程序用串口打印一下按键的实时电平确认它按下时到底是高还是低再回来改条件。这也是嵌入式开发的基本素养——先确认硬件状态再怀疑代码逻辑。3.2 按键按一次、状态翻一次while的阻塞等待妙用第二个案例是第一个的升级版也是实际项目里非常高频的需求按一下按键LED亮再按一下LED灭。看起来简单直接写“如果按键按下就把LED取反”行不行我一向鼓励学生先自己试试完十有八九会发现问题按键按一次灯经常“跳”好几下状态完全不受控。原因很好理解。程序每秒能循环成千上万次而人手按一次按键的时间是几百毫秒。在这几百毫秒里条件“按键按下”一直为真if语句里的取反操作被执行了成千上万次LED亮灭来回翻转最后停在哪个状态基本靠运气。这就是典型的“按键抖动/重复触发”问题。解决办法正是while循环的拿手好戏检测到按键按下后先执行一次LED取反然后让程序卡在一个while循环里死等按键松开。程序逻辑变成if (digitalRead(7) HIGH) { digitalWrite(13, !digitalRead(13)); while (digitalRead(7) HIGH) { delay(10); } }对应到Mixly积木最外层是“如果”积木条件判断按键按下如果块里第一件事是设置13号引脚输出为“取反”Mixly的交互式引脚选择可以直接反选第二件事就是拖一个“当...执行”积木条件还是按键按下循环体里只放一个10毫秒延时。这段程序翻译成人话就是按键一旦按下我先把灯翻个面然后待在这个循环里不动直到你把手指松开我才继续干别的。很多学生不理解为什么循环体里只有一个“延时10毫秒”就能“等待松开”。这里的关键是只要按键没松开条件一直为真while就一直在空转每转一圈等10毫秒等到松开了条件变假循环自然退出。这个“空转等待”的用法就是嵌入式里常说的“阻塞式等待”它牺牲了一点效率但换来了逻辑上的绝对可靠。中间加延时是为了降低空转频率顺便起到按键消抖的作用一举两得。这个案例我还建议学生做一个扩展实验在while循环体里放一个计数器变量每次循环加1。等下松开按键后把计数器的值打印到串口监视器。学生会惊讶地发现一次简单的按动循环体居然转了几十甚至上百次。数值越夸张他们对“程序跑得比手快”这个事实的印象就越深刻。3.3 掷骰子直到6点do...while的必玩案例第三个案例直接上do...while因为它展示的“至少执行一次”特性是while替代不了的。项目需求模拟掷骰子在串口监视器里不断输出1到6之间的点数只要没掷出6就继续掷一旦出现6停止程序。先分析一个问题这个程序最少会掷几次答案是1次。因为程序启动之后无论怎样都要先掷一次骰子出结果之后再判断要不要继续。这种情况下用while写会很别扭你得先把变量初始化成一个不等于6的值来“骗过”第一次判断int 点数 0; while (点数 ! 6) { 点数 random(1, 7); Serial.println(点数); }这个写法能跑但那个“点数0”的初始赋值是多余的纯粹是为了绕过while先判断的特性。而do...while天然匹配这个场景先掷骰子后判断写出来干净利落int 点数; do { 点数 random(1, 7); Serial.println(点数); delay(500); } while (点数 ! 6);Mixly积木的拼法先拖一个“执行...直到”积木循环体里放“变量赋值随机整数 从1到6”、“串口打印换行变量点数”、“延时500毫秒”条件槽里填“变量点数 6”。注意积木上的文字是“直到”意思是“一直做到这个条件满足为止”所以条件要写“点数等于6”不要被绕晕。随机数积木要单独说一下。Mixly的“数学”分类里一般能找到“随机整数”积木不同版本参数范围略有差异。我用的Mixly 1.x经典版里积木显示“从1到6”但生成的C代码其实是random(1,7)因为Arduino的random(a,b)取到的是a到b-1的整数。如果学生用了不同版本的Mixly参数范围显示可能会不一样所以我都会提醒一句拖完积木务必切到代码区看一眼生成结果确认随机数落点对不对顺便加深对“左闭右开”区间这个概念的理解以后写代码能少踩一个坑。这个案例视觉效果很欢乐串口监视器里数字不停翻滚直到蹦出一个6才停。我还会让学生加一个计数器记录一共掷了多少次才出6顺便再讨论一个数学问题掷很多次才出6的概率有多高编程课顺便上了数学课学生们反而记得更牢。4. 常见问题与排查技巧实录4.1 程序一上传就“死机”多半是while没有出口学生在课堂上遇到最多的情况是程序上传之后板子完全没反应按按键没动静串口监视器一片空白仿佛板子“死机”了。排查来排查去最后九成都是同一个原因while循环的条件永远为真循环体里又没有改变条件的操作程序卡死在死循环里出不来了。经典的错误写法比如循环条件写“1 0”这个条件任何时候都为真循环体里只放延时没有任何变量变化。代码层面等价于while (1 0) { delay(100); }程序一辈子停在这里后面写的所有代码都成了摆设。还有一种更隐蔽的情况循环条件依赖某个变量但循环体里忘了更新这个变量。比如想用while让变量从10减到0条件写“变量 0”循环体里却不写“变量减1”结果变量永远是10条件永远成立照样死循环。在Mixly里碰到这种情况我会让学生先在循环体最前面拖一个“串口打印换行”打印循环计数器然后打开串口监视器观察能看到数字一直刷、停不下来就说明循环没有出口。这个“打印中间变量”的排查思路是调试程序最基础也最有效的手段。另外Mixly控制分类里有个“跳出循环”积木对应C语言的break。它可以在循环体里加一个判断条件满足时就强制跳出循环。我建议初学者在做while练习时先放一个“跳出循环”保底比如计数器超过1000就强制退出防止程序长时间卡死。等逻辑确认无误了再把这个保险撤掉。这不是什么高深技巧但能让你在调试阶段少拔好几次USB线。4.2 循环次数莫名其妙多了一次先画流程图while和do...while的另一个常见现象是“循环次数比预期的多一次”。比如条件写“当i小于5执行”程序退出循环时i已经变成5了如果是do...while先执行再判断“直到i不小于5”有可能循环体已经执行了6次。这个差异不是写错了而是两种结构的天然区别。学生容易在这个地方绕晕我一般让他们拿出纸笔把循环画成流程图。while的流程是先到菱形判断框看一眼条件不过就绕过去do...while的流程是先冲进方框执行一遍再回来到菱形判断框。流程图画完多出来的那一次在哪一步增加的一目了然。还有一种边界条件导致的多跑一次判断条件用了大于号还是大于等于号结果完全不同。比如要做“倒计时从10到1”条件写成“i 0”会执行到i变成0退出条件写成“i 0”则会多执行一次到i变成-1才退出。图形化编程虽然不涉及复杂的语法符号但比较积木里的“大于”和“大于等于”是两个不同的积木拖的时候一定要想清楚边界。我的习惯是让学生用串口把退出循环后变量的值打印出来看到数值比预期多1或少1再去检查条件里的边界选择。4.3 常见问题速查表下面这张表是这几年带学生踩坑经验的汇总遇到类似情况可以直接对照排查症状可能原因排查方法解决思路程序上传后没任何反应while条件永真死循环循环体加串口打印看数据是否停住检查条件变量是否被更新用“跳出循环”兜底按键控制灯乱跳没有做防重复触发串口打印按键按下次数用while循环等待按键松开条件写反松开才执行按键模块高/低有效搞混串口打印引脚实时电平确认硬件逻辑后反转条件do...while比预想多执行一次先执行后判断的语义没理解画流程图逐次走一遍对比“直到”和“当”两种写法随机数出现0或者7随机数上下限理解有误切到代码区查看random参数检查积木范围和“左闭右开”区间循环里串口数据刷屏看不清循环体执行过快循环体加延时延时100到500毫秒再观察5. 带过几百个学生后我总结的循环教学心得前面说的都是具体操作方法最后聊几句教学层面的经验。我带学生认识循环比较常用的顺序是先for、再while、最后do...while。for循环最直观学生上手快但它容易让人误以为“循环就是数数”所以教for的时候一定要埋个伏笔屏幕上闪烁次数够了就停那如果我想让它一直闪到按键被按下才停该用哪个循环问题抛出去再引出while学生就有了方向感。循环这一部分我特别建议大家带着学生“故意写一次死循环”。我有个学生做按键控制LED那个案例时把while条件写成了“按键没有按下”结果灯永远不响应按键。后来我们在while循环体里加了串口打印才发现程序在他手指悬空的那几毫秒里已经跑了很多次按键按下的那一瞬间反而被跳过了。这种亲身体会比老师讲十遍道理都管用。让学生亲手制造一个bug再亲手排除它循环结构里最难理解的几个点条件判断时机、循环体执行顺序、条件变量更新就全通了。do...while这个结构说实话在日常教学里容易被一带而过但它对应的“先做一次再问”的思考模型在真实项目里很常见。我先让学生举生活里的例子回答“什么事情是你至少会做一次然后才决定要不要继续的”有学生说“先点一口菜尝好不好吃”有学生说“先试穿衣服再决定买不买”这就是对do...while最直观的理解。有了生活经验打底回来看“执行...直到”积木就不觉得抽象了。每次上完循环这一课我都会留一个综合小项目当作业比如做一个“密码门锁”从串口输入四个数字程序逐个校验错了提示重新输入对了点亮指示灯。这里面既要用到while做输入轮询也要用到do...while做“不管怎样都要先尝试一次”的交互流程。学生做完这个项目对循环的整体把握会比只会做闪烁灯高出不少。这套内容讲下来学生的逻辑思考能力提升很明显我们下篇可以接着聊循环里的break和continue或者直接进入函数看大家需求来定。
返回列表