Skip to main content

笔记

Lecture 0 - CS50x 2023

欢迎!

  • 这门课不仅仅是关于计算机编程!
  • 事实上,你将在此学到极具价值的问题解决技巧。这些技巧不仅能立即应用于本课程之外的学习,更能助你一臂之力,在未来的职业生涯中大放异彩!
  • 然而,这并不容易! 在这门课程中,你将会面临海量的信息。 你会惊讶于你在未来几周内能够完成的事情。
  • 本课程的重点在于帮助你从现有水平不断进步,而非达到某种既定的标准。
  • 本课程最重要的建议是:请务必安排充足的时间来学习。 每个人学习的方式都不同。 如果起步阶段遇到困难,请不要灰心。随着时间的推移,你的技能定会不断提升。

后续内容

  • 本周你将学习 Scratch,一种可视化编程语言。

  • 然后,在未来的几周里,你将学习 C 语言。它看起来像这样:

      #include <stdio.h>

    int main(void)
    {
    printf("hello, world\n");
    }

  • 后续课程中,你还将学习算法。

  • 你将学习内存。

  • 你将学习如何识别并修复代码中的缺陷,以及导致计算机崩溃的常见原因。

  • 你将学习诸如哈希表之类的数据结构。

  • 然后,我们将过渡到一种新的、更高级的语言,称为 Python。 你的代码看起来像这样:

      print("hello, world")
  • 通过本课程,你将深入了解现代编程语言从早期语言演变而来的过程。

  • 我们还将研究如何使用数据库和第三方框架来构建 Web 应用程序。

社区!

  • 你将与来自哈佛学院、哈佛推广学院以及通过 edX.org 参与本课程的同学们共同组成一个学习社区。
  • 本课程还会组织解谜日和 CS50 展览会等活动。

计算思维

  • 本质上,计算机编程就是接收输入,产生输出,从而解决问题。而输入和输出之间的过程,也就是我们常说的“黑盒”,正是本课程要重点探讨的内容。

    带有输入和输出的黑盒

  • 举例来说,我们需要统计班级的出勤情况。可以用“一元计数法”,也就是扳手指头来数。现在的计算机则使用二进制计数。我们常说的“位 (bit)”,就是从“二进制数字 (binary digit)”这个概念衍生出来的。一个“位”要么是 0,要么是 1。

  • 计算机的世界只有 0 和 1。0 代表“关”,1 代表“开”。计算机内部有数百万甚至数十亿个晶体管,它们通过不断地开关来工作。

  • 想象一下,如果用一个灯泡来计数,它只能表示 0 或 1 两种状态。

  • 但是,如果有三个灯泡,就能表示更多的信息了!

  • 使用三个灯泡,以下可以代表零:

    0 0 0
  • 类似地,以下将代表一:

    0 0 1
  • 按照这个逻辑,我们可以提出以下等于二:

    0 1 0
  • 进一步扩展这个逻辑,以下代表三:

    0 1 1
  • 四将显示为:

    1 0 0
  • 事实上,我们只用三个灯泡就可以数到七!

    1 1 1
  • 我们可以这样理解:在二进制数中,每一位上的值代表着不同的权重:

    4 2 1
  • 计算机使用“以 2 为基数”的计数方式,也就是二进制。如下图所示:

      2^2  2^1  2^0
    4 2 1
  • 所以,需要三个比特位(分别代表 4、2 和 1)才能表示最大为 7 的数字。

  • 计算机通常用 8 个比特位(也就是一个字节)来表示一个数字。例如,00000101 这个二进制数就代表十进制的 5。

文本

  • 正如数字是 1 和 0 的二进制模式一样,字母也用 1 和 0 表示!

  • 由于数字和字母都用 0 和 1 来表示,为了区分它们,就有了 ASCII 编码,将特定的字母对应到特定的数字。

  • 例如,字母 A 被决定映射到数字 65。

  • 例如,你收到一条短信,其底层二进制数据可能对应着 72、73 和 33 这几个数字。将它们转换为 ASCII 码,就会得到如下信息:

      H   I   !
    72 73 33
  • 多亏有了像 ASCII 这样的标准,我们才能对这些数值达成共识!

  • 这是一个扩展的 ASCII 值图:

    ASCII 映射

  • 如果你愿意,你可以了解更多关于 ASCII 的信息。

表情符号

  • 随着时间的推移,通过文本进行交流的方式越来越多。

  • 由于二进制编码的位数有限,无法表示人类使用的所有字符,因此 Unicode 标准扩展了编码的位数,从而能够表示更多的字符。

  • 你可能每天都在使用表情符号。以下内容你可能很熟悉:

    表情符号

  • 为了让表情符号更具个性化,计算机科学家们希望为每个表情符号添加不同的肤色选项。他们面临的挑战是,如何在现有编码的基础上实现这一点。最终,表情符号的创建者们决定,用一部分编码表示表情符号的基本结构,另一部分编码表示肤色。

  • 越来越多的功能被添加到 Unicode 标准中,以表示更多的字符和表情符号。

  • 如果你愿意,你可以了解更多关于 Unicode 的信息。

  • 如果你愿意,你可以了解更多关于 表情符号 的信息。

RGB

  • 红色、绿色和蓝色(简称 RGB)是三种颜色的数值组合。

    红绿蓝框

  • 如果我们采用之前用过的数字 72、73 和 33,它们在文本中表示 HI!,但在图像读取器中会被解读为一种浅黄色。其中,红色分量是 72,绿色分量是 73,蓝色分量是 33。

    黄色框

图像、视频和声音

  • 图像本质上是 RGB 值的集合。
  • 视频是由一系列连续的图像组成,这些图像按顺序排列,类似于翻页书。
  • 音乐可以通过 MIDI 数据表示。

算法

  • 解决问题是计算机科学和编程的核心所在。

  • 想象一下,在电话簿中查找单个姓名的基本问题。

  • 你会怎么做呢?

  • 一种方法就是从第一页开始,一页一页地翻,直到最后一页。

  • 另一种方法是每次翻两页。

  • 最后一种可能更好的方法是直接翻到电话簿中间,然后判断:“我要找的名字是在这页之前还是之后?” 接着,重复这个步骤,每次将查找范围缩小一半。

  • 这些方法都可以被称为算法。每种算法的效率可以用所谓的 大O表示法 来衡量,如下所示:

    大O符号 注意,第一个算法(红色高亮显示)的大O复杂度是 n,这意味着如果电话簿里有 100 个名字,最坏情况下需要查找 100 次。第二个算法,每次查找两页,大O复杂度是“n/2”,效率提高了一倍。最后一个算法的大O复杂度是 log2n,也就是说,问题规模翻倍,查找步骤只增加一步。

伪代码和编程的基本构建块

  • 编写伪代码的能力对于在本课程和计算机编程中取得成功至关重要。

  • 伪代码是代码的一种人类可读的版本。例如,考虑到上述第三种算法,我们可以这样编写伪代码:

      1  拿起电话本
    2 翻到电话簿中间
    3 看那一页
    4 如果那个人在这一页上
    5 给那个人打电话
    6 否则,如果那个人在书的前半部分
    7 翻到书的左半部分的中间
    8 返回第3行
    9 否则,如果那个人在书的后半部分
    10 翻到书的右半部分的中间
    11 返回第3行
    12 否则
    13 退出

  • 编写伪代码是一项非常重要的技能,主要有两个原因。首先,在创建正式代码之前编写伪代码,可以帮助你提前理清问题的逻辑。其次,编写伪代码后,你可以将它提供给其他人,帮助他们理解你的编码思路和代码的工作方式。

  • 请注意,我们的伪代码语言有一些独特的特点。首先,其中一些行以动词开头,例如拿起打开等。稍后,我们会将它们称为函数 (functions)。

  • 其次,请注意,有些行包含诸如ifelse if之类的语句。这些被称为条件语句 (conditionals)。

  • 第三,请注意,有些表达式可以被陈述为,例如“那个人在书的前面”。我们称这些为布尔表达式 (boolean expressions)。

  • 最后,请注意像“返回第3行”这样的语句。我们称这些为循环 (loops)。

  • 在接下来要讨论的Scratch中,我们将使用上述每个编程的基本构建块。

Scratch

  • Scratch 是一种由麻省理工学院 (MIT) 开发的可视化编程语言。

  • Scratch 使用的是我们在本次讲座前面介绍过的那些基本编程构建模块。

  • Scratch 是学习计算机编程的绝佳入门方式,因为它能让你以可视化的方式操作这些构建模块,而无需操心花括号、分号、圆括号之类的语法问题。

  • Scratch 的 IDE (集成开发环境) 界面如下所示:

    scratch interface 请注意,在左侧,是你在编程时可以使用的各种构建块。在这些构建块的右侧,你可以将它们拖拽到编程区域来搭建程序。在编程区域的右侧,你会看到猫咪所在的舞台舞台是你的程序运行和呈现效果的地方。

  • Scratch 使用如下所示的坐标系:

    scratch coordinate system 请注意,舞台中心位于坐标 (0,0),现在猫咪也位于这个位置。

  • 首先,把“当绿旗被点击”积木拖到编程区。然后,再把 say 积木拖过去,和之前的积木连接起来。

    scratch with black box

    请注意,现在点击舞台上的绿旗,猫咪就会说“hello world”。

  • 这很好地解释了我们之前讨论的编程原理:

    scratch with black box 请注意,输入 hello world 被传递给 say 函数,而该函数运行的副作用就是猫咪说出 hello world

  • 我们可以让程序更具互动性,让猫咪对特定的人说 hello。按如下方式修改你的程序:

    scratch with black box

    请注意,点击绿旗后,ask 函数开始运行。程序会提示用户输入姓名 ( What's your name? ),并将用户输入的姓名储存在名为 answer变量里。接着,程序会将 answer 传递给名为 join 的特殊函数,这个函数会将文本字符串 hello 和用户输入的姓名拼接在一起。然后,拼接好的字符串会被传递给 say 函数,猫咪就会说“Hello, [用户姓名]”。现在,你的程序就具有交互性了。

  • 类似地,我们可以这样修改程序:

    请注意,点击绿旗后,这个程序会将同样的变量和 hello 拼接在一起,然后传递给 speak 函数。

抽象

  • 除了伪代码之外,抽象是计算机编程中一项至关重要的技能和概念。

  • 抽象是将一个问题简化为越来越小的问题的行为。

  • 例如,如果您要为朋友举办一个盛大的晚宴,那么准备一整桌菜的难题可能会让人感到无从下手!但是,如果您将烹饪饭菜的任务分解为越来越小的任务(或问题),那么完成这顿美味佳肴的重任就会显得轻松一些。

  • 在编程区,输入以下代码:

    scratch abstraction

请注意,您一遍又一遍地做着同样的事情。事实上,如果您发现自己反复编写相同的语句,那么您很可能可以更巧妙地进行编程——将这种重复的代码抽象出来。

  • 您可以按如下方式修改您的代码:

请注意,循环实现的功能和之前的程序完全一样。但是,通过将重复部分抽象成一个重复执行代码的积木,问题就得到了简化。

  • 我们甚至可以使用 define 积木来更进一步!按如下方式编写代码:

    scratch define 请注意,我们正在定义我们自己的名为 meow 的积木。这个函数会播放 meow 的声音,然后等待一秒。在下面,您可以看到,当单击绿旗时,我们的 meow 函数会重复三次。

  • 我们甚至可以提供一种方法,让函数可以接受输入 n 并重复多次:

    scratch define

    请注意,n 是从“meow n times”中获取的。 n 通过 define 积木传递给 meow 函数。

  • 顺便说一句,我们可以将猫称为 sprite——游戏编程中用于屏幕上对象或角色的通用术语,玩家将与之交互。

If

  • 条件语句是编程的基本组成部分,程序会检查是否满足特定条件。如果满足条件,程序会执行某些操作。

  • 为了说明条件语句,请按如下方式编写代码:

    请注意,forever 积木会不断重复执行,持续检查猫是否碰到了鼠标指针。

  • 我们可以这样修改程序,来加入视频感应功能:

  • 请记住,编程通常是一个反复试验的过程。如果您感到沮丧,不妨冷静下来,仔细分析一下当前的问题。您现在正在处理的具体问题是什么?什么在起作用?什么不起作用?

Expanding Your Imagination

  • 在本次讲座中,我们展示了一些Scratch程序,旨在激发大家的想象力。

  • Oscartime 是 David 自己的 Scratch 程序之一 —— 虽然创作过程中,为了这段音乐,他听了无数遍,现在可能都有点怕了。不妨花点时间亲自体验一下这个游戏。

  • 要自己动手制作Oscartime,首先要添加一个路灯。

    oscartime 界面

  • 然后,按如下方式编写代码:

    注意,当鼠标悬停在Oscar角色上时,他的造型会发生变化。点击此链接,可以查看更多代码细节:

  • 接下来,按照下面的方法修改代码,创建一个下落的垃圾。

    注意,垃圾在Y轴上的初始位置是180,X轴的位置是随机的。 当垃圾高于地面时,每次会向下移动3个像素。点击此链接,可以查看更多代码细节:[]

  • 接下来,修改代码,让垃圾可以被拖动。

    点击此链接,可以查看更多代码细节:

  • 接下来,我们可以按如下方式实现评分变量:

    点击此链接,可以查看更多代码细节:

角色移动

  • 现在,让我们从Oscartime转移到Ivy’s Hardest Game,我们现在可以想象如何在我们的程序中实现移动。

  • 这个程序主要由三个部分组成。

  • 首先,按如下方式编写代码:

    注意,点击绿旗后,角色会移动到舞台中央(0,0)的位置,然后持续监听键盘输入,并检测是否碰到墙壁。

  • 其次,添加第二组代码块:

    注意,我们创建了一个自定义的“listen for keyboard”脚本。 通过按下键盘上的方向键,可以控制角色在屏幕上的移动。

  • 最后,添加这组代码块:

    注意,还有一个自定义的“feel for walls”脚本。 当角色碰到墙壁时,这个脚本会把它移回安全区域,防止它穿墙而出。

  • 点击此链接,可以查看更多代码细节

  • 快去体验完整的游戏吧!Oscartime

更多角色

  • Scratch 允许在屏幕上同时显示多个角色(精灵)。

  • 要添加另一个角色,请把下面的代码块添加到你的程序里:

    注意看,耶鲁的角色好像在来回晃悠,挡了哈佛的角色。碰到墙后,它会转弯,直到再次撞墙。 想了解更多?可以看看这些代码块:浏览这些代码块

  • 您甚至可以使一个角色跟随另一个角色。 要添加另一个角色,请将以下代码块添加到您的程序中:

    注意看,麻省理工的标志现在好像在追着哈佛的标志跑。 您可以通过浏览这些代码块了解更多信息。

  • 快去试试完整的游戏吧!Ivy’s Hardest Game

总结

在本课程中,您了解了本课程在广阔的计算机科学和编程领域中的地位。 您学到了…

  • 很少有学生在参加本课程之前有编码经验!
  • 你不是一个人在战斗! 你是社区的一员。
  • 解决问题,才是计算机科学家的真谛。
  • 这门课不仅仅是教你编程,更会教你一种新的学习方法,让你受益终身。
  • 计算机如何理解数字、文本、图像、音乐和视频。
  • 伪代码的基本编程技能。
  • 抽象将如何在您未来的课程工作中发挥作用。
  • 编程的基本构建块,包括函数、条件、循环和变量。
  • 如何在 Scratch 中构建项目。

咱们下节课见!