[Powered by Google Translate] 演练] [习题集3] [Zamyla陈] [哈佛大学] 这是CS50。[CS50.TV] 好了,欢迎大家演练3。 PSET是一个非常有趣的。 这是一个新的CS50称为争夺, 因此,如果你曾经玩过的争夺或类似的棋盘游戏惊奇 它本质上是一个游戏,你必须一格的字母, 在规定的时间,你需要找到尽可能多的 2个字母或更长时间存在的话,在黑板上, 所以也有一定的规则,比如你可以只用一个字母 的网格,在网格中的一个块,你不能回去吧。 你只能建造字母联系在一起的相邻字母, 所以这将是一个非常有趣的pset中,让我们来看看在我们的工具箱。 同样,设备仍在更新,所以一定要确保 每次你进入家电右键打开终端窗口 在终端命令sudo yum的-Y更新。 这也是很重要的,如果你希望能够  运行人员的解决方案,我们肯定建议。 有时候这是很好的,一旦你已经完成了你的代码 对工作人员的解决方案进行测试,确保一切 你进入的工作人员的解决方案,无论出来, 同样的事情发生,你的代码。 好了,所以一定要确保以更新您的设备。 现在,也因为我们正在处理与电网在这种情况下, 我们实际上是要深入研究2维数组。 我们已经处理了一维数组, 但现在我们要扩大他们,让他们有 多个行和多个列。 然后,我们将一定会在此pset的使用功能, 基本上调用一个函数,将一些参数了 ,然后得到一个返回值返回。 在争夺我们不是要求你从头开始,实际上使整个事情, 而是,我们实际上是在给你所谓的分配代码的东西, 所以,我们已经写了这样的代码的功能奠定了 在pset的骨架以及实现一些困难的事情 你一定能够阅读和理解 但并不需要很清楚它。 要迅速在一维数组的老调重弹。 数组是有相同类型的多个值的数据结构, 作为提醒,这些数组是从零开始索引, 所以大多数人都可能熟悉像这样的一个数组。 如果我们想要一个int数组的长度为3, 那么我们就可以对它进行初始化int类型的值。 然后方括号表示它的长度, 然后我们将值分配​​给该数组中的特定元素。 在这里,我们有一个int数组的第一个索引在索引0,2, 是4索引1,索引2是6。 假设我们想要一个更大的数组和容纳多个值。 然后,我们可以有一个二维数组。 现在,这是非常相似,我们的一维数组。 它的0索引,因此这意味着,第一列 是采集在0。 下一个是1,然后,下一个是在2, 然后同样,我们有行,并让你看到,当我们 声明我们的数组,我们还像以前一样,我们表示数组的大小。 我们也同样表示的大小的第一托架 表示你有多少行,第二个指示 有多少列。 所有权利,在此pset的,你要能够 遍历二维数组,可以访问每一个元素 在这个二维数组,所以基本上你想达到 的行和列的值的所有可能组合。 我们想要达到0行,第1列,2,和3。 我们要达到行1列0,1和2。 我们必须有某种结构,使我们能够 遍历所有的行和所有的组合 在该列。 在这里,我有一个二维int数组。 它有3行3列, 所以这是的快捷方式 发现整个二维数组。 我说的第一行,将有2,4,和6, 种在这张幻灯片和前面的例子类似。 然后,我将有第2行3,6,9, 然后第3行4,8,12。 我们有我们的二维数组, 我们知道,它看起来像这样。 我们有2,4,6, 3,第6,第9, 4,8,12。 现在,如果我们添加的指数, 这将是0行。 这将是第1行。 这将是第2行。 同样,我们有0列, 第1列和第2列。 是。 [男]其中三名为列,哪一个是行吗? 列这些, 所以你列的这些的。 这是第0列,这是第1列。 这是第2列。 [男]如何在声明中的int表[3] [3]? 当你声明的二维数组,然后在方括号中的第一个数字 将是你有多少行, 然后,第二个是要多少列。 太好了,所以我们需要某种结构, 某种循环,将会给我们每一个可能的组合。 说,我们开始说 - 好吧,在此行中访问任何 让我们现在只是看在这行。 这些都是行这里。 我们知道,我们的行索引为0, 但访问此元素,它是在第0行和第0列, 这样的话,我们就可以访问它的索引[0] [0]。 然后这一个,同样地,仍然是在第一行上, 但它是在第二列中,所以我们访问由[0] [1]。 然后,最后一个将是[0] [2]。 当我们在一个特定的行,我们将要 遍历所有可能的列值。 让我们从一个for循环 从0开始,并进入我们有多少行的长度。 这是骑自行车的每一行。 然后我们想要做的是在该 每当我们在一个特定的行,我们要循环通过所有可用的列, 这样的话,我们将有另一个循环。 让我们把它Ĵ。 I,j和k是很常见的行索引的循环变量, 这样你就可以使用,如果你喜欢。 也尽量避免,然后,如果这些变量中常用的循环 尽量避免使用它们像其他的东西在你的代码中的变量名 只是因为它是常见的约定使用i,j和k内循环或指数。 好吧,那么我们在这里有一个for循环遍历所有的行。 每次,它是在不同的行 我们会遍历所有的不同的列。 这种方式,我们实际上可以得到所有可能的组合 0,1,2,0,1,和2。 这有意义吗? 这样我们就可以访问每一个值。 现在,我们可以选择做列第一和。 这真的无所谓,只要你遍历 所有的列的所有行。 现在让我们做一些与这些值。 比方说,打印。 现在,让我们来打印他们的整数 的变量,然后在那个地方是,它是一个n值表。 现在具体的行的索引将是我,因为我们使用它来遍历我们的行, 然后j遍历我们的专栏。 现在让我们来2D。 现在,当我们运行2D打印出所有的值 在我们上面指定的顺序, 所以你看,它首先经过的所有行, 所以这是在第0行,然后打印所有在该行的值 然后继续执行。 这是一个例子的方式,你会遍历 和一个二维数组中的值进行行动。 太好了,现在,我们将看到在分配代码的功能很多, 所以其中的一些功能将是布尔函数 返回一个布尔值,他们给你。 有些人会是整数,例如,等基本上 审查职能基本功能是有一点点 一个返回值,名称,使用与调用程序, 然后他们可以有任意数量的参数。 从本质上讲,当你的下一个函数内调用该函数, 基本上就像你现在说的,我希望你能执行此功能, 你必须通过在某些值,所以在这种情况下,我们的函数foo 将有2个整数,并在该函数,然后 这将是能够访问它们,把它们称为x和y。 一个类似的例子是低功能 你可能已经在你的加密程序, 所以基本上这些功能已经为你写的, 但根据他们的返回类型,你可以使用他们的职责范围,。 假设你有一个名为foo的布尔函数。 然后,你可以使用,因为你知道,这将是一个布尔值。 从本质上讲,当你调用它,它会返回一个布尔值, 这样你就可以把它当作这将是一个布尔。 在你的条件,你可以简单地说 如果foo,然后再通过它所需要的参数, 5和9的实例中,2的整数, 然后,你知道这将返回true或false, 这样的话,您可以使用这个作为条件本身。 同样地,你也可以说富(5,9)== TRUE 或==虚假或类似的东西, 但稍不必要的,因为函数本身就是 已经值或真或假。 我们要记住这一点,当我们看到一些例子,在分配代码。 好了,回到争夺后,我们有二维数组 了解我们的皮带下的功能。 在争夺本质上,你将有一个网格的字母, 然后你要帮助实施一个方案, 据此,用户可以输入不同的字母,他们看到对电网, 所以,这也意味着,你要绘制游戏板。 然后,用户将被输入的某些词, 但是,你必须检查A,在字典中的那些话是否是有效的, 或B,它们是否真的存在于电路板,可以发现在董事会。 然后在分配代码,我们会去那个在第二。 你会看到什么已经为你做的, 然后在给定的结构的分配代码添加功能。 有一定的功能都是空白的。 有一定的功能,你只需要添加。 有一定的功能,你要工作是平局, 所以你要实现的绘制函数, 其实在黑板上画所有的字母。 你要必须实现的查询功能,让你不得不检查 的字符串是否用户输入的是一个有效的单词的情况下, 这样的话,因为我之前提到的,这包括是否在字典中不 以及它是否是一个有效的游戏移动。 然后,你要实现的争夺 其中,如果用户是在游戏中,例如,具有麻烦找到任何字 然后如果他们键入“抢”到的提示 随后的比赛板旋转90°, 保持相同的字母,但只要旋转90°顺时针。 最后,我们要处理情况和灵敏度, 本质上,当所有的字在字典中的分布代码包含在 都存储为大写字母,但我们希望让用户,例如, 如果他们进入混合物中的小写和大写 或者只是小写字母,如果这个词是有效的 那么他们就应该以及能够获得积分。 好了,所以分配的代码,它可能是一个有点艰难获得通过第一。 您可能不希望阅读这一切,只是直 编写程序,但请不要读一次, 读了两遍,读三次,读一遍,一遍 让你有一个良好的意识和感觉真的很舒服 的代码,即使你没有写自己的这些功能​​, 样的,你知道他们在做什么,你可以期望 的方式,他们可能会与你要实现的功能进行交互。 事不宜迟,让我们进入这个分配代码, 我会帮助你们理解它。 我已经下载了分配代码。 你可以做到这一点。 的指示,在规范中,你必须使自己的目录的pset 3, 然后,如果你执行一个命令,在规范中找到 然后你就可以下载文件, 其中包含基本的字典文件,如果我们只是看,很快。 这在本质上包含一个完整的列表的话,将是我们的字典。 好吧,让我们从顶部开始。 另外在这里你会发现,这种分配代码的好作风 是对我们有利,因为我们可以看到评论 解释代码是如何被使用的。 我们有这样的,包括我们的图书馆。 请注意,我们在这里的#include 使图书馆可以让我们跟踪的时间,因为 你必须在争夺基本上进入尽可能多的话 在给定的时间框架。 在这里,我们有一些变量。 比赛期间,我们已经将它设置为30秒。 我们说,在网格的尺寸,它是一个方形网格 将是4×4。 我们说的话,一些字在字典中, 在任何地方都可以最多只有29个字母。 然后这里有一个名为log的文件。 从本质上讲,我们要自动化的一些结果从您的代码, 所以尽量不要改变任何东西,因为我们将做日志处理。 您不必不太明白,但, 只是尽量不要改变任何事情,做日志。 请注意,在这里变量网格,其中的字符是一个二维数组, 我们的主要功能外声明, 所以,这就是我们所说的一个全局变量。 因为我们正在处理的一个游戏,在这里, 如果你还记得所有的方式回到划伤 当我们有类似的得分,例如, 当我们正在处理的一个游戏,可以访问到 大量的各种脚本,所以同样的,我们有这个变量 需要可以访问了很多的功能在我们的程序中, 所以网格这里是一个2维数组,将存储 争夺游戏中的字母。 稍后我们将看到使用后, 但我们也有一个二维数组的布尔值叫做标记, 所以基本上当我们进入检查是否有字 是有效还是无效,我们需要知道我们是否已经访问过某块, 参观了一定的信,然后标记基本上是要 包含在一个给定的索引或真或假, 因此,它可以让我们知道我们是否已经到过那里, 我们是否已经访问过的信,在我们的某些核, 等标记,以后你会看到, 基本上准确地反映了电网。 在这里,我们决定,我们希望我们自己的数据类型。 我们不快乐,只是字符串。 实际上,我们想要的东西称为一个字, 因此,我们有这个typedef结构, 然后在它被发现的,它有一个布尔, 因此,无论这个词已被发现或没有。 然后,它有一个字符数组, 基本上,它是实际的单词。 那么,现在的话是,我们已经取得了实际的新的数据类型, 所以我们可以有,例如,一组字 我们可以做一个新词,他们中有多个实例。 但是,我们只有一个字典,所以这就是为什么我们只有一个 结构调用字典,而不是一个typedef结构。 结构有与字典中的大小的整数 以及作为一组字,并再次 我们使用这个全局变量的话,这是上述定义, 的字的数量,实际上在我们的字典。 在这里,我们有一个完整的列表的原型,函数原型, 本质上说,好了,现在你可以期望有 所有这些功能都在程序中。 我有一个void函数,称为透明, 抓取是发生在一个布尔函数 一个字符串,然后2个整数,等等,让你看到这里。 在gedit也是一个不错的功能是沿侧 如果您确保您选择了此功能选项卡,在这里, “源代码”选项卡,然后将实际显示的所有功能 你必须在你的程序中。 它会告诉你一些事情,你可以使用。 例如,在这里,你已经定义了一个新的数据类型,称为字 然后,你有一定的全局变量。 但这个功能“选项卡是非常有用的,因为你可以点击来回 并跳转到你的程序中的特定点。 好吧,我们现在的主要功能。 当用户输入的命令中, 基本上可以说/争夺, 或者它们也可以在一个数字输入后,基本上表示 委员会要玩。 通常,只要你输入一个命令行参数 那么它只是给你一个随机的板,但说用于调试目的 你想,以确保您只需检查一遍又一遍相同的电路板 然后你可以做什么,只是说./scramble1,例如, 它总是给你相同的电路板。 在这里,它确保正确使用, 因此,如果用户输入的命令行参数超过2, 然后,它会教他们如何正确使用程序 然后退出。 在这里,如果argc是2,这意味着,如果用户已经输入的数字 具体的字,他们要使用,然后 基本上当程序以后进行了随机板 然后,我们基本上是给它的种子,迫使它有点像 使用一定的价值。 那么在这里我们载入我们的话的文件。 基本上,如果它不能打开字典,如果出现错误, 然后将返回1。 我们初始化电网。我们来看看该功能后。 我们设定的得分为0。 我们计算比赛将结束时, 所以这是30秒,因为我们设置。 那么在这里,再次是日志文件,你不需要改变。 这里我们的程序中有一个while(true)循环的肉, 所以请注意,如果你只是有一个while(true)循环本身 然后将继续执行,无论是在它的身体, 但正如你将在后面看到,我们实际上有一个休息 所以我们实际上让我们有一些方法,它实际上打破了 的功能,而不是执行,直到永远。 首先是在屏幕上,会发生什么事情将清除 这样就可以得出一个新的董事会,那么它将调用的函数绘制。 再次,它会记录它,所以基本上每次通过这个循环 它会报告给你的分数。 检查游戏是否应该结束, 无论你是或不,然后汇报你已经离开了多少时间 如果本场比赛仍然在起作用。 那么在这里我们有一个提示就一个字, 然后我们的GetString函数, 所以这是用户输入一个词来形容你。 然后基本上,如果他们实际上已经进入了一个字,如果它不为空, 然后程序会记录它。 然后,你要检查是否需要来扰乱电网, 所以基本上如果他们在命令争夺战中,争夺进入, 那么它会旋转90°。 ,然后否则,如果它不是字争夺战 然后你想要做的是,你要查找单词。 (发现(字)是真实的。稍后我们将进入该功能。 然后你会想看看它,所以基本上是在网格上, 是它在字典中吗? 而且,如果是这样的话,那么它会增加你的分数的字母数 这个词是。 这是我们的主要功能。 我们在这里可以看到,这是本质上就像一个转义码, 所以你不需要担心这么多, 但基本上只要你所说的清晰,它会清除终端 将光标移回和擦除任何写了前种。 让我们不要去抓取相当只是还没有。 相反,我们会向下滚动,在这里看到的绘制函数, 这是你的工作TODO。 从本质上讲,你必须打印在当前状态下的电网, 因此,我们已经照顾的实际初始化电网, ,所以你不必担心哪个字母放置在网格 或类似的东西,但在绘制函数时,你会想 打印出来,无论是在网格中。 那么在这里我们有一个布尔函数调用找到, 在主函数中,我们看到上面。 如果这个词被发现,也被在字典中查找, 如果这两个返回true,那么它会增加得分。 这里是需要在Word作为一个字符串查找功能, 它必须是2个或更多个字符, 然后这是什么做的是搜索这个词的网格。 在这里,我们看到的例子在网格中每一个元素的迭代 他们的行和列,然后在迭代的迭代。 在这里记住的标记二维数组的基本存储或真或假的 我们是否已经去过那封信。 从本质上讲,这将重置所有标记,因为我们只处理与标记 每一次,我们正在检查一个特定的单词。 然后在这里,一旦我们重新设定所有的标志 它实际上搜索这个词,所以要搜索的单词 这就是我们使用的抓取功能,让我们回去爬 来看看它。 什么抓取的是,它需要在一个字符串中字母 以及基本上是x和y,其中的起始索引 字是其中用户已所述。 本质上,它会检查,如果x <0>尺寸 基本上,这意味着,该指数实际上不存在在我们的游戏中, 这样的话,返回false。 如果你已经访问过的具体信 然后,要返回false,因为在争夺规则 是,当你有 这里的信,例如, 你可以加入一个字母或对角线这样, 所以基本上你的下一个字母可以在任何相邻块, 但你不能做的事情,比如,去这封信 回去的A,所以你只能使用一次每个字母。 那是有道理的,这里的标志,如果我们曾经做过的那样, 如果标记设置为true,那么这是不是一个有效的单词。 然后它是什么,它​​会检查。 它说,我要在这个特定的位置,以检查是否 信,我们希望是存在的。 如果不是的话,则返回false。 由于它已被选中块,那么它会设置标记 在那个特定的点为真。 现在,检查,基本上,如果我们将继续 这意味着我们要去寻找下一个字母 在Word的用户试图提交。 这里记得的规则。 你试图去检查所有的相邻值, 的上方,下方,左侧和右侧,以及对角线 同样,当我们想遍历二维数组 我们要遍历每一个可能的检查 每一个可能的排列之间的行索引和列索引 在这里,我们要检查所有可能的组合, ,如果是左侧的信,上面直接,或向右。 在这里,我们看到,这个循环检查的左侧 当我为-1。 当它为0时,它会检查在同一列,这封信是, 然后,如果i是1,这是它的最终值,然后它检查到右侧, 那是不足够的,对不对? 我们需要检查所有的垂直值, 这样的话我们这里有一个循环会检查它是否低于 在相同的水平或以上,那么该组合 将要访​​问的每一个相邻块A. 然而,它也检查块在A, 这样的话,我们要确保我们不检查一个。 那么现在,到了前面的检查是否是有效还是无效 然后,我们想要做的相同的过程在其余的字 除非我们已经做了一个,那么这里是一个前体功能。 它要求本身,我们将进入一个位后, 但它为所有后续的字符串进行相同的过程。 我们已经讨论了查找功能。 我们知道它在做什么。 它基本上是检查是否用户给这个词, 在黑板上,确实存在,它是否是一个有价值的举动。 在这里,我们有一个初始化函数。 请注意,它的无效,所以它不会重新回到了我们什么, 但它只是将要为我们做的事情。 这里关闭的维基百科有一个频率 上的每一个字母的字母的基础上多久 在英语中它的使用。 你可以看到,e是,例如,一个最流行的字母。 我们要填充电网。 这个函数的功能是填充字母的网格 相对于它们的频率在这个数组中的一种。 现在,这是使用这种语言 说的频率,大小 这是一种只有特定的情况下。 事实上,我们可以使用的频率的大小,所以,当你真正想要 找到一个数组的长度,你可能不会使用大小的 而仅仅是使用数组的长度。 你可以问你的TFS跟你说话多一点, 但我们知道,这种语法在这里是一个特殊的情况下。 现在,在网格中的每一个元素 我们希望让一个字母,这将是伪的, 所以随机的,但不完全是。 从本质上讲,这确实是我们制定了一个新的双 一个随机的0和1之间的值。 基础上,我们要映射, 所以说,d被设定为0.6,例如。 然后,如果d是60%,在 然后我们要去看看所有的字母和 相对于他们已经习惯了多久 60%英寸 这是没有的字母,但只有60%,而 一个占用这么多空间,然后B需要这么多, 然后E,例如,将占用这么多。 基础上的相对的长度或频率 这些信件中,我们要映射这个随机值 0和1之间的一个特定的信。 这就是这个代码在这里, 然后在这里k是一样的转变在哪里沿 在信中,我们想要的,所以我们在网格中设置字符 A + K。 请注意,回想着贪婪 我们不得不使用ROUND函数来处理浮点不精确, 同样,我们必须考虑到,有时 浮标不正是我们打算在他们的, 因此,我们要作出的渔获量。 那么在这里我们进入文件I / O,基本上读取和写入文件, 你会得到后,但尚未完全, 所以基本上这将打开一个字典文件,读什么, 然后将其设置为一个数组。 请注意,我们将它设置到结构,我们已经宣布,字典结构, 所以词典的数组,称为词联系在一起, 所以它在做什么说的话词典,在这个特殊的指数 是这样的,这样的价值。 然后,我们几乎完成分配代码。 您有任何意见,我们终于有查找功能 指示你的代码应该做的是什么。 查找将在字典中查找单词 只要这个词还没有被发现已 标志,它作为发现,用户可以使用它再次 但也返回true思想的主要功能, 返回true,所以说,这个词可以拿下。 然后你终于加扰功能, 这是另外一个void函数,因为它做的事情 但不返回任何东西,所以会做什么的加扰功能 网格旋转90°的顺时针方向旋转。 我知道,可能是有点粗糙,但它是非常重要的。 看我经历的分配代码, 但是,请尝试去通过自己。 我喜欢做的是了解它映射 这是什么计划,所有这些功能实际上做什么? 如果我是通过重新分配代码, 现在,我种的感觉发生了什么事情,然后我会说 我们开始我们的主要功能, 然后我想到的第一件事情,它是调用load, 所以主要的呼叫负载,但负载是一个void函数, 所以后来我做什么,表明只是把一个单箭头 指向加载,因为主要要求。 接下来的事情就是初始化。 主要调用初始化, 然后,如果我们回头看我们的主要功能 我认为这接下来的事情,它, 这里有不同的东西,主要是呼吁吨, 但现在,我只是专注于最重大的 相关的代码,所以我不包括一个我或类似的东西。 那么接下来的事情,它是清除它, 然后它有画, 所以我知道抽奖的东西,我们要做的。 这就是平局功能。 后来我们看到,下一个是有点 这样的话,我们有争夺。 然后我们发现,这样的发现是另一个功能。 我们看到,找到的是如果你还记得,那是一个布尔函数, 所以这实际上是一种回馈给我们。 然后,我在这里表示,我们发现, 然后我们也查找。 但记得也有此抓取功能 这似乎并不被称为主, 这样就意味着其他一些功能的调用抓取, 并通过分配代码,如果你找回来 你看,发现这里是一个使用抓取, 所以后来找到然后还链接抓取, 这是一个布尔值,它返回的东西, 所以我加入另一件事,然后抓取递归 它也回到它自身上循环。 然后,如果你在这里看到我画的图片,我们的程序看起来像什么, 因此,了解某些功能之间的关系, 回到那个你也看到订单的游戏 和逻辑的游戏程序如何继续进行。 我们读过的分布码。 你将要执行的第一个函数, 或要实现的功能之一是画画, 所以在这里你其实有一点点的自由与此有关。 如果我们看一下在工作人员的解决方案 我要打开终端窗口,实际上, pset3/scramble。 从头开始。我想我需要更新我的设备。 如果你玩的工作人员解决方案的争夺, 是在规范的说明是 - 然后你可以看到,他们已经打印出来的游戏板, 但基本上他们做的是,他们把每个字符间的空格, 但你有一点点的自由与此,所以如果你要打印的行,例如, 在他们之间,那么你就可以做到这一点。 你要回想起我们如何遍历一个二维数组的所有元素, 你要打印这些,请确保你有你的循环 您的打印功能,例如,你以正确的顺序打印。 如果你希望你的迭代循环,当你遍历 你使用的指标,确保你以正确的顺序打印。 在第一次处理二维数组可以是一个有点混乱, 这张幻灯片上,我做了一个表,显示你 对于每一个给定的点在二维数组的指标是什么, 因此,如果你想参考此快速检查 或参考或类似的东西,那么你就可以使用此功能。 列是蓝色的,行是红色的。 查找的功能是双重的。 查找 - 这是一个布尔函数会告诉我们 是否真或假的用户提交的字 可以接受作为一个有效的值, 在争夺这么一句话是唯一有效的 如果它在字典中找到,如果它实际上是在董事会, ,所以要记住,你必须实现自己的查询, 所以你要检查两件事, 是否这个词实际上是在字典中,无论是被找到了。 回忆全局变量的字典, 这是一个结构,我们所做的,基本上有一个int大小 与它相关,以及一组字, 字是一个新的数据类型。 因此,为了访问,例如,字典或词语的数组的大小, 然后你可以做什么,只写“dictionary.size, 类似的方式,你会使用任何其他变量。 因此,如果dictionary.size表示的大小的字典, 同样中,dictionary.words代表阵列。 所以,如果你想访问的字典中的某个词, 那么你将不得不增加一个索引 因为你不得不说,“dictionary.words索引i' 然后执行此基础上的东西。 因此,了解该词典具有一定的规模,与之相关联的, 以及一个数组的话,要检查,如果事情是在字典中, 然后,你就必须interate在词典 要检查是否找到这个词。 现在,如果你觉得回到了演讲,当我们谈到不同的方式来搜索物品, 那么请记住,线性搜索,可能并不总是最好的一段路要走。 但是,它绝对是一个寻找的东西。 有时候,你可能会发现,你实现你的查找功能 线性搜索,然后再你的程序会得到休息。 然后,以后你可以回去和改变的方式,你搜索一个字。 所以,铲球 - ,基本上知道 - 知道如何访问 话数组的字典里,想看看铲球 这个词是否是实际在字典或不。 但我们也需要解决这个词是否是在黑板上。 不管是被找到了。 因此,我们已经发现功能,记不清了。 它显示了苏,但一个字是什么? 这是一个哲学问题,而是看的类型定义。 我们有所谓的'发现'和字符数组的一个布尔值, 代表该字。 所以,当你返回查询,你会想,以检查是否这个词已经被发现或没有。 现在,知道的布尔发现 - 发现是名称的布尔 相关的每一个字 - 然后你会如何访问该变量, 回想起我们如何访问内的变量字典吗? 所以在这里我们有字典,然后我们说点的大小,对吗? 同样,当我们有一个词,在这种情况下,要小心,因为 字是任何其他的数据类型,如int或一个字符串。 所以,你不能只是说“字”,除非这就是它的名字。 你将有一个变量的名称,然后一旦你有, 说,名为foo,例如,你可以说:“foo.found, 将返回您是否这个词已被发现或没有的布尔值。 那么,在pset的下一个部分,是落实争夺, 据此,每当用户输入的争夺 - 这是已经处理 在这里分配代码 ​​- 你只需要实现 争夺战已指示你到90°顺时针旋转板的功能。 根据该规范,指示说,董事会90°顺时针旋转 使得在网格的值[0] [0],然后移动到网格[0] [维度-1。] 在这种情况下,加扰,我们尺寸是4,所以0-0,然后将映射到0-3。 让我们明确这一点,看看它可能看起来像。 我不会做一个4×4格,而是一个3×3 1。 比方说,这是一英寸的二维数组。 我只是,只是有 - 所有权利。 所以说,我们要争夺此,我们要旋转90°顺时针。 我们知道,作为起点,该值在0-0,其中在这种情况下,是数字0, 映射到0行,列维度-1。 所以,在这种情况下,尺寸是3。 那么将移动到第0行,第2列。 因此,我们必须有编号为0。 本质上我们正在做的是,我们正在做这个, 身体转动,然后2到这个角落, 8,然后去这个角落,6到这一个。 然后其余的样子 - 所以这是一个的网格看起来像当你已经成功地炒什么。 当你实施的加扰功能,你会想要做什么 是看,好了,怎么能替换这些值吗? 是否有某种模式或某种公式来确定 在一个特定的指数呢? 例如,我可能会看一下3-4-5这里是一排。 我在别的地方见3-4-5? 嗯,我看到它在这里。 同样,我看到6-7-8一排,但它实际上是一个列在这里。 这就是模式,我现在看到的,但也有可能是一些其他的。 在此基础上,认为某种模式,某种方式。 一旦你确定了一个,那么你将要重置的值在网格中。 因此,格0-0将成为6,网格0-1将成为3。 但请记住,您将会 - 例如,如果你马上复位, 说0-2格变为0,然后你失去2。 所以回想起来,这是不够的,只是重新分配。 您可能会想要做的东西的临时副本 在你真正把它放在正确的地方。 的最后一件事情就是执行不区分大小写。 如果你回顾一下,搜索到的点在规范中,当用户输入一个字符串。 如果你还记得,回想起 - 哦,我删掉了地图。 如果你认为你的程序的地图,这是在主要功能, 所以看你处理用户输入的字符串, 然后在那里,想从你的工具,你 加密的pset,PSET 2,然后,你可能会想办法能 允许用户输入大小写混合的。 因此,他们可能转换为大写和小写字母的组合,但应该仍然是有效的。 在词典中,记得当我们打开这个文件,每一个字存储的所有大写字母。 但是,我们不希望用户必须输入大写所有的时间。 任何人都可以想办法,我们也许能够让用户, 即使他们输入全部小写,例如?是吗? [学生]:你可以把它向上吗? 是的,没错。你可以把它向上。 所以,你可以把所有的字母为大写,然后 这样,你保证,这将是一个精确副本 凡是在字典中找到的,如果它在字典中。 大。我们有一点点的剩余时间。 因此,一些事情,你可能会遇到在此pset的是需要知道的 你的变量是在一个特定的时间点。 因为我们在规范中有明确的功能,基本上 清除不管你在黑板上画了,除去这一切,然后重写最重要的是, 你写你的pset时,你可能不是真的想这样的事情发生。 好了,因为你将要看到的,有一次我在此争夺,例如, 一旦我进入争夺战,它做的,到底是什么之前,仅作参考。 那么你可能想要做的是回到您的主要功能 和评论,例如。 那么,当你下一次运行你的程序, 你的程序将不会清除它来代替,而将只保留最重要的是打印的。 还有一些其他的方法来调试以及。 你可以做的是,你可以有打印f报表的,我想。 有一件事,我看到了我分级在pset是包括人类在内的打印f报表的 打印出时间跟踪,在某一点上的变量。 但只是确保结束时,一旦你已经写完了所有打印f报表 为您跟踪的东西,你对此有何评论出来后, 或将其删除,一旦你已经完成了。 这是另一种方式,你可以做的东西,你可以只写在打印f声明 的地方,相关的和看到的,基于终端打印出, 该变量是什么。 另一种方式来做到这一点,我们将进入更详细的演讲, 是GDB,这是一个调试工具。 从本质上讲,当你运行它,它会进入你的程序,你可以把它推进 一个单一的步骤,而不是评价一切的时间。 那么你可以打破它成小步骤,然后根据的道路上 - 前进的道路上打印的东西,看到的值是什么。 这可以帮助你找出你的代码中的错误可能。 我们可以做的事情是编写一个简单的函数,然后 看看我们如何能够使用GDB来看看是怎么回事。 因此,让我们有一个int主,然后作为主要的参数,我们有什么? 我们有int参数c和String参数诉 我要保存在演练GDB.z.好的。 我将返回0。 因此,如何对我们的只是有一个简单的for循环,让我们有12个。 让我们也有一个int计数器和 我们就可以开始为0。好吧。 因此,在for循环中的每一个点,让我们说,我们要增加计数器 它乘以不管我是。 这是一个很短的功能。 让我们GDB。哦!然后 - 铛是聪明的。 告诉我,我并没有包括cs50.h. 好的。所以,现在我们要 - 事实上,对不起你们。我要重命名的文件,只是因为它是一个有点混乱。 好的。所以,现在我们想要做的是,我们要开始GDB。 我说:'GDB调试,所以基本上它会被设置为专注于这个调试, 调试文件。 我打算把一个断点。 本质上,该程序正在运行,直到它击中在一定的断点。 我去说破的主要功能。 所以我现在要运行调试;,所以GDB里,我可以运行的代码。 它的运行程序,虽然主要是我们写的第一件事情之一, 我们也有包含文件的东西上已经。 它主要的断点。 比方说,“下一个”,所以我们可以继续。 它说:“int计数器= 0。” 我会说'打印计数器“。 这很奇怪。所以,基本上我们希望计数器为0, 但GDB是退一万步,所以每当你说下, 它说,int计数器= 0。这是未来的事情,它的执行。 然后你按一下 - 你可以再次说下,或者你可以说'N, 现在如果打印计数器,计数器为0,因为我们的期望。 从根本上说,它创建了它自己的一种变量,但无论是有 - 想在这里;该计数器代表什么。 所以,我要点击“下一步,我想知道我是什么。 你会打印我,我是0,因为我们的期望。 接下来,再次,它表示,它的通过再次循环, 因此,如果我打印我,比如,我可以看到我们的 - 我目前是1。 所以这是一个办法,如果你设置一个断点,在一个特定的功能 然后继续去下,然后检查我是什么, 如果你有一个猜测,也许某处的东西,因为它没有发生, 你怀疑,也许这是在第一个索引或最后一个索引或东西, 你可以使用GDB,继续打印I,能够检查这些价值观是什么。 那么,在GDB,因为打印,其次是常见的参数, 常用的命令,就像我简写下到n, 我也可以简单地说P计数器,这仍然是0。 然后我点击下一步。我想再次打印计数器。 好了,所以这仍然是0。 你种想知道的 - 嗯,我想计数器是一个阶乘函数。 - 只是在调试技术 - 为什么会是什么? 为什么计数器不增加它的价值吗? 为什么会住在0? 好,我在这里 - 早在这里,我说的计数器,计数器x我。 那么,如果我回到我的功能开始, 我看到,当我印我,我是0,什么是0×什么? 这是0,对不对?所以这是可能的原因为何计数器 永远不会被任何其他的号码。 那么我可能想要做的是回到我的机能的, 说,好吧,好吧,事实上,我想在1开始。 要解决的事情吗? 不太,因为这里仍然是0计数器。 因此,让我们设置为1。 我们要重设我们的调试工具,让我们退出。 然后,我们可以做的是,我们可以GDB调试, 将在主休息,然后重新运行调试,下一个,下一个,下一个。 让我们打下了几下,然后我们将打印计数器,看到 - 我们没有正确的文件。 即使我们改变的源代码,然后我们 没有更新我们的可执行文件。 我相信,你可以做 - 是的。 在GDB本身,你确实可以让文件。 所以,你不必退出GDB再次。 你可以回去的源文件,将其保存在GDB,你可以把它。 大。因此,让我们运行调试。 我们要开始它从一开始,因为我们有一个新的可执行文件。 我们可以通过几次,然后打印我,打印计数器,继续。 好的。所以,现在我们看到,计​​数器实际上是增加它的价值,因为我们希望它。 这只是一个小小的一口大小的例子,你会如何使用GDB 输入您的密码,打印特定的值,单击下一步继续到下一行, 和缩写,并打印出来。 显然,在争夺的代码是一个比较复杂的多,但你可以做什么 设置一个断点 - 在您的查找功能,类似的东西,你可以设置一个断点。 因此,一旦它到达的地步,它需要寻找的东西, 然后GDB运行一切到这一点,那么你就可以开始打印的值。 一样是在这一点上假的标志,是真的吗? 这可能是东西,你可能要使用。 GDB,不强调太多, 因为我们将进入更详细的演讲, 但我只想让你们知道,你可能能够使用它 如果你开始在pset,并希望了解 一个更好的办法,只是把打印f报表的,乱抛垃圾全部通过你的代码。 有GDB打印它,可以设置这些断点 让你的程序可以运行,直到某一点 让您真正踏进去,并找出问题。 右。那么,如果我们回头看的争夺,我们读过的分布码。 我们已经谈论的方式来遍历二维数组,你一定会 是要遍历二维数组,当你来绘制你的游戏的网格。 我们谈论的查找功能,我们要如何确保一对夫妇的事情。 我们要确保,我们没有到过这个词之前。 我们也希望,以确保它实际上是在字典中。 然后,我们谈到争夺战,我们要如何旋转板。 知道你可能想要的东西副本 是能够将其移动。 最后,我们谈到的情况下和敏感性,要确保你如何 尽管任何相结合的情况下,用户输入, 如果它是一个有效的字在字典中, 那么它会正确地找到。 那么,一起争夺pset的,那就是演练3。 谢谢大家的到来,祝你好运与争夺。 CS50.TV