ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CS50 2024 Week 0重刷:Scratch中藏着的编程思维与Pset0避坑指南

CS50 2024 Week 0重刷:Scratch中藏着的编程思维与Pset0避坑指南 我又把CS50的2024版整个过了一遍这次重刷我特别留心了Week 0的Scratch部分。老实说第一次看这门课我还是个纯新人当时觉得用积木拖来拖去挺小儿科也没太当回事。但这次带着几年写代码的经验回头看才发现CS50拿Scratch开场根本不是照顾新手这么简单——它其实是在用一个极其聪明的方式先把编程里最抽象、最容易劝退的那部分思维提前打包教给你。这篇笔记我就好好聊聊Scratch这周我到底悟到了什么也把我在做Pset0就是Week 0的编程作业时踩过的几个坑一并写出来给正在跟课的朋友当个参考。这篇文章适合谁一种是正在啃CS50 2024、还没开始写C语言代码的朋友你看这篇能把积木背后的逻辑先理顺后面进C语言会舒服很多。另一种是自己早就学过编程、但没认真看过Scratch的人我建议你带着这家伙在抽象什么的心态来读会有收获。1. 为什么CS50拿Scratch开场它逼你先想清楚三件事很多人不理解一门大学计算机系的硬核入门课凭什么第一周不直接上C语言而是让一群大学生拖积木我这次重刷才意识到David Malan那节课的野心非常大——他要在你还没见过任何真正的编程语言之前就把程序到底是什么形状的这个问题焊进你的脑子里。1.1 先建立程序的形状再学语法细节我们成年人学编程最容易犯的一个错误就是一头扎进语法细节里出不来。今天学int main(void)明天学printf的格式控制符学了一个月你脑子里全是碎片唯独没有一个程序完整跑起来是什么感觉的整体图景。Scratch解决的就是这个问题。它把所有语法都藏起来了剩下的积木块就是程序结构本身。你在Scratch里搭一个点击绿旗让小猫咪走十步然后说Hello你看到的是一个从上到下的积木串。这个从上到下的顺序感就是程序最底层的顺序执行结构。你先有了这个形状再去看C语言里那些花括号和分号它们不过是在用另一种记录方式描述同一个形状而已。所以我特别同意CS50这个设计先让你用手摸到程序的骨架再教你往骨架上填肉。顺序反了就是光背语法不练思维越学越迷糊。1.2 Scratch刚好把语法糖全部剥掉了你去看任何一种真实语言的代码里面都混杂着三种东西逻辑、语法、还有语言特有的坑。对新手来说语法和坑往往比逻辑更扎眼。比如C语言里每个语句结束要打分号少打一个就编译报错。这个报错跟你的思路正不正确完全没关系但它就是会打断你。Scratch完全不存在这个问题。积木是卡扣式的卡不上就是卡不上你根本不可能拖出一块语法错误的积木。这就等于把写错代码这件事从学习路径里暂时删掉了。你唯一可能出错的就是你的逻辑本身。这一招太狠了它逼着你直面一个真相编程里真正的难点从来不是语法而是你想让程序怎么走这件事。等你想清楚了再去学语法你会发现语法根本不是障碍就是一套死记硬背的符号规则。1.3 我在Lectur 0里看到的一个精妙设计从Hello World到条件循环都有积木对应大家如果回头去翻Lecture 0的演示David Malan在台上用Scratch现场做了个小游戏里面用到了一大堆积木事件积木当绿旗被点击、运动积木移动十步、外观积木说Hello、控制积木重复执行/如果那么、侦测积木碰到边缘还有变量、音乐等等。他不是随手用的这些积木几乎精确对应了CS50后续课程里所有的核心概念。事件对应C语言的入口函数运动对应函数调用重复执行对应循环如果那么对应分支变量对应数据存储侦测对应输入和条件判断。也就是说你第一周在Scratch里玩到的每一个积木在后面十周里都会以代码的形式再见面。我当时没意识到这件事重刷的时候真的会被这个课程设计震撼到这哪是玩积木这分明是在用乐高把整门课的地图先给你拼了一遍。2. 五类积木背后的编程原语我重新做的分类笔记既然说到了积木我就把Scratch积木按编程原语重新分类了一遍。网上很多教程是按积木颜色教的什么运动类、外观类、声音类这样学当然也行但从编程思维的角度看我更推荐按下面的分法去理解。2.1 事件与顺序程序不是读出来的是触发出来的Scratch里所有程序都靠事件启动。最常见的当绿旗被点击还有一个当角色被点击以及当接到广播等等。这个设计其实非常贴近真实的软件系统。你手机上的App不是一开机就从头跑到尾的而是随时准备响应你的触摸、消息推送、网络请求等各种事件。这一点恰恰是很多编程新手在Scratch阶段没想通的事。他们以为程序就像写作文一样从第一句念到最后一句就完了。实际上程序更像是一直待命的状态平时什么都不干一旦某个事件发生就去执行对应的积木块。如果你在Scratch阶段理解了这个事件驱动的思维后面学C语言里的main函数和回调函数甚至学前端开发里的按钮点击处理都会比别人快半拍。至于顺序执行说白了一个积木块接着一个积木块往下跑这没啥好讲的。真正要命的顺序问题是后面那个广播陷阱我放在第4章详细讲。2.2 循环与条件控制流的两种原始冲动我习惯把循环和条件放在一起想因为它们的本质都是让程序做出选择和重复。Scratch里循环有三种重复执行固定次数、重复执行直到条件成立、无限重复。条件则是如果那么和如果那么否则。你别看就这么几个积木它们组合起来能解决绝大多数编程问题。我在做Pset0的时候就反复用这两种积木让角色反复执行某个动作直到碰到边缘碰到边缘就反弹这就是循环条件的经典组合。说白了编程里所谓复杂逻辑九成都是循环套循环、条件套条件的堆叠Scratch帮你把这两种基本形状练熟了后面写什么都能顺藤摸瓜。2.3 变量、广播、自定义积木数据与抽象在Scratch里的模样变量大概是Scratch里最被低估的积木。因为它长得不起眼很多新手干脆不用遇到问题就硬写一堆重复积木。但CS50的作业里有一个要求就是必须用变量逼着你养成存数据、改数据、用数据的习惯。我自己的体会是变量这个概念在Scratch里学代价是最低的因为你可以用滑杆实时看到变量怎么变这个可视化反馈放到真实语言里根本没有。广播积木就更有意思了。它解决的是不同角色之间怎么通信的问题。一个精灵广播一个消息其他精灵可以各自回应。这个机制对应的其实是编程里特别重要的解耦思想发送方不需要知道接收方是谁、有几个只需要把消息丢出去。我后面学到网络编程里的消息队列、发布订阅模式时脑子里对应的原型就是Scratch的广播。自定义积木则是函数的雏形。Scratch里可以把一段积木打包成一个新的积木以后反复调用。这就是最原始的模块化和代码复用。我强烈建议做Pset0的时候刻意用一下自定义积木哪怕只打包一段很短的逻辑你也会深刻理解为什么函数是程序员的左膀右臂。3. 从Scratch到C的思维桥做完项目后我突然看懂了Lecture 1我当时上CS50时的节奏是周五晚上看完Lecture 0周六做Pset0周日熬夜看Lecture 1。过程里有个特别奇妙的体验——做完Scratch项目再去听C语言整个人是有接住的感觉的。那些积木块像是自动在脑子里翻译成了C代码。3.1 积木到C语句的翻译对照表我把这个过程整理成了一张对照表写在这里对后面学C语言特别有参考价值Scratch积木对应的C语言概念当绿旗被点击int main(void)程序入口移动10步函数调用执行某个操作说Hello调用输出函数如printf重复执行10次for循环重复执行直到...while循环如果...那么...否则if / else 分支变量声明变量并赋值广播消息消息传递 / 事件通知自定义积木函数定义与调用碰到边缘侦测条件判断的实时求值这张表不是严格一一对应但你带着这张表去听Lecture 1C语言那些概念就全都有着落了。你不会觉得while是个从天而降的新东西你会觉得它就是你把重复执行直到这个积木换了一种写法而已。3.2 坐标系、随机数与触摸编程本质的暗线Scratch里有一个将x坐标增加10的积木。你拖一下积木精灵就横着飞出去了。表面上看这只是让精灵动起来但如果你多问一句x坐标是什么你其实已经开始接触计算机里最基本的数据表示——坐标就是一串数字屏幕上的位置不过是数字的可视化。还有移到随机位置这个积木。我第一次用的时候只觉得好玩第二次重刷才意识到这就是随机数生成的高层封装。后面写C语言时你发现生成随机数要先srand、再rand、还要处理范围那一堆细节很容易劝退新人。但你在Scratch里早就理解了随机位置的几何意义再看C代码里那堆数字运算你看到的是实现细节而不是思想障碍。David Malan在课上有句话大意是编程不是关于代码的是关于问题解决的。Scratch这段学习就是这句话的最佳注脚——它让你先看到问题和解决思路把代码的皮扒掉等你有底气了再把皮穿上。4. 完成Pset0时我踩过的四个认知陷阱作业要求是做一个你自己的Scratch项目条件包括至少有两个精灵使用至少一个循环使用一个条件判断使用一个变量等等。我在做的时候磕磕绊绊踩了好几个坑这里逐个说出来每一个都是真实教训希望你别再陪我走一遍。4.1 陷阱一以为绿旗只触发一次其实每个精灵都要自己接事件我一开始做项目脑子里的模型是点一下绿旗整个项目开跑所有精灵依次行动。结果我把所有逻辑全堆在一个精灵身上另一个精灵完全不动。调试了半天才发现Scratch里当绿旗被点击这个积木必须分别放在每个精灵身上。也就是说绿旗只是发了一个全场广播每个精灵都要自己写上收到绿旗后干什么。这个坑的本质是事件驱动模型的局部性每个角色只对自己的脚本负责没有全局一次跑完这回事。想通这一点之后我重构了整个项目把每个精灵的行为拆成独立的脚本段用广播去协调它们。这也让我后来写前端代码时不犯把所有状态都集中在一处管的毛病。4.2 陷阱二广播不等接收方处理完程序就继续往下跑这个坑比第一个更隐蔽。我让精灵A广播一个消息给精灵B然后在A的脚本里紧接着就让A做后续动作。我的假设是B处理完A才开始下一个动作。但Scratch的广播机制是异步的——A把消息扔出去广播后面的积木立刻执行根本不会等B跑完。后来我在教材上看到解决办法如果一定要让A等B完成就要用广播并等待这个积木。这说明什么说明Scratch在底层已经告诉你程序世界里有同步和异步两种协作方式。这是个特别抽象的概念很多人在学网络编程时才遇到会因为搞不懂线程和异步而被折磨很久。但Scratch把它做成了一个可视化的选择题要等就选广播并等待不等就选广播。你亲手试过两者的差别以后再学回调、异步IO这些概念至少不会觉得它们是完全陌生的外星语。4.3 陷阱三变量漏初始化叠加出了天文数字Pset0要求用变量记分所以我设了一个分数变量。我的第一个版本却没在绿旗事件开头把分数重置为0结果每次点击绿旗重玩分数都从上一次结束的值继续加。玩几局之后分数变成了几百上千看起来非常滑稽。这个问题的根子是变量在使用前必须初始化。在编程里这是最经典、最基础的注意事项但很多初学C语言的人会在声明指针时犯同款错误——声明了不赋值就用程序直接崩溃。我在Scratch里用一次漏初始化比看十遍教科书记得都牢。所以做作业的时候一定记得把初始化当成一个独立步骤写进设计里。4.4 陷阱四坐标写错角色跑出屏幕就找不回来了我还干过一件蠢事设置精灵移动时用了很大的坐标值比如x设置为500但Scratch舞台的x范围只有-240到240。精灵直接飞出了视野我一度以为它丢了甚至重新做了一遍。后来才想起来把坐标拉回范围内就能找回来。这个问题背后其实就是数据范围的概念。真实程序里变量越界、数组越界、整数溢出统统都是同一类问题。Scratch用坐标范围友好的方式让你在游戏环境里先感受一次越界你要是能借机问一句为什么超过240就不见了那这颗知识的种子就算种下了。5. 走出课程再看Scratch那些热搜问题背后其实都是同一件事写完Pset0之后我本来以为这辈子不会再碰Scratch了。结果最近因为帮朋友的孩子看少儿编程逛了一圈国内社区发现大量关于Scratch的搜索问题特别有意思。我随手看了几个发现这些问题表面上是操作求助本质上全是编程思维问题。5.1 为什么scratch亮度能难倒一堆人有段时间scratch亮度这个词上过热榜。你可能觉得奇怪调亮度不就是拖个滑杆吗实际上很多人卡住的原因是找不到亮度积木、或者调了亮度但颜色没变化。我在细看后才发现Scratch里的亮度效果只对部分角色的某些颜色模式有效而且必须配合将颜色特效设定为这类外观积木使用。这个问题的本质是对属性与效果关系的理解。角色不是一整块贴图它有颜色、亮度、虚像、像素化等多个特效属性亮度只是其中一种。你在Scratch里玩过这个以后接触CSS里的opacity、filter、blur属性时就会知道特效是分层叠加的不是改一个数值就整个大变样。5.2 保留两位小数其实是个抽象思维练习题scratch怎么保留两位小数也是一个高频问题。Scratch里没有直接的四舍五入到两位小数积木但你可以用将数字乘以100四舍五入再除以100的方式实现。这本质上就是小学就学过的换单位思维把小数问题变成整数问题处理完再换回来。这个问题换算到编程里就是数据格式化与精度控制的雏形。以后你在C语言里用printf(%.2f, num)在Python里用round()你会发现它们背后都是同一件思维把一个大问题转换成可控的小问题处理完再还原。你在Scratch阶段能自己琢磨出乘以100再除以100这个方案绝对比考试时背十道题都有用。5.3 用Scratch做植物大战僵尸类项目真正要练的是任务拆解另一个搜索热门是scratch 植物大战僵尸代码评论区几乎都是求源码的。我自己没做这个项目但给朋友的小孩辅导时围观过完整过程。这类热门项目最大的难点不是某个积木不会用而是任务拆解你要先想清楚僵尸怎么移动、植物怎么发射子弹、子弹和僵尸怎么碰撞、碰撞之后谁消失、分数怎么加、输赢怎么判断。如果你愿意自己动手做一个植物大战僵尸极简版哪怕只用最基本的移动、克隆、侦测、变量你等于做了一次完整的软件工程训练。比直接抄源码有意义得多。你要问我怎么做我建议按这个顺序拆第一步让僵尸从左往右走第二步让植物每过几秒发射子弹第三步让子弹碰到僵尸后两个都消失第四步用变量记分数第五步加上僵尸走到终点就失败的判断。一步一测跑通一个再进入下一个。5.4 自定义积木、变量与条件判断普通案例里最容易被低估的组合最后回到热搜里的scratch 变量 条件判断scratch 自定义积木。这两个关键词放在一起其实就构成了写稍微复杂程序的黄金三角变量存状态条件判断状态自定义积木复用逻辑。我在Pset0里没用自定义积木但也后悔过。帮我辅导的小孩做小游戏时我把他的项目里重复出现的三段积木抽成一个自定义积木他后来改需求时只改了一处就全生效了那个原来还能这样的表情比讲任何理论都有说服力。所以我建议大家在Scratch阶段不要只满足于跑通。凡是遇到同一段逻辑出现两遍以上就应该考虑抽成自定义积木凡是需要记录和改变状态就勇敢地引入变量凡是需要根据状态做出不同行为就是条件判断的用武之地。把这三个组合练熟再往任何编程语言迁移都属于降维打击。写到这里这份关于Scratch部分的笔记差不多就整理完了。我重刷CS50这轮最大的体会是很多人太小看Week 0了。别急着跳过Scratch去写C代码先花一周把积木玩透、玩出自己的想法后面十周你会感谢这一周的。最后再分享一个小习惯我做每个Scratch项目之前都会先在纸上画出这个角色在什么事件发生时会做什么反应的因果图画完再拖积木。这套做法让我后来写任何语言的项目都保持先梳理事件流、再动代码的习惯效率高不少。
返回列表