计算概论 B 五子棋大作业 VER 2.0
本文档是本次五子棋大作业的说明指南,请先阅读再开始本次作业。
前言
本次大作业的主要内容为编写一个能在命令行中模拟五子棋的简单小程序,也就是说其只需要根据给定的输入模拟出棋盘的状态即可,并不需要它来决定如何落子,这部分占本次大作业 100% 的分数。 编写一个游戏 AI 并非必选内容,当然我们鼓励学有余力且时间充裕的同学动手尝试,如果你成功地完成了这个额外任务,可以获得一定的奖励分数,但本次大作业总分并不会突破上限。 所以请结合自己的实际情况,在接下来的两周内合理安排时间。 另外,必做内容并不困难,按部就班地完成不会有困难,请同学们相信自己的能力。
下载文件
本次大作业下发的内容主要包括四部分:
- README 文档,也就是本文档
- Gomoku 辅助脚本,一套我编写的 Python 脚本,用来调用接口函数,测试各种功能等等
- std 目录,在目录下有两个 Python 脚本,分别是
simulator.py和agent.py,是我实现好的模拟器模块和 AI 模块 - stu 目录,在目录下有两个 Python 脚本,分别是
simulator.py和agent.py,是你将要实现的模拟器模块和 AI 模块
下发 std 的目的在于,你可以随意运行 Gomoku 辅助脚本,加载我写好的模块,观察我的模块是如何完成对应功能的,你只需要以此为目标仿照着写好自己的脚本即可。
借助 Gomoku 辅助脚本,你可以直接开始一盘命令行中的五子棋对弈(并且我建议你这么做,以了解自己要实现的功能),也可以和我写好的 AI 来一场较量(不过,这个 AI 非常愚蠢,你会轻松碾压它),甚至可以让自己的 AI 和我的 AI 来一场比赛。
当然,我对下发的 std 目录下的脚本进行了加密保护,所以你查看不到其中具体的代码实现,嘿嘿。也正是因为加密脚本的限制,你需要下载和自己操作系统(macOS、Windows、Linux)及 Python 版本(3.5、3.6 或更高)对应的代码文件,否则加密脚本可能会运行错误。
比如,我的系统是 macOS (Intel 64位),Python 版本是 3.9,所以我应该下载 darwin.x86_64_py3.9。
如果你的系统是 Windows (64位),Python 版本是 3.6,那么你应该下载 windows.x86_64_py3.6。
你可以在命令行中使用 python3 -V 查看自己的 Python 版本。(另外,macOS 对应的代号是 darwin 哦)
大部分同学应该都是 x86_64 架构,2020 款搭载 Apple M1 芯片的笔电是 arm64 架构,使用 Linux 系统的同学我相信你不需要我解释这些。
提交文件
最终,我们需要你提交自己的 stu 文件夹下的两个脚本(simulator.py 和 agent.py),以及一份简单的实验报告。
任务内容
了解辅助脚本及模块功能
gomoku.py 就是我编写的辅助脚本了,helper 目录下是一些其会用到的模块。在命令行下使用 python gomoku.py -v 就可以查看辅助脚本的版本号了。
辅助脚本提供了两种运行模式,第一种是 simu 模式,用于调起指定的 simulator.py 中的对应函数,实现对五子棋游戏的模拟。第二种是 game 模式,通过设置两个玩家(玩家可以是 AI 或人工输入)进行一场五子棋对弈。下面将分别介绍两种模式。
对了,说在最前,我们的五子棋规定黑子先,白子后,无禁手,当场上棋盘满,则认为平局。
simu 模式
通过 -m simu 参数你可以指定 simu 模式,如在命令行下使用 python gomoku.py -m simu 可以进入最简单的 simu 模式。其默认会使用我编写好的 std.simulator 模块作为五子棋模拟器。如下:

此时,>>> 表示脚本正在等待你的输入。输入 new 5 5 表示开始一局新的游戏,棋盘大小为 5x5。

可以看到其输出了一个空白的 5x5 棋盘,以 A~E 标示行,以 a~e 标示列。接下来输入 move B C c 表示新的落子,第一个 B 表示 Black 黑色,第二个 C 表示 C 行,即第三行,第三个 c 表示 c 列,即第三列。

可以看到在棋盘中间落下了新的黑子。再输入 move W A e 表示在棋盘右上角落下白子。

同期望的一样!现在你已经了解了 new 和 move 操作。假如此时白方玩家突然觉得自己的落子有些愚蠢,想要撤销上一步,模拟器也是可以实现这个功能的!输入 undo 表示撤销,查看变化。

瞧,白子消失了!假设突然黑方玩家有急事,希望保存游戏将来有时间再继续,模拟器也是可以实现的!输入 save first_game.data 表示将游戏状态写入 first_game.data 文件。

可以看到新产生了 first_game.data!我们再通过输入 undo 撤销一步,如下:

然后再 load first_game.data 加载之前保存的游戏。

游戏状态成功恢复了!现在你又了解了 undo,save 和 load 操作,同 new 与 move 一并,这就是你需要实现的五种指令了。最后,使用 quit 指令退出 Gomoku 辅助脚本。

game 模式
使用 -m game 模式可以进入 game 模式。在 game 模式中,你需要设置两名玩家,分别是 playerB 表示黑子玩家和 playerW 表示白子玩家。这里的玩家,既可以是如 std.agent 这样的 AI 模块,也可以是我写好的 helper.human 模块,只要其实现了 next_move 函数即可。例如,你可以通过 python gomoku.py -m game --playerB std.agent --playerW helper.human 设置我编写的 AI 执黑子,你作为人工输入执白子,来开始对弈。

输入 M n 表示你在 M 行 n 列落子。

可以看到棋盘被更新,AI 又落一黑子,并再次等待你的输入。你可以继续这样和 AI 玩一会,或者随意输入一个非法指令以结束程序,如 bilibili。(很抱歉,我忘记为这个模式设计一个体面的退出方式了)

通过 python gomoku.py -m game --playerB std.agent --playerW std.agent 你也可以使我编写的两个 AI 对战。
输入输出
为了便利同学们调试程序,我为辅助脚本设置了从指定文件读入指令、向指定文件输出结果的功能。使用 -i filename 的方式指定输入文件,使用 -o filename 的方式指定输出文件。比如,你可以下载 data 目录,其包含一些我设置的样例,如 example1.in 是输入文件,example1.out 是对应的输出文件。使用 python gomoku.py -m simu -s std.simulator -i data/example1.in 可以从 example1.in 输入,这样你就不必在每次调试时重新手动输入一边了。
模拟器模块
这部分的代码你都应当在 stu/simulator.py 中完成。其中应当定义这三个函数:
operation(opt)winner()draw()
当然,你还可以定义其他的自己需要的函数或全局变量等等。
operation
operation(opt) 接受的传入参数 opt 是一个字符串,表示一次操作,如:
new 10 10move B D eundosave foo.dataload foo.data
你需要自己识别 opt 字符串代表了哪种操作并完成对应的功能。
如果 opt 是一个非法参数,比如在 5x5 的棋盘上要求 move B Z z,或在空白的棋盘上要求 undo 等等,operation 函数就返回字符串 invalid operation。否则,operation 函数就返回一个多行字符串,即当前棋盘的状态,如下面这样:
""" a b c d e
A B B B
B W W
C
D
E
"""
为了避免不要的麻烦,我强烈建议你在形式上和我的输出保持一致。
winner
winner 函数是用来检查当前棋盘局面是否已经产生赢家,如果已经有胜者,则返回长度为 1 的字符串 'B' 或者 'W' 表示胜者,否则返回 None。
我相信不需要再为大家解释五子棋胜利的规则了。
draw
draw 函数是用来检查当前棋盘局面是否平局,如果平局则返回 True,否则返回 False。
游戏 AI 模块
这部分是附加的选做内容,额外得分有限,请合理分配精力。但我们鼓励学有余力的同学尝试一下,你的 AI 只要能轻松战胜 std.agent 就可以认为基本达到合格线了。(如果选择此部分的同学较多,不排除将来会根据两两对战结果评定提交的 AI 等级的可能性)
你需要在 stu/agent.py 中编写 next_move(board) 函数,其接受多行字符串 board 作为输入(这个字符串就是模拟器模块 operation 函数的返回值),返回一个形如 move B M n 这样的操作字符串。注意,返回的字符串只能是 move 指令,且落子颜色和行列都应该合法。返回非法指令的玩家会被直接判负。
你可以大胆想象如何选择下一步落子的位置,将其转化为 Python 代码。
实验报告
实验报告并非字数越多越好,你只需要撰写必要的说明即可。比如,你的实验报告可以包括以下内容:
- 你是如何在 Python 中表示棋盘的,你实现各项功能的基本思路是什么样的
- 你是如何将游戏状态写入文件的,又是如何读取恢复的
- 你是如何设计自己的游戏 AI 的 (可选)
- 你在本次实验中遇到了哪些困难和疑问,是如何解决的(或者还没有解决)
- 你对本次实验的改进建议
另外,实验评分不仅会考察你的代码是否实现了要求的功能,也会考虑到你的代码逻辑是否简单清晰、必要的说明注释是否完善、代码风格是否美观等等诸多方面。如果你非常学有余力且时间非常充裕,也可以尝试进一步丰富程序的功能,包括实现图形界面等,最终会酌情加分。
写在最后
首先,这次大作业其实并不困难。编写游戏 AI 并非必须,鼓励大多数同学将更多精力放在模拟器模块的实现上。你只需要一步一步来、一点一点实现每个功能,相信自己你一定可以轻松完成的。你可以自己编写一些测试用的类似 example1.in 的输入文件,用于测试模拟器功能是否完善。我建立了一个 北大网盘文件夹,你可以在其中的 share 文件夹上传你的 .in 和 .out 文件和大家一起共享,互帮互助,一起 DEBUG。并且,我实现的程序也比较简单,诸多地方可能还不尽完善,欢迎在群里或者私聊我提出,我会不断改进。(如果改进了,我会更新版本号并通知,请及时关注)

Updates
VER 2.1 (2020-12-2)
修复了 Windows 下因为变色字符产生意外输出的 BUG。
Author: YouSiki
Last Update: 2020-12-24