本章涵盖
- 使用Python实现一个围棋棋盘
- 落子并模拟一个游戏
- 依据围棋规则来编程确保合法落子
- 构建一个可以自我对弈的简单机器人
- 可以与您的AI下完整的一盘棋
在本章中,您将构建一个灵活的库,该库提供表示围棋游戏和支持围棋规则算法的数据结构。如上一章所述,围棋规则非常简单,但是要在计算机上实现它们,您必须仔细考虑所有边缘情况。如果您是围棋游戏的新手或需要重新学习规则,请确保您已阅读第2章。本章是技术性的,需要你对围棋规则有很好的了解,才能充分理解细节。
在本章的最后,您将实现您的第一个围棋AI。虽然这种AI仍然很弱,但是却拥有有关围棋游戏的所有知识,它需要在以下各章中发展,成为更强大的版本。
你将从正式介绍棋盘和用电脑玩围棋游戏的基本概念开始:什么是一个棋手、棋子或落子?下一步,你将关注游戏的具体内容。计算机如何快速检查哪些棋子可以被吃掉或着什么时候应该用劫的规则?一场比赛何时及如何结束?我们将在本章中回答所有这些问题。
3.1用Python表示一个游戏
围棋是下在一个方形棋盘上的。通常初学者会先下一个9*9或者13*13的棋盘,有一定水平或职业棋手都会去下19*19的棋盘。但是原则上,围棋可以在任何尺寸的棋盘上下棋。实现游戏的方形棋盘是很简单的,但是你需要去在线上去处理复杂的事情
使用Python表示围棋游戏可以通过逐步调用dlgo去构建一个模块。在整个章节中,您将被要求创建一些文件并实现类和函数,这些类和函数最终将导向你的第一个AI。本文及其后各章的所有代码可在http://mng.bz/gYPe.的GitHub上找到
虽然您绝对应该克隆这个存储库作为参考,但我们强烈鼓励您从头开始创建文件,因此这样就可以看看库是如何一个个地被构建起来的。我们的GitHub存储库的分支里包含本书中使用的所有代码(以及更多)。从这一章开始,每一章都有一个特定的Git分支,代码都有给定一章的标识。例如,本章的代码可以在分支章节_3中找到。下一章遵循相同的命名惯例。
要构建一个Python库来表示围棋,您需要一个足够灵活的数据模型来支持一些用例:
- 跟踪你与人类对手比赛的进度。
- 跟踪两个AI之间游戏的进度。这似乎与前面的观点完全相同,但事实证明,存在一些细微的差别。最值得注意的是,单纯的AI很难识别棋局是否结束。让两个AI互相对弈是一个重要的技术,将会在接下来一章来使用,所以值得在这里说明
- 比较同一棋盘盘面的多个搜索序列。
- 导入对局记录,并由其生成训练数据
我们从几个简单的概念开始,比如棋手或落子是什么。这些概念将为在后面的章节中处理所有上述任务奠定了基础。
首先,创建一个新文件夹dlgo,并将一个空的_init_py文件放入其中,作为一个Python模块初始文件。另外,创建两个名为gotypes.py和goboard_slow.py的附加文件我放所有的棋盘和游戏的功能。此时您的文件夹结构应该如下所示:
dlgo
__init__.py
gotypes.py
goboard_slow.py
在围棋中黑棋和白棋会轮流开始下棋,这里我们就使用枚举类型来代表不同类型的棋子。一个棋手要么是黑棋要么是白棋。当一个棋手下了之后,你会让Player对象中的另一个实例去下棋,把这个Player对象放到gotypes.py文件里
import copy
from dlgo.gotypes import Player
# 定义操作类(包括落子、投降,不允许用户pass)
class Move:
def __init__(self, point=None,if_pass=False,if_resign=False):
# 断言,两种条件(落子为空,玩家投降了)都不会执行下面语句,直接跳出
assert (point is not None) ^ if_pass ^ if_resign
self.point = point
s