forked from panjd123/Surakarta
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request panjd123#91 from guzhangtong/main
Team16 final report
- Loading branch information
Showing
1 changed file
with
208 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
## 总阶段报告 | ||
### 第一阶段 | ||
--- | ||
#### 规则实现算法 | ||
**基本规则判断:** | ||
|
||
判断不出界/没有自食/没有移动空白棋子等常规易于判断的规则,在此处不再赘述。 | ||
|
||
**非吃子合法移动:** | ||
|
||
判断非吃子移动是否合法,需要两个判断。 | ||
其一,需要判断是否to坐标对应的期盼状态为空。 | ||
其二,需要判断to坐标与from坐标的横纵坐标差绝对值是否小于等于1。 | ||
|
||
**旋吃判断:** | ||
|
||
在这里我将棋盘分为两条可吃子路径链条(line_1,line_2)。而一from棋子和to棋子所在的路径状态可能有三种。 | ||
其中:which_line==1,whichi_line==2,which_line==3,分别代表在路径1/2/1和2上。 | ||
首先判断from和to是否都在同一个line上.(注意3的两面性)。排除不在同一路的,再根据路径标出号。 | ||
可知路径是一条有24个节点的环链表,在这里我们为了便于理解采用了数组存储,有阻碍标为1,无阻碍标为0。注意在这里棋子自己并不遮挡自己,所以标注为0.另一个值得注意的是:在一些交叉点,一个格点存在两个路径标号,我们需要考虑from2,和to2的存在。 | ||
|
||
一切准备就绪后,只需要通过循环来判断from/from2能否成功移动到to/to2且路上无阻挡(数组==0)且旋吃(通过几个特殊旋吃轨道两旁格点),就大功告成啦。 | ||
|
||
算法思想十分简单。 | ||
|
||
|
||
### 第二阶段 | ||
--- | ||
#### QT游戏框架搭建 | ||
**基本游戏实现与规则判断:** | ||
|
||
首先对于棋子的储存,我们声明了棋子类,用来存储棋子的颜色,id,坐标,是否死亡。这样存储的好处是便于能够在后续画棋子/走棋子等函数中实现。 | ||
其次需要注意的是: | ||
1.关于鼠标坐标与棋盘坐标的转换。 | ||
我们用了坐标转换函数实现。 | ||
2.关于turn的转换与判断。 | ||
我们用了bool类型的flag来进行记录与判断,这样能够实现在某一个棋子turn时候不会错点其他棋子,同时能够内部自己换要走的棋子。 | ||
3.关于规则。 | ||
判断不出界/没有自食/没有移动空白棋子/判断非吃子移动是否合法等常规易于判断的规则与阶段一一致,在此处不再赘述。 | ||
4.棋盘绘画。 | ||
|
||
**游戏可视化界面与进一步游戏功能实现:** | ||
|
||
MainWindow主界面,用来控制Board类。MainWindow内有选择模式(人机,ai,网络等),其中该类包含了悔棋、投降、超时检测等操作,由Board信号驱动,启动游戏开始定时器,当定时器开始时,会通过Board类判断当前由哪位用户在操作,并判断超时时间 | ||
class Board{ | ||
public: | ||
QVector<Stone> _s; //当前进行棋子 | ||
QVector<Stone> _s_back; //悔棋 | ||
QVector<Stone> _s_reset; //重新开始 | ||
void Board::mouseReleaseEvent(QMouseEvent *ev)//选择棋子 | ||
{ | ||
copyStone(_s_back,_s); //这里鼠标松下的时候,会把之前的棋子布局和状态记录下来 | ||
class Board{ | ||
void undo(); //悔棋 | ||
bool getUser1(){return bTurn;} //获取当前用户 | ||
void reset(); //重新开始 | ||
|
||
**游戏界面美化:** | ||
|
||
通过样式表和QSS等实现简单的美化,在此不再赘述。 | ||
|
||
|
||
### 第三阶段 | ||
--- | ||
#### 接入网络 | ||
**联网框架构建:** | ||
(以下部分由顾张彤提供) | ||
|
||
一、大致思路 | ||
我依据文档要求,计划为服务端、客户端分别重建项目,从程序设计层面将服务端与客户端分开。我分别为服务端、客户端设计了两个mainwindow类。 | ||
|
||
我在服务端mainwindow类中设计了send_to_client、receive_from_client、remove_client、cut_time等函数以实现基本通信功能,并为日志模块创建了Logger对象、logger指针。服务端初步实现了监听、收发信息、通知对局开始、计时、转发MOVE_OP、重启、超时判断等功能,可以进行基础通信。同时,我为日志模块构建了logger类,实现了日志功能。 | ||
|
||
在客户端的mainwindow类中,我设计了receiveMessage函数,实现了CHAT_OP、READY_OP、MOVE_OP、REJECT_OP等功能。同时设计了最初的客户端图形化界面。 | ||
|
||
|
||
二、遇到的困难 | ||
在设计服务端END_OP时,由于服务端需要具有合法性判断、胜负判断的功能,需要在END_OP中用到大量前期游戏逻辑。我请教了同学,计划利用第一阶段surakarta_rule_manager和第二阶段Board.cpp的canmove函数。由于对前期代码不熟悉、理解能力、代码能力有限,我未能独自完成服务端游戏逻辑的填写。 | ||
|
||
**游戏逻辑完善:** | ||
|
||
基本“照搬”前一阶段的代码,不过值得注意的是在这个时候要实现客户端和服务端的分离,所以需要将canmove函数判断得到的结果改写成op形式来发送,以此传递信息于服务端和客户端。客户端可以继续实现规则判断的逻辑,如判断不出界、没有自食、没有移动空白棋子等。但此时,这些判断主要用于本地UI的即时反馈和玩家操作的提示。服务端在接收到客户端的棋子移动请求时,需要重新验证这些请求是否符合游戏规则。但是由于时间原因,我们对MOVE_OP和END_OP的填写有所简化,故无法和别的小组联机对战。 | ||
|
||
客户端仍然负责棋盘的渲染和棋子的绘制。但此时,绘制的数据应来源于与服务端同步的棋子列表,而不是仅依赖于本地的棋子存储。当服务端接收到客户端的棋子移动请求并验证通过后,需要更新全局的棋子列表,并通知所有相关客户端进行棋盘的同步更新。 | ||
|
||
|
||
#### AI算法 | ||
**算法** | ||
|
||
目前1.5AI采用贪心算法。简单粗暴,主要思想是:能吃对方且不被对方吃的->能吃对方的->不能吃对方的但即将被吃的->移动了也会被吃的。 | ||
定义评估函数: | ||
评估函数用于估计一个给定游戏状态的优劣。对于不同的棋类游戏,评估函数的实现可能会有所不同。它通常会考虑一些如棋子位置、控制区域、棋子的移动性等因素。 | ||
|
||
实现minimax算法: | ||
minimax算法是一个递归算法,它试图最小化对手的最大可能得分(如果你是先手)或最大化自己的最小可能得分(如果你是后手)。 | ||
对于每个可能的走棋,递归地计算其后续状态的得分,并返回最佳得分。 | ||
在递归过程中,保存每个节点的得分和最佳走棋。 | ||
|
||
实现alpha-beta剪枝: | ||
alpha-beta剪枝是minimax算法的一个优化,用于减少不必要的计算。 | ||
对于每个节点,维护两个值:alpha和beta。alpha表示当前玩家在当前搜索路径上的最佳可能得分(对于先手是最大值,对于后手是最小值),而beta表示对手的最佳可能得分(对于先手是最小值,对于后手是最大值)。 | ||
如果在某个节点的搜索过程中,发现当前路径的得分已经不可能比alpha大(对于先手)或比beta小(对于后手),则剪去该分支的后续搜索,因为这些分支不会对最终决策产生影响。 | ||
|
||
选择最佳走棋: | ||
在递归搜索结束后,根据保存的最佳得分和走棋信息,选择最佳走棋。 | ||
这通常是通过回溯到根节点并沿着保存的最佳走棋路径来实现的。 | ||
另:AI部分代码有参考网上各个ab剪枝代码和视频中的写法。 | ||
|
||
### 第四阶段 | ||
--- | ||
**完善AI** | ||
|
||
【秦禛涵2023202271】在这个阶段提升了AI的性能。 | ||
|
||
**附加任务** | ||
|
||
【苏楷棋2023202240】在第二阶段实现了单机游戏的重新开始。 | ||
|
||
【顾张彤2023202299】在第二阶段基础上,在第三阶段完成了附加任务4,即再来一局。这在游戏结束的提示界面上体现为重新开始。 | ||
|
||
【秦禛涵2023202271】在第一、第二阶段热情帮助Team1、Team6小组同学解决问题,完成附加任务10。 | ||
|
||
|
||
### 分工 | ||
--- | ||
**第一阶段** | ||
【秦禛涵2023202271】完成AI/rule的所有代码填写,并进行debug。 | ||
|
||
***测试*** | ||
|
||
【秦禛涵2023202271】完成第一阶段代码测试,【顾张彤2023202299】【苏楷棋2023202240】辅助完成代码测试。 | ||
|
||
**第二阶段** | ||
【秦禛涵2023202271】目前该阶段代码在游戏实现阶段(包括棋盘建立/整个游戏的完整流程成功运行至一方输),游戏美化阶段(包括按钮形态设计/样式表调整/背景图片制作)完成,并进行debug。 | ||
|
||
【苏楷棋2023202240】完成按钮与其对应功能(包括悔棋/倒计时/认输等功能),并进行debug。 | ||
|
||
***测试*** | ||
|
||
【秦禛涵2023202271】【苏楷棋2023202240】完成第二阶段代码测试。 | ||
|
||
**第三阶段** | ||
【秦禛涵2023202271】 完成与AI的算法优化/AI接入联网游戏并进行debug。在队友提供的联网框架下将上一阶段部分游戏代码填入这一阶段,并实现任务:现实能走的地方,显示上一次移动的棋子。优化联机模式下的canmove函数,使之实现前后端分离。参与修改行棋记录格式。 | ||
|
||
【苏楷棋2023202240】 在队友提供的联网框架下完成将上一阶段部分游戏代码填入这一阶段,并实现任务:结算面版。 | ||
|
||
【顾张彤2023202299】 实现行棋记录,完成整体联网的OP等函数的框架填写以及大框架搭建,将上一阶段部分游戏代码填入这一阶段,参与AI的部分debug。 | ||
|
||
【苏楷棋2023202240】【顾张彤2023202299】进行联网逻辑的debug,实现吃子后同步,修改MOVE_OP格式,填写并完善第三阶段代码注释。 | ||
|
||
***测试*** | ||
|
||
【秦禛涵2023202271】 完成AI的测试,参与联网模式下的AI测试和联网human VS human 测试。 | ||
|
||
【顾张彤2023202299】【苏楷棋2023202240】 进行组内联机测试,完成联机AI测试,参与联网模式下的AI测试和联网human VS human测试。 | ||
|
||
**报告撰写** | ||
|
||
除了联网框架报告、第四阶段报告、部分分工报告、仓库地址由【顾张彤2023202299】撰写外,其余报告均由【秦禛涵2023202271】撰写。 | ||
|
||
**一些状况** | ||
|
||
由于分工问题原定独立编写联网逻辑的【顾张彤2023202299】没有参与前两阶段的代码编写,对游戏逻辑不够熟悉,导致5.18那一次ddl没有赶上。且在那一天我们才发现了我们分工有问题,所以第三阶段游戏逻辑的改写与填充准确说是从5.20开始写的。与助教沟通后助教建议我们两个星期的时间只把较为基础的游戏部分从单机游戏改写成联网,故附加任务我们完成得不多。后续我们也会试着将6.3提交版本的代码优化。且因为考虑到我们不参加比赛,于是为了保证游戏的可玩性,我们设计了human VS human和human VS AI两个功能,并没有在human VS human中接入AI。 | ||
|
||
|
||
### 致谢与被致谢 | ||
--- | ||
01组同学、06组同学、王燚同学。 | ||
以及项晓清同学、张昕跃同学、杨昱文同学。 | ||
感谢交流指导。 | ||
|
||
以及【秦禛涵2023202271】在第一第二阶段帮助了01/06组同学,并被致谢。 | ||
|
||
|
||
### 代码仓库 | ||
--- | ||
#### 初版 | ||
|
||
[总仓库](https://github.com/huoguocat/catcat) | ||
|
||
[第一阶段](https://github.com/huoguocat/HUOGUO_CATCAT_Surakarta) | ||
|
||
[第二阶段棋子](https://github.com/huoguocat/catcat/tree/main/HUOGUO_qizi) | ||
|
||
[第二阶段单机游戏](https://github.com/huoguocat/catcat/tree/main/surakarta_stage2_16/surakarta_stage2) | ||
|
||
[第三阶段协议的解析与封装](https://github.com/huoguocat/catcat/tree/main/stage3) | ||
|
||
[第三阶段客户端源代码](https://github.com/huoguocat/catcat/tree/main/surakarta_source) | ||
|
||
[第三阶段客户端打包exe](https://github.com/huoguocat/catcat/tree/main/Client_Team_16) | ||
|
||
[第三阶段服务端源码](https://github.com/huoguocat/catcat/tree/main/Surakarta_server_source) | ||
|
||
[第三阶段服务端打包exe](https://github.com/huoguocat/catcat/tree/main/Server_Team_16/Server_Team_16) | ||
|
||
|
||
#### 最终版本 | ||
|
||
[总仓库](https://github.com/guzhangtong/Surakarta_final) | ||
|
||
[第一阶段规则判断](https://github.com/guzhangtong/Surakarta_final/tree/main/stage1) | ||
|
||
[第二阶段游戏逻辑](https://github.com/guzhangtong/Surakarta_final/tree/main/stage2) | ||
|
||
[第三阶段客户端](https://github.com/guzhangtong/Surakarta_final/tree/main/client) | ||
|
||
[第三阶段服务端](https://github.com/guzhangtong/Surakarta_final/tree/main/server) |