# NewGoBang **Repository Path**: yeziqiushui/NewGoBang ## Basic Information - **Project Name**: NewGoBang - **Description**: 基于Qt C++的五子棋 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2021-05-09 - **Last Updated**: 2022-06-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # NewGoBang 基于Qt C++的五子棋 ### 网络对战 开发日志 TimeOut客户端的做法 发起者(超时的一方): 输出超时信息(messagebox) 发送超时信息 执行网络对战结束的操作gameover 服务端的做法 改变房间双方的状态 将房间资源回收 给对端发送对端超时的操作 让它们失去对房间的控制操作 发送对端超时 接收者的做法: 输出你赢了(messagebox) 执行游戏结束操作 Success客户端的做法 发起者(五子成线的一方): 输出成功信息(messagebox) 发送成功信息 执行网络对战成功的操作gameover 服务端的做法 改变房间双方的状态 将房间资源回收 给对端发送对对端成功的操作 让它们失去对房间的控制操作 超时(发起者的操作): 失去对房间的控制权 超时的接收者(接收者) 释放房间资源 发送给客户端 接收者的做法: 输出你赢了(messagebox) 执行游戏结束操作 客户端给服务端发送信息的逻辑: 发送方:(客户端) 将棋子显示到棋盘上 给服务端发送信息 服务端:(接收方) 如果对端是下线状态,则不发送棋子 如果对端是在线状态,并且处于写的状态下,服务端给对端发送棋子 如果对端是超时状态,则不发生棋子 一方挂掉 挂掉的发起者会向服务端发送信令 服务端: 发起者: 1.失去对房间的控制权 2.设置自己的状态为下线 如果对方没有下线 即状态处于读 写的状态 给对端发送自己下线的信息 如果对端已经下线 即状态处于下线状态 返回 然后回收资源 接收者 1:失去对房间的控制权 2,设置自己的状态为free 3.发送给客户端自己下线的信息 客户端 显示对方下线 你赢了 游戏结束 悔棋: 只能是轮到发送方落子了,发送方才能悔棋 发送方先停止时间的推移 发送方给服务端发送悔棋信令 服务端给对端转发悔棋信令 如果对端同意,那就给服务端发送对端同意的信令 对端将自己的落子点和对方的落子点都卸下来 服务端收到之后,给发送端发送对端同意,发送端将黑白两子都移除一个 重置时间 对端不同意,那就给对端发送不同意的信令 五子棋的登陆系统 使用qsqllite做账户信息的存储,包含用户的基本信息,账号,密码,id,用户名,所使用的图片,等级等 用户表 Id 账号 密码 用户信息表 Id 用户名 所使用的图片的路径 个性签名 等级 用户好友表 Id 好友id 状态 游戏大厅的更新: 客户端一秒钟给服务端发送心跳请求,服务端接收到之后,把当前的全部的房间信息分发给客户端。 信令格式: type: heart_alarm 服务端的心跳反馈: type:HallInfo; { Homeid; 先手:{用户名字,级别} 后手:{用户名字,级别} } … 客户端接收到之后,将心跳的内容反馈到大厅窗口上。 服务端需要做的修改: 接收到用户发送的数据的时候,会判断当前的SendBuf是否是空的,如果是空的,那就申请内存,如果不是空的,那就释放内存,然后重新申请 更改策略: 写数据的时候,直接追加,写结束之后,将申请的内存去清理掉 具体策略: 如果写缓存有数据 即:数据格式是 int(数据长度)+Json 那就在其后写入,int+Json 发送 当前的读写策略 客户端发送数据: 1.发送数据长度+Json 4.发送数据 +Json 服务端接收数据: 2.读取数据长度+Json 3.发送数据 +Json +追加数据长度+Json 对于混合指令的处置手段: 使用类似string的方式扩容 在读取通讯指令,给对端发送(不会造成问题) 引入内存池机制,可以防止重复申请释放内存做出的服务端资源消耗。 对内存池做的更改: 用户自定义(12个)槽的数据长度: 游戏开始的时候,进行三次握手: 这样可以让客户端和服务器均知道双方可以通讯。 服务端在分配房间的时候,有两个方式,一个是在双方都进入到等待,在队列里面拿数据。另外一种是双方选择房间进行对战。在另外一组房间号里面寻找。 客户端 游戏大厅的设置: 点击网络对战的时候,出现游戏大厅,在大厅可以选择进入的房间号码。 点击对应的listview之后,给服务端发送信令 { Type: inHome; HomeId: id; } 服务端给客户端反馈: { Type: 先手/后手/先手-等待队友中 ,先进入房间的是先手 } 如果另一个客户进入同样的房间 服务端先判定当前房间是否是空的,如果是空的,拿给客户端反馈的类型就是在等待队友中 如果房间不是空的那就给房间的双方反馈,先手/后手信息 用户登陆信息: 用户退出登陆: 2021.2.28 加入了心跳功能 客户端给服务端发送ping 服务端反馈pong 客户端超时服务端设置的3/4*(max heart_time) 或者 1*(heart_time)那就挂了 2020.5.1 加入对非法报文的裁决机制(反外挂) 关于ArgPacket的状态: 创建的时候 : player_status:free 进入队列的时候,但是没有队友匹配 : player_status: 无状态 匹配之后: 先手: write 后手: read 双方相互发送棋子: 发送方: read 接收方: write 取消网络对战: 取消成功: 取消失败: 通告对端 4. 技术栈 服务端采用C++ 作为主语言开发,通讯采用reactor模型(one loop per thread) 数据库采用sqlite 客户端采用Qt开发,主语言C++