在这个问题中,你需要为俄罗斯方块(Tetris)游戏编写一个简单的 AI。目标很简单:完成至少一行。更具体地说,为了本题的目的,我们按照以下修改后的规则进行游戏:
图 G.1:七种俄罗斯方块的初始方向。
- 游戏区域是一个高 20、宽 10 的网格,初始为空。
- 游戏会逐个向玩家提供随机的俄罗斯方块序列,如图 G.1 所示。游戏使用“袋子随机生成器(bag randomiser)”,即前七个方块各不相同,接下来的七个方块也各不相同,依此类推。
- 玩家可以将每个方块向侧面移动,并按 90 度的倍数进行旋转。这些调整在网格上方进行。
- 随后,方块会落入游戏区域,一旦其某一部分因为被之前的方块阻挡而无法继续下落,它就会锁定在当前位置。在下落过程中,无法对方块进行移动或旋转。
- 当发生以下任一情况时,游戏结束:
- 网格中的某一行被方块完全填满,玩家获胜。
- 某个方块无法完全落入网格内,玩家失败。
交互协议
你的程序将与一个名为 grader 的特殊程序进行交互。这意味着你的程序的输出会被发送给 grader,而 grader 的输出会被发送到你程序的标准输入中。这种交互必须遵循特定的协议:
grader 会重复发送随机方块(见下文说明),用图 G.1 中的大写字母 {I, J, L, O, S, T, Z} 之一表示。对于每个方块,你的程序必须按以下格式回答其期望的放置位置:
- 两个整数 $r$ 和 $x$ ($0 \le r \le 3, 1 \le x \le 10$),其中 $r$ 表示方块应顺时针旋转的次数,$x$ 表示方块所占据的最左侧列(列从左到右编号,从 1 开始)。
grader 随后会相应地旋转并定位方块,并将其放置在期望的位置。
在发送每个放置位置后,你应该刷新标准输出,以确保它被发送给 grader。例如,在 C++ 中可以使用 fflush(stdout),在 Java 中使用 System.out.flush(),在 Python 中使用 sys.stdout.flush()。
当你的程序成功完成一行或发送了无效的放置位置时,游戏结束(以先发生者为准;如果两者同时发生,则无效放置优先)。如果方块的任何部分必须被放置在游戏区域之外(顶部或侧面),则该放置无效。
如果你的程序完成了一行,grader 将发送单个字符 W。收到此字符后,你的程序必须像往常一样以退出代码 0 终止。
如果你的提交遵循上述协议并完成了一行,它将被接受。如果它进行了无效的放置,将被判定为“Wrong Answer”。
如上所述,方块序列由袋子随机生成器决定。该随机生成器的种子值已预先固定,因此每个提交都在相同的方块序列上运行。
样例
样例输入 1
S O T J I W
样例输出 1
1 1 2 4 2 2 3 9 0 6
在上面的交互示例中,左侧是 grader 的一种可能输出,右侧是提交程序的一种可能正确输出。
两侧的空行仅用于强调时间顺序。grader 永远不会输出任何空行。
图 G.2:交互示例示意图。