跳转至

大作业实验报告

一 · 小组简介

小组成员

鲁嘉宁 2021201518 冯宵瑶 2021201516 冯锦程 2021201644

小组分工

本小组三位同学线上线下一起共同完成大作业三个阶段的实现

仓库链接

https://github.com/Fxy2021201516/Chinese_checkers.git

二 . 各阶段任务完成情况

第一阶段

  1. 实现多界面的呈现与切换
  2. 实现棋盘的呈现
  3. 实现棋子的呈现与移动
  4. 实现行棋的合法性的判断

第二阶段

  1. 服务端的窗口和相应的处理判断能力。包括:客户端进入房间的合法性、玩家姓名的合法性、行棋的合法性、终局的判断、排名的计算、轮空清空棋子。
  2. 客户端的窗口呈现和相应的移动能力。包括:显示时间、显示己方姓名、移动棋子并传输相应通信协议等。
  3. 服务端和客户端之间的通信建立

第三阶段

  1. 实现AI与单机模式之间随意切换,支持2、3人AI模式

附加功能

  1. 实现连跳展示路径
  2. 可查看任一方棋子上一步行棋路径
  3. 可实现人与AI对战

效果图展示

1

2

4

4

三 . 整体思路

第一阶段

  1. 定义QPushButton类为棋子 image-20220626112028750
  2. 定义可点击区域vector image-20220626112234052
  3. 定义棋盘数组 image-20220626112308029
  4. 通过鼠标点击事件来记录坐标与棋盘上的位置,从而使棋子可以移动 image-20220626112855138
  5. 通过递归判断连跳是否合法 image-20220626112649431

第二阶段

分别在客户端与服务端设置 receive 函数,判断接收到的信息并作出相应处理。

服务端

  1. 对各个协议的接受、发送、处理。 服务端判断移动是否合法,如不合法向客户端发送错误信息,使客户端撤销本次移动。 在服务端设置计时器,实现轮空判负功能,棋子中途轮空将直接被在棋盘上移除。 image-20220626113404533

客户端

  1. 显示图形界面
  2. 对各个协议的接受、发送、处理。其中,客户端记录所有鼠标点击事件,记录坐标位置,并直接做出移动。若收到服务端的信息显示自己为非法移动,再进行撤销。 image-20220626113757566

第三阶段

  1. 通过权值计算的方法,判断权值最大的移动即为AI应该作出的移动。
  2. 为棋盘设定初始的权值表,然后根据棋子在棋盘上的位置,调整每个棋子权值的占比。 image-20220626114515391
  3. 遍历AI一方所有可能的移动方案,再以上述逻辑遍历AI所有对手可能的移动方案,之后再次对AI后一步的走法进行尝试。 image-20220626114618145
  4. 综合考虑以上几步,按进攻、防守、搭桥分别计算得出权值。
  5. 总权值最大的即为AI所做的移动 。 image-20220626114916153

四· 遇到的问题和解决方案

第一阶段

  1. 空指针: 以下问题:程序进入多人游戏时无窗口出现直接报错为“crash”
  2. 在遍历容器为每一个棋子设置槽函数时注意每方棋子在vector中和begin与end的位置关系
  3. 在生成棋盘时数学关系出错,导致在后面程序的运行中出现错误的对应关系,从而出现未被正确赋值的指针
  4. 数学关系逻辑问题: 棋盘上棋子不在正确位置
  5. 连跳不能正常进行,递归前记得初始化

第二阶段

  1. 棋子移动时未考虑棋子逻辑坐标与Qt的图形界面的交互. 移动棋子,有正确的玩家控制权轮换,对棋子移动的合法性判断也体现棋子已经完成移动,但是不显示棋子移动且被移动棋子原位置仍可点击(并且在点击后crash). 解决方法:在走棋时更改棋子作为一个按钮在界面上的位置信息(棋子继承 QPushButton 类)
  2. 与第一阶段程序的整合: 为了更好地联系第二阶段,我们对第一阶段的程序做了一定程度的修改,例如坐标系的建立方法、棋子坐标的改动、不同游戏人数的实现思路,在改动的同时,机械的复制粘贴就导致了很多的bug。比如,程序运行到changeinfo时,总会报空指针的错误,原因是我们在复制粘贴时,搞错了两行代码的位置,把this->select指成了空指针。
  3. switch的case里不放break;while循环里没有放终止条件。所以我们调试的时候经常遇到意想不到效果……

第三阶段

  1. 不会记录路径:考虑每次都会覆盖上一次的路径。
  2. AI移动的方向不符合正常思维:权值设置不合理。
  3. AI棋子反复横跳:在设计AI判断和寻找路径的函数中,有一些范围和逻辑上的小错误,导致用到此部分是出现错误。
  4. 选择了正确的棋子并且算出了想去的位置,但是跳不过去:深度搜索时,flag设置成了局部变量,则每一次调用递归函数时都被赋予了新值。解决方法:设置为全局变量,并处理每次变化的逻辑关系。