Skip to main content

Lab 10 Tetris

常见问题解答

每个作业顶部都会链接常见问题解答。您也可以通过在URL末尾添加“/faq”来访问。实验10的常见问题解答请见此处

介绍

本实验将帮助您入门项目的第二阶段:交互性。我们不要求您在进行本实验时已完成第一阶段。如果您尚未开始,我们强烈建议您尽快开始!

在本实验中,您应该考虑如何将一些想法(或实现!)应用到项目3中。 这也将帮助您更好地熟悉项目所需的实用工具。

danger

本实验有很多辅助方法 - 您无需了解每个方法的作用,但请注意,在实验过程中您可能需要调用其中的一些方法。最终您还会用到库中的方法。请务必通读这些文件以了解您正在使用的内容! 请注意,坐标 (0, 0) 代表棋盘的左下角。

俄罗斯方块

为了让您更好地制作游戏,我们将以俄罗斯方块为例!如果您对俄罗斯方块不太熟悉,它是一款益智游戏,玩家通过移动、旋转从上方落下的不同形状的方块(称为俄罗斯方块)来“消除”线条。玩家可以根据需要移动和旋转方块来消除线条;每消除一行,玩家就能获得积分。当未清除的线条到达棋盘顶部时,游戏结束。

您的所有代码都将在 Tetris.java 文件中实现。我们还提供了其他三个文件:

  • Tetromino.java:包含您将使用的棋盘方块
  • Movement.java:包含旋转和移动方块的逻辑
  • BagRandomizer.java:帮助随机化生成的方块

您无需直接修改这三个文件,但 Tetris.java 中会用到这些类。我们还会使用 StdDraw 库来实现用户输入等功能。您会发现此库对于项目 3 非常有用。

虽然我们的目标是完成一个可运行的 Tetris.java 游戏,但应该将其分解为更小的步骤,循序渐进。游戏大致可以分为以下几个步骤:

  1. 创建游戏窗口。
  2. 随机生成一个方块供玩家控制,并实时显示当前分数。
  3. 根据玩家的输入更新方块的移动。
  4. 一旦方块无法移动,检查是否需要消除任何线条,更新分数并生成新的方块。
  5. 重复步骤 2-4,直到游戏结束(当未清除的线条到达顶部时)。

总的来说,良好的编程习惯是先编写具有明确功能的小程序,再利用这些小程序构建更复杂的方法。查看 Tetris.java 文件,您会发现其中包含许多辅助方法,用于构建更复杂的游戏机制。强烈建议您在项目3中也采用这种方式,将游戏逻辑分解为单独的方法。这样做能为您提供清晰的开发思路,也更容易对逻辑进行单元测试。

完成本实验后,您将得到如下效果:

俄罗斯方块游戏示例

如果您想亲自体验这款游戏,请点击这里

StdDraw

正如之前提到的,我们将使用 StdDraw 库。StdDraw 是一个已经提供的库,它提供了一些基本功能,例如在程序中创建绘图以及获取用户输入。开始之前,请务必查阅 API。您会发现其中的一些方法不仅对本次实验,对 Project 3 也很有帮助。

运行游戏

要运行游戏,请运行 Tetris.java 中的 main 方法。目前,运行后应该只会显示一个黑色方框。随着您实现更多方法,您可以使用此方法来验证游戏逻辑的正确性。

方法概述

因为所有的代码实现都在 Tetris.java 文件中,所以你需要完成一些方法才能使游戏正常运行。

info

正如之前提到的,请务必仔细阅读 Tetris.javaTetromino.javaMovement.java 这几个文件,以便熟悉本次实验中提供的辅助方法。虽然您不一定需要了解每个辅助方法的工作原理(抽象!),但它们中的一些方法很可能对您的实现有所帮助,因此请仔细阅读它们,以便您了解有哪些方法可供您使用。

updateBoard

这个方法会根据用户的输入来更新棋盘状态。第一步是检查用户是否输入了任何内容,如果用户输入了,则获取输入。StdDraw API 中有一些方法对于实现实验的这一部分很有用。考虑查看 hasNextKeyTypednextKeyTyped

接下来,你需要实现当用户按下特定按键时所触发的相应操作。用户可以输入 5 个键:

  • a:将当前棋子向左移动一格
  • s:将当前棋子向下移动一格
  • d:将当前棋子向右移动一格
  • q:将当前棋子向左旋转 90 度
  • w:将当前棋子向右旋转 90 度

我们建议您查看 Movement.java 中提供的一些辅助方法,看看您可以调用哪些方法来移动棋子或旋转棋子(你不需要自己实现任何移动的逻辑,而是应该理解并利用这些辅助方法的功能。)。

还为您提供了一个 Movement 实例供您使用。

根据上面的描述填写该方法。再次提醒,请务必仔细阅读 Movement.java 文件和 StdDraw 的 API 文档!

incrementScore

这是一个辅助方法,可帮助更新您的分数。玩家的得分会根据每次消除的行数增加(如果存在消除行的情况)。可以将其分解为以下四种情况:

  • 1:100 分
  • 2:300 分
  • 3:500 分
  • 4:800 分

填写 incrementScore,以便玩家的分数如上所述增加。

clearLines

每当在俄罗斯方块游戏中完成一行时,我们希望更新分数并清除该行。 此方法用于检查放置方块后,是否有一行或多行被水平填满。请考虑以下事项:

  • 因为您不确定具体是哪一行完成了(如果有的话),所以需要检查整个棋盘。
    • 具体来说,我们如何判断一行未完成
  • 找到已完成的行后,就应该清除该行。
    • 清除一行后,需要将该行上面的所有行向下移动。
    • 对于每一条被清除的行,将其数量记录在一个变量中 (linesCleared)。
  • 最后,我们要根据清除的行数更新我们的分数。 建议使用您已经实现的辅助方法来完成这个操作。

请填写 clearLines 方法,检查被清除的行数,并相应地更新棋盘。请注意,棋盘应该作为参数 tiles 传入(如果不这样做,可能会影响自动评分器!)。

runGame

这里是游戏主要逻辑的实现部分。代码框架中已经添加了注释,以帮助您入门。需要注意以下几点:

  • 您需要确保游戏在游戏结束前不会退出或停止(提示:您如何确保这种情况持续发生?)。
  • 如果当前的俄罗斯方块无法向下移动或无法再从其当前位置移动,它将被设置为 null 将方块设置为 null 的逻辑已经完成,您无需关心这部分。
    • 一旦放置了一个方块并且无法再移动,请确保检查是否需要清除任何行并生成另一个方块。
  • 确保根据用户输入更新棋盘,然后渲染这些更改。

以下是一些您可能会用到的辅助方法,以及您已经实现的方法:

  • spawnPiece:在棋盘上生成一个方块,并将当前的俄罗斯方块设置为随机选择的方块
  • isGameOver:检查游戏是否结束
  • clearLines:检查是否需要清除任何行,并根据清除的行数更新分数
    • 确保将棋盘传递到 clearLines
  • updateBoard:检查玩家的移动并根据用户输入更新棋盘
  • renderBoard:渲染棋盘的状态(在用户输入和清除行后调用)

填写 runGame

renderScore

此时,如果您运行游戏,您会注意到缺少一些东西。分数!那是因为我们还没有显示它。填写方法 renderScore,以便显示分数,您可以使用它来验证在游戏中完成行时您的分数是否已正确更新。

以下是步骤:

  • 确保将文本颜色设置为白色(rgb 值为 (255, 255, 255)),以便分数在黑色背景下可见。
  • 分数应出现在位置 x = 7, y = 19。
  • 记得在绘制完成后渲染分数! 以下是一些来自 StdDraw 库的实用方法,您可能会觉得有用(您可能不会用到所有这些方法,但这里提供它们以供参考):
  • StdDraw.setFont
  • StdDraw.clear
  • StdDraw.text
  • StdDraw.setPenColor
  • StdDraw.show
  • StdDraw.pause

填写 renderScore 并运行您的游戏以检查分数是否显示!

提交和评分

本实验的完成情况将部分取决于自动评分器的提交结果以及人工检查。您可以选择在实验室或办公时间进行面对面检查,或者通过Ed平台进行异步检查。

检查时,我们会关注以下几点:

  • 可以使用asd键分别将棋子向左、向下、向右移动,qw键分别控制左右旋转。
  • 按下其他键不应有任何反应(例如,按下h键不应影响游戏界面)。
  • 游戏过程中,分数会持续显示,不会消失。
  • 棋子堆叠或触底时不会穿透。

我们也会检查你的代码实现,请确保你能解释你的思路,以及本次实验的内容如何应用于Project 3的交互性实现。一旦通过检查,将提供一个神奇的词供您填写到您的 magic_word.txt 中,然后您可以提交到 Gradescope。您需要提交神奇的词并通过 Gradescope 上的测试才能获得满分。

再次强调,以下是需要实现的几个函数:

  • updateBoard:根据用户输入更新棋盘
  • incrementScore:根据清除的行数更新分数
  • clearLines:如果行已完成,则清除行
  • runGame:游戏运行的核心逻辑
  • renderScore:显示分数

异步检查

如果选择通过Ed平台进行异步检查,你需要提供屏幕录像。我们建议使用 Zoom 屏幕录像或屏幕录像软件。录像时,请务必显示屏幕键盘。以下是一些屏幕键盘的链接:

  • Mac
  • Windows 请务必回答模板中列出的问题,并请提前规划,因为录制视频和完成checkoff需要一定的时间。

致谢

4 位助教为了创建本实验付出了巨大努力 (Noah Adhikari, Erik Nelson, Omar Yu 和 Jasmine Lin)。