Skip to content

实验框架介绍

在网络学堂作业附件中,我们对不同系统提供了对应的实验框架,见 AI 文件夹。

为了支持本地测试,我们对不同系统有不同的“祖传框架”以直接编译得到动态链接库,其中 Windows 配置了 Visual Studio 项目,Mac 配置了 XCode 项目,Linux 是简单的 Makefile。

但是由于线上平台(也是 Linux)的诞生,你完全可以放弃本地测试,直接使用 Liunx 框架,并用自己喜欢的编程工具配置项目、完成作业。

这里尤其不推荐使用 Windows 框架,Windows 框架下有一些 MSVC 编译器专用的关键字,每年都会有一部分同学因为没有看平台 提交要求 而编译失败。

无论何种选择,Strategy 项目是你唯一需要从中编写代码的项目,下面将对其进行介绍。

Judge.hJudge.cpp

用来进行胜局检测的函数,你可能使用得到也可能使用不到,相关函数的具体说明请见代码中的详细注释。这里只强调一些细节:

  • 由于在某一方落子得胜之前,一定不可能出现过任何一方的胜局,所以我们只需要在某次落子之后,以本次落子点为核心判断是否有多于四个的连子即可。userWin 函数和 computerWin 函数就是这样做的,并且我们只需要在 user 落子时候判断是否 userWin,在 computer 落子之后判断是否 computerWin
  • 由于 isTie 通过检测棋盘是否己满来判断是否为平局,这就意味着调用 isTie 必须在调用 userWincomputerWin 之后。假如某次为用户落子,那么之后当 userWinfalse 时,调用 isTie 进行判断才有意义。

Point.h

Point 类,用来记录棋盘上的一个点。

注意框架中对坐标的规定:棋盘中左上角为坐标原点,纵向为 \(x\) 坐标轴,横向为 \(y\) 坐标轴,\((x,y)\) 点对应于棋盘中第 \(x\) 行第 \(y\) 列的位置(从 \(0\) 开始计而不是从 \(1\) 开始计)。

Strategy.hStrategy.cpp

定义了策略函数同外部调用程序之间的接口。

getPoint 函数:在对抗时,外部程序在每次需要落子时通过调用该函数获得你给出的落子点。你的策略最终应当封装到该函数中,给出你在本步中的落子。

clearPoint 函数:策略模块中动态定义的对象必须由策略模块中的函数来释放;getPoint 函数返回一个 Point *,该指针指向的对象应当通过在外面调用clearPoint 函数来释放。你不需要修改该函数。

注意点

  1. 关于接口函数传入的参数
    1. top 数组给定了当前棋局各列的顶端位置,这些顶端的上面是你可以落子的地方。如果你的策略给出了非法的落子,那么程序会给出提示。
    2. board 二维数组则给出了当前棋局的所有情况。你可以假设自己策略正在同某一用户进行对弈,那么 board0 为空位置,1 为有用户棋子的位置,2 为有计算机(自己的策略)的棋。不可落子点处的 board 值也为 0
    3. 对于不可落子点,外部调用程序己经做出了处理。比如某次落子点为 A 位置,而 A 上面的 B 位置为不可落子点,那么下次传递给你的 top 数组中该列列顶己被设为了 B,而不是 A,所以你的策略中不需要考虑对不可落子点进行特殊处理当然,如果你想充分分析不可落子点,以做出更好的策略也是可以的。我们将不可落子点 (noX, noY) 直接传递给了你,你可以充分利用。
    4. 实际操作时,请注意看代码中详细的注释。这将对你理解整个项目有很大的帮助。
  2. 最好用 Release 模式编译以保证你的落子速度。打印操作会严重影响你的策略的速度,所以在最终版本中请务必去掉所有的打印调试信息。
  3. 不要随意修改工程的各种属性。
  4. (lastX, lastY) 给出了上一次对方落子的位置,刚开局时传入的 lastXlastY 值为 -1。当然,为了更好地组织你的策略,你可以不仅仅利用上一次落子这一步信息,而是在你的策略中将其保存下来,综合多步以便决策时使用。实际上,传入的参数中 topboard 给定了当前的状态,lastXlastY 给定了过去的过程,这样也就为你提供了全部可用信息
  5. 进行思考时,可以认为自己的程序正与一个用户对抗。对方的棋子用 1 标示,自己的程序的棋子用 2 标示。