<center>
## ##**五子棋单机对战**
陈书新 2015013229 龙思宇 2015013239 甘茂霖 2015013247
2017-6-28
#目录
[1. 绪论](#1)[1.1 引言](#1.1)
[1.2 研究的背景及意义](#1.2)
[2. 实验概述](#2)
[2.1 实验目的](#2.1)
[2.2 实验内容](#2.2)
[2.3 实验环境](#2.3)
[3. 需求分析](#3)
[3.1 基本规则](#3.1)
[3.2 主要功能](#3.2)
[3.3 功能说明](#3.3)
[3.4 设计架构](#3.4)
[3.5 游戏流程图](#3.5)
[4. 实验分工](#4)
##
随着社会经济和科学技术的发展,计算机已经深入到人们日常工作和生活的方方面面,各种各样的程序软件也逐渐进入大众的生活,比如在闲暇时间的娱乐生活也开始变得被网络电子游戏等所充斥。而五子棋则是最受人们欢迎的一款益智类棋局游戏,它的简单性,娱乐性,竞技性注定它是一款火爆的游戏。 五子棋是起源于中国古代的传统黑白棋种,当今社会在不同的地域对五子棋也有不同的称呼,其也是一种必须动用脑力的益智类游戏,所以五子棋可以增强思维能力,提高智力。其中蕴含古典哲学的高深学问“阴阳易理”哲理,有利于修身养性,它因为简单易学的特点,所以为人民群众所喜爱,但作为一项高水平的国际比赛,它也有深奥技巧。 五子棋规则相对简单,上手相对容易。本题请同学使用 Python 语言实现一个包含单机双人对战、人机对战,执行 Swap2 规则的,图形界面的五子棋游戏程序。本题预期的产品形态是单机运行的客户端图形界面应用程序。 Python 作为脚本语言,因为其代码开发的快捷性与灵活性,能够快速地进行网站原型的开发与扩展,从而在近些年得到的广大互联企业的关注,例如豆瓣网、Dropbox、Youtube、Instagram 等网站都使用 Python 来进行网站逻辑的编写与构建。如今,几乎所有的初创型企业也大都会选择脚本语言作为其快速开发迭代的保证,因此 Python 作为脚本语言的代表,在我们课程的学习与未来的工作中都有着巨大的帮助与影响。 本课程希望通过实践与了解 Python 相关的数据库应用开发方法,为后续的课程学习积累技术经验。同时,通过 Python 技术开发和实践,希望同学们能够了解企业级架构与普通软件的不同之处,并要求同学们初步掌握软件架构的基本思想、基本方法和基本模型,实现由程序员到软件工程师,由软件工程师到系统架构师思想认识上的转变。更深入地从哲学、美学、技术等不同角度理解软件和体系结构的知识,为后续的数据库、软件工程等课程提供基本的实践经验。 本课程希望同学们能够养成良好的团队意识,要求同学们在短时间内,能够学习新的语言,新的开发模式和新的开发环境,并最终共同制作出一个系统级的软件产品。在快速开发学习、语言学习能力和交流合作能力等方面,都会对同学有较大锻炼与提升。在项目的主体框架下,鼓励同学们创新实践,将富有创新性的想法与内容应用到产品设计中,创造出更具想法与创新的作品。 ① 学习并掌握 Python 的基本语法。 ② 学习并掌握 Python 开发图形界面客户端应用程序的方法。 ③ 熟悉使用 Python 对常用数据结构和算法的实现。 ④ 团队合作,采用合理的团队分工来实现主体部分的项目开发。 ⑤ 理解并掌握代码管理、软件项目管理的基本模式与方法,学习并掌握Git等代码管理软件。 整个实验使用 Python3.6 编写逻辑层,用 PyQt5 编写 ui。 IDE 使用 PyCharm 和 VisualStudio Code。 代码管理用 github 放在组长龙思宇的仓库中,其它组员编写代码后提交 pull request 等待组长合并。 采用 15 路棋盘(15×15)。 Swap2 是当前五子棋世界锦标赛采用的规则。它通过交换黑白双方行棋权(而非对黑方设置禁手)来使棋局平衡。 1. 假先方在棋盘任意下三手(二黑一白)假后方有三种选择: 1. 选黑; 2. 选白; 3. 下四、五两手(一黑一白)再假先方选择黑或白。 2. 此后按Standard Gomoku规则继续进行,即 1. 黑子先行,黑白双方轮流落子; 2. 首先在横、竖、斜方向上连续五个己方棋子者为胜; 3. 超过五子不算赢也不算输。 本系统分成两个部分:单机双人对战和人机对战。 单机双人对战:两名用户在同一台机器、同一个客户端内进行双人对战。程序的主要界面是一张棋盘,棋盘上在相应位置用黑白两色分别显示双方已落的子。用户通过操纵棋盘上的光标选择位置并落子。程序提示两名用户轮流落子并显示当前应由何方行棋。且程序应即时判定是否胜负已分,如胜负已分,则显示哪一方获胜。 人机对战:由程序模拟另一名棋手,与一名用户对战。能够让用户在只有一个人的情况下也能完成游戏,所以要使用人工智能的方法,按照游戏规则,计算机能够自行选择游走方法,与用户进行对弈,计算机扮演者另一个用户的角色。并且,能够正确判断胜负。 \*为实验要求中非必须的需求 游戏准备 双方共有的属性 *是否开启提示 *是否开启悔棋 *是否开启swap2规则 某一方特有的属性 选择某一方为人类 选择某一方为难度为X的AI *选择某一方(若为AI)的单步思考时间 *比分系统,三局两胜制,五局三胜制等
游戏中
*提示当前是哪一方的回合
*为人类玩家提供用户友好的游戏界面
提示上一着棋的落点
根据鼠标的位置提示这一着棋的落点,防止误点
回合结束时判断是否胜利
*到swap2回合给出提示
游戏结束
*显示当前比分
*选择是否继续进行游戏
若是,交换黑白双方
若否,返回初始界面
*允许存盘
扩展功能
*允许复盘
*观看AI间的 pk,方便玩家学习
只要在游戏中选择双方均为AI即可
游戏设置
*改变 ui 样式的功能
User Interface: 用户界面,PyQt5。
UI Logic: ui 逻辑层,每个 ui 单独放在一个类中,在该类中编写 ui 的逻辑(在 PyQt5 中为信号槽)。用户界面的信号会触发 ui 逻辑层的槽函数,这些槽函数会发射新的信号,连向下一层(游戏逻辑层)的槽函数。
Game Logic:游戏逻辑层,为一个类,有若干槽函数和若干普通的成员函数,使游戏的逻辑时刻保持正确。
Game Data:游戏数据层,为一个类,存放了如当前局面,双方对阵信息等数据,和逻辑层分离。
UI Paintevent:ui 绘制层,为一个函数,绘制用户界面。每当底层(游戏数据层)的信息修改后,都会自顶向上调用该层,对UI进行重绘。
人类操作(human):人类可以直接对用户界面进行操作,因此其操作(即信号)直接连接到到UI。
AI操作(AI):AI 不能直接对用户界面进行操作,相反,需要程序对 AI 发出一个请求,即调用AI类的成员函数,获取返回值,才能得到 AI 的操作。因此当需要 AI 进行操作时,游戏逻辑层对 AI 发出请求,AI 返回操作后更新游戏数据层,之后与处理人类操作的步骤一致。
board.py中的Board类主要对游戏逻辑进行管理,它存放 Game Logic 和 Game Data,有如下的成员变量和成员函数。 成员变量: data: 以二维数组的方式存放棋盘 history: 以list的方式存放落子位置 current_player: 当前玩家,1表示先手,2表示后手 current_player_type: 当前玩家的类型,0表示用户,非0表示AI another_player_type: 对方玩家的类型 winner: 获胜的玩家,0表示暂时无胜者,1表示先手,2表示后手,-1表示平局 in_game: 游戏是否开始 off_id, off_delay, off_score: 先手方通过ui输入的参数 def_id, def_delay, def_score: 后手放通过ui输入的参数 成员函数: turn(): 返回当前的轮数 shape(): 返回棋盘的尺寸 in_board(pos): 返回落子点pos是否在棋盘内部(画ui用) at(pos): 返回位置pos的棋子类型(黑棋,白棋,无棋) is_start(): 返回游戏是否开始 start(): 令游戏开始 play(pos): 当前玩家在位置pos落子 undo(): 玩家悔棋 check_winner(): 判断当前局面是否有获胜的玩家 gui.py中的UI类主要对游戏界面进行管理,它继承自 QWidget,存放 User Interface,UI Logic 和 UI Paintevent。游戏只有这一个 QWidget 类主界面,其余的界面都用 QDialog 类(对话框)的形式来实现。该类的成员变量多为绘制点的坐标,这里不在列举,它有如下的成员函数。 成员函数: game_preparation(): 初始化游戏,是ui中的构件合理地显示和隐藏 paintEvent(QPaintEvent): PyQt5的绘制函数 drawLastPlayPosition(painter, center): 绘制上一步的落子点 drawCursorPosition(painter, center): 绘制鼠标指向的落子点 drawChessPiece(painter, center, color): 绘制棋盘上的棋子 drawChessPieceTarget(painter, center, color): 绘制指示先后手的棋子 drawStar(painter, center): 绘制棋盘上的五个星星点 mouseMoveEvent(QMouseEvent): PyQt5的鼠标移动事件 mousePressEvent(QMouseEvent): PyQt5的鼠标点击事件 ai_turn(): ai的回合,开一个新的线程使其运行算法,防止ui卡死 afterPlay(): 每一次落子结束后进行事件判断 start_game(): 开始游戏的准备,数据重置ai.py中的ai类是所有编写的ai的公用父类(一套接口),需要实现下面几个成员函数。 成员函数: ai_move(board): 给出ai对于当前局面的一个落子点 ai_swap1(board): 给出ai对于第一次swap2操作的策略 ai_swap2(board): 给出ai对于第二次swap2(如果有)操作的策略
 龙思宇:“游戏中”代码的编写,为“游戏准备”和“游戏结束”提供接口。随后开始专心机器学习,训练出强大的 AI。 陈书新:“游戏准备”和“游戏结束”代码的编写,并为AI提供接口。随后开始编写使用MCTS(蒙特卡洛树搜索)的 AI。 甘茂霖:UI绘制及美化,撰写文档。编写基于贪心判断局面,找出最优落点的 AI。