
视频元信息
- 时长:约 1 小时(转录内容覆盖 Lecture 0 完整课堂)
- 课程:CS50x Introduction to Computer Science(哈佛大学计算机科学导论)
- 讲师:David Malan(大卫·马兰)
- 主题:第 0 讲——Scratch(计算机科学基础、二进制、算法、编程入门)
内容摘要(TL;DR)
本讲从 AI 与编程的关系切入,介绍了计算机科学的核心——问题求解(输入→算法→输出)。通过灯泡演示讲解了二进制、ASCII/Unicode 编码、颜色与图像/视频/声音的表示方式,并用电话簿查找例子引出算法效率。最后通过 Scratch 图形化编程,展示了函数、条件、循环、变量、抽象等核心编程概念,并以学生作品(Oscar Time、Ivy's Hardest Game)收尾。
1. 开场:AI 与编程的关系 [130.8s~280s]
1.1 AI 正在改变编程,但基础依然重要
- AI 对编程的影响:AI 已经并将在未来几年持续改变编程方式。现在可以用 AI 帮助解决代码中的 bug,甚至直接告诉 AI 你想添加什么功能。
- 人类曾是瓶颈:过去几十年,人类是编程的瓶颈——一天只有那么多小时,团队只有那么多人,但想解决的 bug 和想实现的功能无穷无尽。
- CS50 的真正目标:CS50 不是教你“如何编程”,编程只是副作用。真正的目标是教你如何思考——如何获取输入并产生正确的输出,掌握这些工具。
- 理解:这类似于数学中学习多种求导方法,最终掌握思想后可以借助 AI(copilot)来执行具体计算。
1.2 现场演示:用 Python + OpenAI API 写一个聊天机器人 [285s~730s]
- 在 VS Code(CS50 版本)中编写
chat.py,使用from openai import OpenAI创建客户端。 - 调用
client.responses.create,传入model="GPT-5"和input="In one sentence, what is CS50?"。 - 运行
python chat.py,程序返回 CS50 的介绍。 - 改进:使用
input()让用户输入任意问题,存入变量prompt,实现动态提问。 - 进一步改进:引入 system prompt(系统提示),例如
limit your answer to one sentence,这样用户无需每次手动强调。 - 趣味示例:将系统提示改为
pretend you're a cat,AI 的回答会带上猫的风格。 - 关键结论:用大约 10 行代码就能构建自己的 AI 聊天机器人,这体现了编程的强大能力,也说明理解底层原理的重要性。
1.3 橡皮鸭调试法(Rubber Duck Debugging)与 CS50 的 AI 工具 [750s~850s]
- 编程圈传统:在桌上放一只橡皮鸭(或任何可爱物品),当遇到 bug 时向它解释你的代码。通过把问题说出来、理清思路,常常能自己发现错误。
- CS50 提供虚拟鸭子:
cs50.ai(内置在cs50.dev中)。课程允许并且鼓励使用 CS50 自己的 AI 工具,但不允许使用 ChatGPT、Gemini 等其他 AI 软件(除非课程明确允许)。 - 虚拟鸭子的设计目标:像一位好的人类导师,知道 CS50 内容,引导你找到解决方案,而不是直接剧透答案。
易错点/规定:CS50 课程只允许使用 cs50.ai 的 AI 工具,使用其他 AI(如 ChatGPT、Gemini、Claude)是不被允许的(除非作业另行说明)。
2. 计算机科学是什么?问题求解的核心模型 [856s~915s]
- 计算机科学 = 信息的研究:如何表示信息、如何处理信息。
- 计算思维(Computational Thinking):将计算机科学的理念应用于现实世界的一般问题。
- 问题求解的抽象模型:
- 输入(Input):要解决的问题
- 输出(Output):期望的解决方案
- 黑箱(Black Box):中间的“秘密酱料”,即算法
- 理解:这个模型贯穿整个课程,所有编程都是围绕“输入→处理→输出”展开。
3. 二进制:计算机如何表示数字 [920s~1135s]
3.1 从十进制到二进制
- 计算机底层只用 0 和 1(二进制),这是它们的“字母表”。
- 十进制(Base-10):有 10 个数字(0~9),每一位代表 10 的幂(个位=10⁰,十位=10¹,百位=10²……)。例如 123 = 1×100 + 2×10 + 3×1。
- 二进制(Base-2):只有 0 和 1,每一位代表 2 的幂(个位=2⁰=1,二位=2¹=2,四位=2²=4,八位=2³=8……)。
- 用手指数数演示:只用一只手,二进制可以数到 31(因为 5 个手指,2⁵=32 种组合,包含 0)。模式比数量更重要——手指的“位置/模式”代表不同权重。
3.2 灯泡与晶体管
- 灯泡关 = 0,灯泡开 = 1。计算机内部有数百万个微小开关——晶体管(transistors),通过控制电流通断来表示 0 和 1。
- 为什么用二进制? 电要么流动要么不流动,区分“开/关”比区分 10 个电压等级简单可靠得多。
- 用多个灯泡可以表示更大的数:3 个灯泡(3 bits)可以表示 0~7;4 bits 表示 0~15。
3.3 字节与常用单位
- 位(bit):一个二进制数字(0 或 1)。
- 字节(byte):8 个 bit 组成一个字节。8 bits 可以表示 0~255,共 256 种可能。
- 常见单位:KB(千字节)、MB(兆字节)、GB(吉字节)、TB(太字节)等,都是基于字节的倍数。
- 256 这个数字很常见:因为 2⁸=256,旧电脑只能显示 256 种颜色,某些图像格式也只支持 256 色。
- 32 位与 64 位:32 bits 可以数到约 40 亿(2³²≈4 billion),若要表示负数则约 20 亿;现代电脑/手机普遍使用 64 bits(2⁶⁴)。
- 溢出问题:如果没有足够的位来存储更高的数,计数可能会意外回到 0(如 7 之后变 0)。理解:这就是现实世界中很多程序 bug 的根源之一。
易错点:二进制中每一位的权重是 2 的幂(从右往左:1, 2, 4, 8, 16, 32, 64, 128……),不是 10 的幂。计算二进制数时,只需将对应位为 1 的权重相加。
4. 字符编码:从数字到字母 [930s~1400s]
4.1 ASCII 码
- 计算机存储字母的方式:给每个字符分配一个整数编号。
- ASCII(美国信息交换标准代码):早期标准,用 7 位或 8 位表示字符。
- 大写 A = 65,B = 66,C = 67……
- 小写 a = 97,b = 98,c = 99……
- 规律:小写字母比对应大写字母大 32。例如 'a'(97) - 'A'(65) = 32。所以将大写转小写只需将二进制中 32 那一位从 0 改为 1。
- 示例:二进制
01001000 01001001 00100001= 十进制 72 73 33 = ASCII 字符 'H' 'I' '!',即 "HI!"。 - 课堂互动:8 位学生上台分别代表 128、64、32、16、8、4、2、1 位,通过举手(1)或不举手(0)拼出单词。最终拼出 "BOW"(B=66, O=79, W=87)。
4.2 Unicode 与 Emoji
- ASCII 的局限:只能表示 256 个字符,不够覆盖所有人类语言(如带重音的字符、亚洲文字等)。
- Unicode:ASCII 的超集,使用更多位(16、24、32 位等),可表示超过 40 亿个字符。
- Emoji 也是字符:它们本质上是 Unicode 编码的字符,只是显示为彩色图形字体。
- 示例:
😂(Face with Tears of Joy)的 Unicode 码点是十进制的 4,036,991,106(约 40 亿),不同的平台(Apple、Google、Telegram)对同一个码点有不同的图形渲染。 - 理解:Emoji 的跨平台差异就像不同字体显示同一个字母,底层数据相同,只是“字体”不同。
5. 颜色、图像、视频与声音的表示 [1400s~1800s]
5.1 RGB 颜色模型
- 颜色也可以用数字表示:使用 RGB(红绿蓝) 三色混合。
- 每种颜色用 1 个字节(0~255)表示强度:红、绿、蓝各 8 bits,共 24 bits(3 字节)。
- 示例:RGB(72, 73, 33) 在文本上下文中是 "HI!",但在图像上下文中是一种暗黄色。
- 黑色 = RGB(0,0,0);白色 = RGB(255,255,255)。
- 十六进制表示(如
#000000、#FFFFFF)是另一种基系统,之后课程会讲到。
5.2 图像与像素
- 图像由 像素(pixels) 组成,每个像素有独立的颜色。
- 每个像素颜色需要 3 字节(RGB),所以大图像文件自然以 MB 计。
- 同一个二进制模式,在不同软件中解释不同:在文本编辑器里是字母,在 Photoshop 里是颜色,在播放器里是视频/声音。上下文决定解释方式。
5.3 视频
- 视频 = 一系列快速播放的图像(如每秒 30 帧),利用视觉暂留产生运动错觉。
- 这就是“电影”(motion pictures)的由来——快速翻动的图片。
5.4 声音
- 声音可以用数字表示:频率(音高)、持续时间(时长)、振幅(响度) 等参数。
- 例如每个音符用三个数字表示(频率、时长、音量),接收方按约定解释就能还原音乐。
5.5 课堂问答
- 问:计算机如何区分字母 65 和数字 65? 答:取决于上下文(context)。程序员或软件决定如何解释这些 0 和 1——是显示为数字还是字母还是颜色。
- 理解:这体现了“数据”与“元数据/解释”的分离,也是编程中类型系统存在的原因之一。
6. 算法与效率:电话簿查找问题 [1800s~2200s]
6.1 问题:在电话簿中找 John Harvard
- 三种算法:
- 从第一页开始逐页查找:正确但慢(最多 1000 页)。
- 每两页一翻:快一倍,但可能跳过目标(需要回退一页检查)。
- 从中间开始,每次排除一半:每次将问题规模减半,效率最高。
6.2 算法效率的图形化
- 横轴:问题规模(页数 n),纵轴:时间(秒/翻页次数)。
- 算法 1:
y = n(线性,直线)。 - 算法 2:
y = n/2 + 1(线性,但斜率更小)。 - 算法 3:
y = log₂(n)(对数曲线,增长非常缓慢)。 - 关键结论:当问题规模翻倍(1000→2000 页),线性算法时间也翻倍,但对数算法只需多一步。
- 计算机科学/良好设计 = 不仅要正确,还要高效,要考虑时间、CPU、内存、成本等资源约束。
考点:算法效率的比较——线性 O(n) vs 对数 O(log n)。二分查找(每次减半)是对数时间,远快于线性查找。
7. 伪代码与编程基础概念 [2200s~2600s]
7.1 电话簿算法的伪代码
1 拿起电话簿
2 翻开电话簿的中间
3 看这一页
4 如果 John Harvard 在这一页
5 打电话给他
6 否则如果 John Harvard 在书的前半部分
7 打开左半部分的中间
8 回到第 3 行
9 否则如果 John Harvard 在书的后半部分
10 打开右半部分的中间
11 回到第 3 行
12 否则
13 放弃(John Harvard 不在电话簿里)
- 为什么可以循环回到第 3 行? 因为每次问题规模都在减半,最终会缩小到一页或空。
- 遗漏的 corner case:如果 John Harvard 根本不在电话簿里,程序会无限循环或未定义行为。必须处理“找不到”的情况。
- 理解:计算机死机/卡死往往是因为程序员没有预料到某些边界情况,导致软件进入未定义状态。
7.2 核心编程术语
- 函数(Functions):动词/动作,完成一小块工作。
- 条件(Conditionals):岔路口,决定走哪条路。
- 布尔表达式(Boolean Expressions):只能回答“是/否”、“真/假”、“1/0”的问题,以数学家布尔命名。
- 循环(Loops):重复执行某些操作。
- 理解:这些概念构成了所有编程语言(Scratch、C、Python 等)的共同基础。
8. 从机器码到高级语言:抽象的力量 [2600s~2800s]
- 计算机只懂 0 和 1(机器码)。早期人类直接用二进制编程(如打孔卡),非常繁琐。
- 编译器(Compiler):把高级语言翻译成机器码的程序。
- 层级示例:
- 机器码:
01101000 01100101 01101100 01101100 01101111(打印 "hello, world") - C 语言:
printf("hello, world"); - Python:
print("hello, world")
- 机器码:
- 抽象(Abstraction):我们可以站在前人的肩膀上,使用别人封装好的高级功能,而不必关心底层实现。例如 OpenAI API 封装了复杂的模型推理,我们只需几行代码就能调用。
- CS50 的教学路线:Scratch → C → Python → SQL → HTML/CSS/JavaScript,逐步从图形化到文本化,理解不同层次的抽象。
9. Scratch 入门:第一个程序 [2800s~3600s]
9.1 Scratch 环境介绍
- Scratch 是 MIT 媒体实验室开发的图形化编程语言(约 20 年前),适合初学者。
- 界面组成:
- 积木区(Blocks Palette):各种彩色积木,按功能分类(事件、控制、外观、声音、侦测、运算等)。
- 编程区(Programming Area):拖拽积木拼接代码。
- 角色区(Sprites):默认是一只猫,可更换角色。
- 舞台(Stage):角色活动的二维世界,有坐标系(x, y),中心为 (0,0),x 范围约 -240~240,y 范围约 -180~180。
9.2 第一个 Scratch 程序:说 Hello World
- 使用
当绿旗被点击(事件)+说 Hello World(外观)积木。 - 点击绿旗运行,点击红色停止按钮停止。
- 函数与参数:
说积木是一个函数,白色椭圆框是它的输入(参数/argument)。 - 副作用(Side Effect):屏幕上出现对话气泡就是副作用——程序运行产生的可见/可听效果。
9.3 让程序交互:询问名字
- 使用
询问 What's your name? 并等待(侦测)积木,它会返回一个值。 - 返回值(Return Value):函数返回给程序的值(存储在
回答变量中),人看不到,但程序可以使用。 - 用
连接 hello,和回答积木拼接字符串。 - Bug 演示:如果直接放两个
说积木,会看到先显示 "hello" 再显示名字,因为程序执行太快,人眼来不及看到。解决办法:使用等待 1 秒积木,或者用连接积木一次性输出。 - 理解:这个例子展示了“程序执行顺序”和“人眼感知速度”的差异,以及如何通过组合函数解决小问题。
9.4 声音与循环:让猫叫三次
- 使用
播放声音 Meow 直到播放完毕积木。 - 最初复制粘贴三次,代码冗余;改用
重复 3 次循环,并在每次之间加等待 1 秒。 - 代码质量:复制粘贴是坏味道,应该用循环/函数抽象公共逻辑。
9.5 自制积木(函数抽象)
- 使用
制作新的积木创建自定义的喵积木,内部封装“播放声音 + 等待”。 - 更进一步:给
喵积木添加输入参数n(次数),内部用重复 n 次实现。 - 抽象的好处:使用方只需调用
喵(3),不需要关心内部实现;修改内部实现不影响外部调用。 - 理解:这就是“封装”和“模块化”——把复杂细节隐藏,提供简单接口,是软件工程的核心思想。
9.6 条件与事件:宠物猫
- 使用
重复执行(forever)+如果 碰到鼠标指针?条件积木,实现“鼠标碰到猫时猫叫”。 - 演示 Bug:如果忘了
重复执行,程序只检查一次,之后移动鼠标无效——因为程序已经执行完了。 - 理解:需要“持续监听”事件时,必须用循环包裹条件判断。
10. 综合案例:Oscar Time 游戏 [3600s~4500s]
10.1 游戏目标与实现
- 学生作业:把掉落的垃圾拖到 Oscar 的垃圾桶里,音乐结束前得分。
- 实现步骤:
- 舞台背景:画一个灯柱(静态背景)。
- 角色:把猫换成垃圾桶(用不同造型切换实现动画——盖子打开/关闭)。
- 垃圾角色:从顶部随机 x 位置出现,y 固定 180,不断向下移动(
将 y 坐标增加 -1)。 - 拖拽:设置
将拖动模式设为可拖动,玩家可以拖动垃圾。 - 得分:如果垃圾碰到 Oscar,则“传送”回顶部(重新掉落),并
将 分数 增加 1。 - 音乐同步:用
等待积木精确控制不同垃圾的出现时间,与歌曲节奏匹配。
10.2 代码演进(Oscar 0→4)
- Oscar 0:只有背景和角色,无代码。
- Oscar 1:Oscar 角色检测鼠标,切换盖子开/关造型。
- Oscar 2:垃圾角色实现掉落和拖拽,碰到 Oscar 后回到顶部。
- Oscar 3:发现重复代码(两处“回到顶部”),创建自定义积木
回到顶部来消除重复。 - Oscar 4:添加
分数变量,碰到时加分。
10.3 设计教训
- 先解决小问题:不要一开始就想着完整游戏,先做背景,再做角色,再添加交互,逐步迭代。
- 避免复制粘贴:公共逻辑应提取为函数/积木,便于修改和复用。
- 数学坐标很有用:理解舞台坐标系(x, y)才能实现“从天空掉落”“左右移动”等效果。
11. 综合案例:Ivy's Hardest Game [4500s~5200s]
- 学生前辈实现的游戏,展示更多编程概念:
- 角色移动:用键盘方向键控制哈佛校徽移动(
如果 按下 上箭头 那么 将 y 坐标增加 1)。 - 墙壁碰撞:检测碰到左墙/右墙,然后反向移动 1 像素(反弹效果)。
- 敌方角色(Yale):自动来回移动——
重复执行+ 碰到墙转向 180 度 +移动 1 步。 - 追踪角色(MIT):
重复执行+面向 哈佛校徽+移动 1 步,实现自动追踪。 - 速度调整:把
移动 1 步改为移动 10 步会让游戏更难,但也可能产生视觉抖动(因为步子太大导致来回摇摆)。
- 角色移动:用键盘方向键控制哈佛校徽移动(
- 理解:这些游戏机制都可以用最基本的积木组合实现,体现了“组合”和“抽象”的力量。
12. 结尾与课程传统
- 课程结束时请学生上台玩最终版游戏,获胜后发放蛋糕(CS50 第一节课的传统)。
- 鼓励学生在课程网站(cs50.dev)上动手实践,使用 Scratch 完成自己的第一个编程作业。
关键标签/关键词
CS50 Lecture 0 Scratch 二进制 ASCII Unicode RGB 算法 二分查找 伪代码 函数 循环 条件 布尔表达式 抽象 编译器 变量 返回值 副作用 AI OpenAI API 橡皮鸭调试法 计算思维
生成时间:2026-09-02 15:37:56 生成平台:VideoNote