【CS 61B】Data Structures, Spring 2021 -- Week 1(1. Intro and 2. Classes, Lists, Arrays, Maps)

目录

61B 2023 Lecture 1

1、[Intro1, Video 1a] Welcome to 61B, Spring 2023!

1.1 61B Overview

2、[Intro1, Video 1b] 61B Logistics

2.1、Course Components

2.2 Class Phase

3、[Intro1, Video 1C] Phase 1 Overview

4、[Intro1, Video 2A] Hello World

5、[Intro1, Video 2B] Static Typing(静态类型)

6、[Intro1, Video 2C] Declaring Functions(声明一个方法)

7、[Intro, Video 2D] Reflections on Java(小结)

7.1、Java与面向对象

7.2、Java与静态属性

7.3 本周任务

8、[Intro1, Video 3a] Compilation(代码编写)

9、[Intro1, Video 3b] IntelliJ Demo(IDE - IntelliJ IDEA)

10、[Intro1, Video 3c] HW0A Due Friday(作业)

10.1 Self-Check 1.26: Confusing

10.2 Exercise 2.5: starTriangle

10.3 Self-Check 2.25: numberTotal

10.4 Exercise 3.23: printIndexed or Exercise 4.17: stutter

10.5 Self-Check 4.5: ifElseMystery1

10.6 Exercise 4.19: quadrant(象限)

61B 2023 Lecture 2 - Classes, Lists, Arrays, Maps

Part 1: Classes in Java

1、Defining and Instantiating Classes

1.1 Object Instantiation(对象实例化)

1.2 Construct(构造方法)

2、Defining a Typical Class(Terminology)定义典型类

2.1 Instantiating a Class (实例化一个类)

3、Static vs. Non-Static (静态与非静态)

3.1 Why Static Methods?(为什么是静态方法?)

3.2 Static Variables (静态变量)

Part 2: Lists, Arrays, and Maps

1、Lists in Java 4.0 (有序列表)

2、Abstract Data Types vs. Concrete Implementations (抽象数据类型)

3、Modern Java Lists

4、Arrays

5、Maps

Part 3:Summary

Part 4:Lab & Assignments/Exams

1、HW 0B: A Java Crash Course (Part 2)

2、Lab 1.1 : Setting Up Your Computer(实验环境配置)

A. 安装 Java

B. 安装 Git

C. 安装 Windows 终端(可选,但推荐)

3、Lab 1.2 : IntelliJ, Java, git

A、工具准备

B、环境搭建

4、Project 0: 2048

A、emptySpaceExists

B、maxTileExists

C、atLeastOneMoveExists

D、tilt(Main Task


目前 CS 61B 已经更新到了 Spring 2023,但提供给旁听生的自动评分器的最新版本仅支持到 Spring 2021,而且 Spring 2021 的自动评分器也只提供到今年的年底,属于是且用且珍惜。所以本章的内容主要是 Spring 2023的 Week 1 内容,但实验和项目做的是 Spring 2021的,后续的学习应该也会换成 Spring 2021,不然做了作业测试不了对错也挺难受的。不过跟着 Spring 2023 了解一下最新的讲解也还是挺不错的。

另外,不吹不黑,CS 61B不愧是一代神课,除了英文授课造成一点点困扰外,其它的都挺好的,尤其是自动评分机制,能很清楚的看出自己错在哪,而且给出的骨架代码也都具有测试用例,比国内的基础课要好太多了!

CS 61B数据结构,2021 年春季: Main | CS 61B Spring 2021开放了自动评分器

CS 61B数据结构,2023 年春季: Main | CS 61B Spring 2023 (未开放自动评分器)

【配套参考书📕】Hug61B Spring 2019 Edition: 1.1 Essentials · Hug61Bhttps://joshhug.gitbooks.io/hug61b/content/chap1/chap11.html

Week1 课程安排:

61B 2023 Lecture 1

1、[Intro1, Video 1a] Welcome to 61B, Spring 2023!

1.1 61B Overview

让代码更有效率

2、[Intro1, Video 1b] 61B Logistics

2.1、Course Components

2.2 Class Phase

3、[Intro1, Video 1C] Phase 1 Overview

4、[Intro1, Video 2A] Hello World

5、[Intro1, Video 2B] Static Typing(静态类型)

6、[Intro1, Video 2C] Declaring Functions(声明一个方法)

1、记得写注释,格式:/** */

2、函数声明方法

7、[Intro, Video 2D] Reflections on Java(小结)

7.1、Java与面向对象

7.2、Java与静态属性

7.2.1 什么是Static Typing

Static Typing:静态类型,每个变量、参数和函数都有一个声明的类型,使其更容易让程序员理解和推理代码,这称为静态类型。

7.2.2 Static Typing的优缺点

7.3 本周任务

下一课中,将讨论一些关于 public static xxx 的实际含义,并进行深入了解

8、[Intro1, Video 3a] Compilation(代码编写)

compile:javac HelloWorld.java -> HelloWorld.class

running: java HellloWorld -> Hello World!

想要了解编译器的确切工作方式的话可以查看:CS 61C 以及 CS 164

9、[Intro1, Video 3b] IntelliJ Demo(IDE - IntelliJ IDEA)

10、[Intro1, Video 3c] HW0A Due Friday(作业)

作业链接🔗:HW 0A: A Java Crash Course (Part 1) | CS 61B Spring 2023

10.1 Self-Check 1.26: Confusing

10.2 Exercise 2.5: starTriangle

10.3 Self-Check 2.25: numberTotal

10.4 Exercise 3.23: printIndexed or Exercise 4.17: stutter

10.5 Self-Check 4.5: ifElseMystery1

10.6 Exercise 4.19: quadrant(象限)

61B 2023 Lecture 2 - Classes, Lists, Arrays, Maps

Part 1: Classes in Java

1、Defining and Instantiating Classes

instantiation:实例化

在Java中,因为所有的代码都是类的一部分,所以所有的函数都是方法

虽然所有想要运行的代码要位于public static void main(String[] args)方法内部,但并不是所有类中都要有一个Main方法

IDEA中快速生成Main方法的快捷语句:psvm or main

1.1 Object Instantiation(对象实例化)

类可以实例化,实例可以保存数据

为 Dog Class 添加 size 属性

示例代码:

DogLauncher: 不为 size 赋值,则默认为0

1.2 Construct(构造方法)

示例代码:

2、Defining a Typical Class(Terminology)定义典型类

类中的实例变量要严格按照 blueprint 中的来,不能自己在外部添加

2.1 Instantiating a Class (实例化一个类)

3、Static vs. Non-Static (静态与非静态)

静态方法使用类名调用;

非静态方法使用实例后的对象名调用;

静态方法不能访问非静态的实例变量;

3.1 Why Static Methods?(为什么是静态方法?)

示例代码:

3.2 Static Variables (静态变量)

你应该选择使用类名去访问类变量,而不是使用一个实例对象名

定义在类中的方法或变量可以被成为成员方法或变量;

静态成员可以直接使用类名访问;

非静态成员则不能通过类名调用;(这和Static的加载机制有关)

静态方法必须通过一个特定的实例来访问实例变量。

Part 2: Lists, Arrays, and Maps

1、Lists in Java 4.0 (有序列表)

2、Abstract Data Types vs. Concrete Implementations (抽象数据类型)

一个抽象数据类型为什么要有多个具体的实现?

3、Modern Java Lists

使用泛型增加限制,否则就会像在Java 4.0 中的List一样,无法将从List中检索的数据分配给变量

4、Arrays

5、Maps

示例代码:

Part 3:Summary

最常见的Map的实现是 TreeMap HashMap

下节课的内容是:深入理解研究 LinkedLists 和 ArrayLists之间的区别

大约在课程的第7周,我们将讨论 TreeMaps 和 HashMaps

Part 4:Lab & Assignments/Exams

1、HW 0B: A Java Crash Course (Part 2)

2、Lab 1.1 : Setting Up Your Computer(实验环境配置)

A. 安装 Java

B. 安装 Git

C. 安装 Windows 终端(可选,但推荐)

1、打开 Windows Terminal 的配置文件 settings.json

2、在其中添加以下内容,注意路径要改成自己的:

3、修改“+”的默认配置,使其默认打开的是 git bash:

3、Lab 1.2 : IntelliJ, Java, git

配置GitHub环境,以链接 Gradescope 实现自动评分

A、工具准备

GitHub Desktop:(非必须)

GithubDesktopZhTool:(汉化工具),傻瓜式一键汉化

推荐使用 GitHub Desktop 方法直接通过 GUI 来操作文件的上传, 不推荐下面环境搭建中使用 git 命令的方法(不过你要是想要练习一下 git 倒是可以尝试练习一下,但完全属于是可以,但没必要)
CS61B Autograder终极排坑https://zhuanlan.zhihu.com/p/344813657

B、环境搭建

1、在 GitHub 网站中完成仓库创建:

  

2、在本地创建一个文件夹 CS61B ,并将创建好的远程仓库 clone 到本地:

git clone https://github.com/panda-tang/cs61b.git

长时间未验证,会提示验证,我们选择 code 验证即可:(主要是有时候选择浏览器验证,但是浏览器不弹出)

完成验证:

遇到的问题与解决方法:

Problem 1: OpenSSL SSL_read: Connection was reset, errno 10054

Solution:git config --global http.sslVerify "false"

Problem 2: Failed to connect to github.com port 443 after 21059 ms: Timed out

Solution:设置全局代理,再取消

git config --global http.proxy http://127.0.0.1:1080

git config --global http.proxy http://127.0.0.1:1080

git config --global --unset http.proxy

git config --global --unset https.proxy

3、将远程的 sp21初始实验代码仓库 pull 到本地仓库:

cd cs61b

git remote add skeleton GitHub - Berkeley-CS61B/skeleton-sp21: starter code for spring 21

git pull skeleton master

遇到的问题与解决方法:

Problem 1:fatal: refusing to merge unrelated histories

Solution:git pull --rebase --allow-unrelated-histories skeleton master

Problem 2:fatal: not a git repository (or any of the parent directories): .git

Solution:git init

4、配置环境变量 REPO_DIR

5、提交第一个lab

git add lab1/*

git commit -m "completed first part of lab1"

git branch -M main

git push -u origin main

6、到Gradescope中链接你的GitHub账户,选择提交:

到此结束:

4、Project 0: 2048

在这个项目中,你将构建这个游戏的核心逻辑。也就是说,我们已经将所有GUI代码、处理按键和大量其他脚手架组合在一起。你的工作将是做最重要和最有趣的部分。

游戏本身非常简单。它是在一个 4 x 4 的方格中进行的,每个方格可以是空的,也可以包含一个大于或等于2的2次方的整数。在第一次移动之前,应用程序将包含2或4的贴图添加到最初空棋盘上的随机方格中。选择2或4是随机的,选择2的概率是75%,选择4的概率是25%。

然后玩家通过方向键选择方向来倾斜棋盘:北、南、东或西。所有贴图都朝那个方向滑动,直到移动方向上没有剩余空间。一个贴图可以与另一个贴图合并,从而为玩家赢得积分。

A、emptySpaceExists

你在这个项目中的工作是修改和完成模型类,特别是 emptySpaceExistsmaxTileExistsatLeastOneMoveExiststilt 方法。其他的都已经为你实现了。我们建议按照这个顺序完成它们。前两个是相对简单的。第三个(atLeastOneMoveExists)比较难,而最后的 tilt 方法可能相当困难。我们预计倾斜将花费你3到10个小时来完成。前三个方法将处理游戏结束的条件,而最后的 tilt 方法将在用户按键后修改棋盘。你可以阅读checkGameOver 方法的非常简短的正文,以了解你的方法将如何被用来检查游戏是否结束。

让我们先看一下前三种方法:

①、需求分析

public static boolean emptySpaceExists(Board b):

如果给定的棋盘中的任何一块瓷砖(tiles)为空,该方法应返回true。在这个项目中,你不应该以任何方式修改Board.java文件。对于这个方法,你要使用Board类的tile(int col, int row)和size()方法。其他方法没有必要。

Note:我们在设计Board类时使用了一个特殊的关键字private,不允许你直接使用Board的实例变量。例如,如果你试图访问b.values[0][0],这将不会起作用。这是件好事! 它迫使你学会使用 tile 方法,你将在整个项目的其余部分使用它。

尝试打开 TestEmptySpace.java 文件夹。运行这些测试。你应该看到,6个测试失败,2个通过。在你正确编写了emptySpaceExists方法后,TestEmptySpace的8个测试都应该通过。

Quick Overview(Video):Proj 0 - emptySpaceExists

②、代码实现

Solution:

Test:

B、maxTileExists

①、需求分析

public static boolean maxTileExists(Board b)

如果棋盘中的任何一张牌等于获胜的牌值 2048,这个方法应该返回真。请注意,与其在代码中硬编码2048这个常数,不如使用 MAX_PIECE,这是一个属于Model类的常数。换句话说,你不应该做if (x == 2048),而应该做if (x == MAX_PIECE)。

留下像2048这样的硬编码数字是一种不好的编程实践,有时被称为 "神奇数字"。这种神奇的数字的危险在于,如果你在代码的一个部分改变了它们,而在另一个部分没有改变,你可能会得到意想不到的结果。通过使用像MAX_PIECE这样的变量,你可以确保它们都被一起改变。

在你写完这个方法后,TestMaxTileExists.java中 的测试应该通过。

②、代码实现

Solution:(基本上同上面的 emptySpaceExists 方法一致,但由于当矩阵中的值为0时,会返回空,所以在这里我们加入了一个非空判断,否则就会出现异常提示)

Cannot invoke "game2048.Tile.value()" because the return value of "game2048.Board.tile(int, int)" is null

Test:

C、atLeastOneMoveExists

①、需求分析

public static boolean atLeastOneMoveExists(Board b)

这个方法更具挑战性。如果有任何有效的移动,它应该返回true。我们所说的 "有效移动 "是指,如果用户在玩2048游戏时可以按一个按钮(向上、向下、向左或向右),导致至少一个瓷砖移动,那么这样的按键就被认为是有效移动。

有两种方法可以产生有效的移动:

  1. 棋盘上至少有一个空位。
  2. 有两个相邻的牌具有相同的价值。

例如,对于下面的棋盘,我们应该返回 true,因为至少有一个空位。

|   2|    |   2|    |

|   4|   4|   2|   2|

|    |   4|    |    |

|   2|   4|   4|   8|

对于下面这个棋盘,我们应该返回 false。在2048中,无论你按什么按钮,都不会发生任何事情,也就是说,没有两个相邻的牌的数值相等。

|   2|   4|   2|   4|

|  16|   2|   4|   2|

|   2|   4|   2|   4|

|   4|   2|   4|   2|

对于下面的棋盘,我们将返回 true,因为向右或向左移动将合并这两张64张牌,向上或向下移动也将合并这32张牌。或者换句话说,至少有两块相邻的牌有相同的价值。

|   2|   4|  64|  64|

|  16|   2|   4|   8|

|   2|   4|   2|  32|

|   4|   2|   4|  32|

在你写完这个方法后,TestAtLeastOneMoveExists.java 中的测试应该通过。

②、代码实现

Solution:该方法可以通过如下方式解决,对除最后一行外的所有元素进行向上检查,以及对除最后一列外的所有元素进行向右检查,这种方法虽然便于操作,但会造成资源浪费,因为相当于多循环遍历了一次。

除此之外,我们可以通过另一种方式完成一次遍历,降低重复。我们可以通过控制边界,在一次遍历中同时完成向上和向右的检查,然后再分别对没有检查到的边界元素进行单独的向上或向右检查,从而保证所有的元素都被检查过。

Test

D、tilt(Main Task)

①、需求分析

public boolean tilt(Side side):

tilt 方法做的是实际移动所有 tiles 的工作。例如,如果我们有一个 board,它是由以下内容组成的:

|   2|    |   2|    |

|   4|   4|   2|   2|

|    |   4|    |    |

|   2|   4|   4|   8|

press up,tilt 将修改 board 这个实例变量,使游戏的状态变为现在:

|   2|   8|   4|   2|

|   4|   4|   4|   8|

|   2|    |    |    |

|    |    |    |    |

除了修改 board 之外,还必须发生另外两件事:

  1. score 实例变量必须被更新,以反映所有 tile 合并的总价值(如果有的话)。在上面的例子中,我们将两个4合并为8,两个2合并为4,所以分数应该增加 8+4=12。
  2. 如果 board 有任何变化,我们必须将局部变量 changed 设置为 true。这是因为在 tilt 的骨架代码的最后,你可以看到我们调用了一个 setChanged() 方法:这通知GUI有东西要画。而你自己则不需要对setChanged 进行任何调用:只是修改局部变量 changed 即可。

board 上所有 tiles 的移动都必须使用 Board 类提供的 move 方法完成。棋盘上的所有 tiles 都必须使用Board 类提供的 tile 方法来访问。由于GUI实现中的一些细节,每次调用 tile 时,你只能在给定的tile上调用move方法一次。我们将在本文档的 Tips 部分进一步讨论这个限制条件。

Quick Overview:Project 0 - The Tilt method

Tips:

我们强烈建议开始时只考虑向上的方向,即当提供的 side 参数等于 Side.NORTH 时。为了支持你这样做,我们提供了一个TestUpOnly类,它有四个测试:testUpNoMerge, testUpBasicMerge, testUpTripleMerge, and testUpTrickyMerge。你会注意到,这些测试只涉及到一个单一的上移。

在考虑如何实施上升方向时,请考虑以下几点:

在某一列中,最上面一行(第3行)的棋子保持不动。如果上面的空间是空的,第2行的棋子可以向上移动,如果上面的空间与自己的值相同,它也可以向上移动一个。换句话说,在迭代行的时候,从第3行开始向下迭代是安全的,因为 tile 不可能在移动过一次后还得再移动。

虽然这听起来并不难,但它确实很难。要准备好拿出记事本,写出一堆的例子。力求代码优雅,尽管在这个问题上很难做到优雅。我们强烈建议创建一个或多个辅助方法来保持你的代码简洁。例如,你可以有一个辅助函数来处理棋盘的单列,因为每列都是独立处理的。或者你可能有一个辅助函数,可以返回一个所需的行值。

提醒你: 你应该只在一个给定的tile上调用一次 move方法。换句话说,假设你有下面的 board,并press up。

|    |    |    |    |

|    |    |    |    |

|    |    |    |    |

|    |    |    |   2|

我们可以通过以下方式来实现这一目标:

Tile t = board.tile(3, 0)

board.move(3, 1, t);

board.move(3, 2, t);

board.move(3, 3, t);

setChanged();

return true;

然而,GUI会感到困惑,因为同一块 tile 不应该只通过调用setChanged来多次移动。相反,你需要通过一次调用move 来完成整个移动,例如

Tile t = board.tile(3, 0)

board.move(3, 3, t);

从某种意义上说,最难的部分是弄清楚每块 tile 应该在哪一行结束。

为了测试你的理解,你应该完成这个 Google Form quiz。这个测验(以及下面的测验)是完全可选的(即没有评分),但强烈建议你这样做,因为它可以发现你对游戏机制可能存在的任何概念性误解。你可以尝试这个测验,只要你愿意,次数不限。(主要的核心就是:每当你想要移动 tile 的时候需要先获取到你想要移动的那个tile)

要知道什么时候应该更新score,请注意,如果将tile t 移动到c列和r行会替换现有的tile(即你有一个合并操作),board.move(c, r, t)方法会返回true。

更糟糕的是,即使在你获得了向上方向的 tilt 工作后,你还必须对其他三个方向做同样的事情。如果你天真地这么做,你会得到很多重复的、稍加修改的代码,并且有很大的可能引入不明显的错误。

对于这个问题,我们已经赠送了一个干净的解决方案。这将允许你只用两行额外的代码就能处理其他三个方向的问题! 具体来说,Board 类有一个 setViewingPerspective(Side s) 函数,它将改变 tile 和 move 类的行为,使它们的行为如同给定的一面 NORTH 一样。

例如,考虑下面的board:

|    |    |    |    |

|  16|    |  16|    |

|    |    |    |    |

|    |    |    |   2|

如果我们调用 board.tile(0, 2),我们会得到16,因为16在第0列第2行。 如果我们调用board.setViewingPerspective(s),其中s是 WEST,那么board将表现为 WEST 是 NORTH,即你的头向左转90度,如下所示:

|    |    |  16|    |

|    |    |    |    |

|    |    |  16|    |

|   2|    |    |    |

换句话说,我们之前的16将在board.tile(2, 3)处。如果我们调用board.tilt(Side.NORTH),并适当实现tilt,board 将变成:

|   2|    |  32|    |

|    |    |    |    |

|    |    |    |    |

|    |    |    |    |

为了让棋盘回到最初的观察视角,我们只需调用board.setViewingPerspective(Side.NORTH),这将使board表现得如同NORTH原来的样子。如果我们这样做,board现在就会表现得像原来一样:

|    |    |    |    |

|  32|    |    |    |

|    |    |    |    |

|   2|    |    |    |

观察一下,这和你把原来 board 上的 tiles 滑向西边(WEST)的情况是一样的。

重要提示:在你完成对 tilt 的调用之前,请确保使用board.setViewingPerpsective将视角设回Side.NORTH,否则会发生奇怪的事情。

为了测试你的理解,请尝试第三个也是最后一个 Google Form quiz。你可以随心所欲地尝试这个小测验,次数不限。

Q & A

Problem 1:why I code the same as Prof. Hug but when I press the up or down, nothing happens

Solution:修改 GUISource 类中的 getKey() 方法,将 switch … case 中的↑改成中文的"向上箭头",以此类推,或者我们可以在下方位置处写一个sout,打印看一下自己的按键输出是什么,然后改成对应的即可:

②、代码实现

First Commit

修改后 Second Commit:Success!

Final Code

首先定义了一个方法 colFirstElement,因为我们是从第3行开始向下遍历的,所以这里返回的当前元素下第一个不为 null 的 tile。

然后遍历 board 中的每一个 tile:判断 cur 与 next 的各种状态,并进行相应的合并或移动操作。

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
cs61b spring18是伯克利大学的一门计算机科学课程,是基于Java编程语言的数据结构和算法的进阶课程。对于学习者来说,有一些资源是可以帮助他们更好地理解和掌握这门课程的。 首先是课程网站,学生可以在伯克利大学的网站上找到cs61b spring18的课程页面,其中包含课程信息、课程教材、作业和项目说明等。这个页面非常详细,学生可以从中获取到所有关于这门课程的信息。 其次,教师提供了讲座的视频录像,学生可以通过观看这些录像来学习课程中的知识。这些录像可以在课程网站上找到并随时观看。教师在讲解知识时会结合具体的实例和代码,在给学生提供理论知识的同时,也给出了实践的操作方法。 此外,课程网站上还提供了课程讲义和课程作业的解答。学生可以下载这些讲义并进行学习,同时可以参考作业的解答来巩固和理解课程的概念和知识。 最后,在线论坛是一个很有用的资源。课程网站还提供了一个在线论坛,学生可以在这里与其他学生进行讨论和交流。他们可以分享问题和解决方案,互相帮助和支持。 总的来说,cs61b spring18的学习资源非常丰富,学生可以通过课程网站、讲座录像、讲义、作业解答和在线论坛等多种方式来学习和理解课程中的知识。这些资源旨在帮助学生更好地掌握数据结构和算法的概念和实践。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TomLazy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值