# Socket 网络编程斗地主大作业 设计文档
- ## 程序架构及设计思路
![](https://www.writebug.com/myres/static/uploads/2021/11/10/a8a4a594adeadd89ba61fba4df8adf36.writebug)
![](https://www.writebug.com/myres/static/uploads/2021/11/10/5df12b791fbf6c7b853c20ce7fafef83.writebug)
我写了一个 Card 类,继承自 QWidget,用来存放扑克牌的花色和点数,以及是否被选中。我重写了 paintEvent 函数,画出扑克牌。如果牌被选中,则上移 30 像素,重绘该扑克牌。
![](https://www.writebug.com/myres/static/uploads/2021/11/10/d651b0b6821be06fddeb0771d1b45995.writebug)
![](https://www.writebug.com/myres/static/uploads/2021/11/10/0881735ed62cc0d1d8645825e73ae1d9.writebug)
我还写了一个 CardCombine 类,用来判断玩家所出的牌是什么类型,是否合法,点数是否比上一位玩家大。具体来说,先判断该组牌是空、单牌、顺子、对子、三带(一、二)、四带二、飞机还是炸弹,根据类型判断牌的优先级(王炸 > 炸弹 > 普通牌 > 空 > 非法),优先级高则可出,优先级相同则比较点数。
在准备界面,显示一个“开始连接”按钮,当三个用户都按下这一按钮后(A 知道自己是否和 B、C 连上,B 和 C 连上后向 A 发送消息,A 收到消息后,向 B、C 下达开始指令),页面跳转为游戏界面,update()函数重绘界面背景。我在 A 用户端实现随机发牌和随机确认地主,并将各方的牌和由谁开始叫地主的信息传送给 B 和 C。无论是哪方开始,叫地主顺序和出牌顺序始终是 A-B-C-A。三家都确认是否叫地主后,由 A 用户端确认地主是谁,将信息发送给 B、C,开始游戏。用户出牌后会将出牌信息发给另外两个用户,出牌情况将显示在三个用户的界面上,并更新 last(CardCombine)作为下一次出牌的比较对象。每一次出牌后都会更新三个用户端上各方的余牌数量,并由各方自行判断是否轮到自己出牌和游戏是否结束(一方剩余牌数为 0)。若游戏结束,则显示输赢,并出现“再玩一次”和“退出”两个按钮。若三位玩家都都选择再玩一次,则游戏界面初始化,重新开始随机发牌和随机确认地主。点击退出则程序停止。
## 客户端工作流程
我在 A 用户这里创建了两个 listenSocket,等待 B 和 C 的连入;在 B 用户这里创建了一个 listenSocket,等待 C 的连入。当 B 和 C 连上 A、C 连上 B 之后,利用 connectToHost 和 nextPendingConnection 函数在每个用户端各创建两个 readWriteSocket,实现两两用户之间可以互发消息,通信完成。
**通信协议**
![](https://www.writebug.com/myres/static/uploads/2021/11/10/a7039adda1b372e6d3dcd25e26841c4b.writebug)
- 当一个用户想给另一个用户发送一个 QString 字符串消息时,他需要先获得该字符串的长度,将其转换为一个长度为 2 的 QString,和消息合并起来,再将整个字符串写给另一个用户。
![](https://www.writebug.com/myres/static/uploads/2021/11/10/e93c89879e0d5c3bcdacfa50f4b84197.writebug)
而当用户接收消息时,他需要先读出前两个字符,将其转换为 int 格式,获取该消息的长度信息,再读入完整的消息。这样一来,避免了 QTcpSocket 将一个消息分成两个消息写出,或是将两个消息合并成一个消息读入。
为了避免粘包,我加上了一行代码“while(!readWriteSocketC->atEnd())”,来确保每一条消息都会被读到。否则有可能出现两次 write 只触发一个 readyread 信号的情况,导致第二条消息未被读入。
## 规则设计流程
**连接**
连接时需要确认三个用户两两互联。A 是等待 B 和 C 连接的一方,故 A 用户端可以确认 AB、AC 之间是否连上。而 B 是等待 C 连接的一方,所以 B 用户端可以确认 BC 之间是否连接。当 BC 连上之后,B 给 A 发信息“begin”,A 收到消息后判断三者是否两两互联成功,若成功,则通知 B、C 开始游戏,自己也转入游戏界面。A 在连上 B 和 C 之后也会各做一次判断,直到两两连接成功。
**叫地主**
由 A 用户端随机指定开始叫地主的用户,并发送信息(“jiaodizhu”)让其转入叫地主界面。每一个用户叫完之后将结果通知给另外两个玩家,另外两个玩家需显示并判断是否轮到自己叫地主。当三人都完成叫地主,由 A 用户端判断谁是地主,将结果发给 B 和 C,由地主开始出牌。
**出牌**
每一个用户储存一个 CardCombine 类 last,用来储存上一次有效出牌(不包括不出)。轮到用户出牌时,客户端判断哪些牌被用户选中(Card 类中有一个 bool 成员 isSelected),将这些牌和 last 作比较(compareTo 函数),若优先级更高或点数更大,则可以出牌。用户将出牌信息传给另外两个用户,另外两个用户需将这些牌显示在界面上,更新自己的 last,并判断是否轮到自己出牌。
判断出牌合法性
先判断牌的类型:
- 空:张数为 0;
- 单牌:张数为 1;
- 对子:张数为 2 且两张牌点数相同;
- 顺子:张数大等于 5,每一张牌都比前一张牌点数大一
- 连对:牌数大等于 6 且为双数,重新排序后每一张偶数牌都满足比前一张偶数牌大一
- 三张:牌数为 3 且 3 张点数相同
- 三带一:牌数为 4 且有三张牌点数相同
- 三带二:牌数为 5 且有三张牌点数相同,另外两张牌点数也相同
- 四带二:牌数为 6 且有四张牌点数相同,或牌数为 8 且有四张牌点数相同,另外四张两两点数相同
- 飞机:牌数大于等于 6 且是三的倍数,重新排序后每一张模 3 余数相同的牌都满足比前一张大一
- 飞机带单牌:有飞机存在且飞机数量等于单牌数量
- 飞机带对子:有飞机存在且飞机数量等于对子数量
- 炸弹:牌数为 4 且 4 张点数相同
- 王炸:牌数为 2,点数分别为大王和小王
判断牌的优先级:王炸 > 炸弹 > 普通牌 > 空 > 非法
优先级高则可出,优先级相同则比较点数,点数大则可出。
## 心得
架构要事先规划好,否则最后重开一局的时候初始化很困难。
Ui 界面的设置尽量写在一起,否则东一个按钮显示、西一个 label 位置会让程序看起来很混乱,也不利于最后重新读并梳理自己的代码。
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
本项目旨在用C++编写程序利用 connectToHost 和 nextPendingConnection 函数在每个用户端各创建两个 readWriteSocket,实现两两用户之间可以互发消息,通信完成。
资源推荐
资源详情
资源评论
收起资源包目录
基于C++ Socket 网络编程斗地主大作业 (238个子文件)
playwindow.cpp 11KB
cardcombine.cpp 10KB
cardcombine.cpp 10KB
cardcombine.cpp 10KB
playwindow.cpp 7KB
playwindow.cpp 7KB
card.cpp 5KB
card.cpp 5KB
card.cpp 5KB
playgame.cpp 4KB
playgame.cpp 4KB
playgame.cpp 4KB
mainwindow.cpp 4KB
mainwindow.cpp 3KB
mainwindow.cpp 3KB
main.cpp 172B
main.cpp 172B
main.cpp 172B
Socket网络编程斗地主大作业 设计文档.docx 165KB
cardcombine.h 2KB
cardcombine.h 2KB
cardcombine.h 2KB
mainwindow.h 2KB
mainwindow.h 2KB
mainwindow.h 2KB
card.h 1KB
card.h 1KB
card.h 1KB
214833-120P41A43836.jpg 218KB
214833-120P41A43836.jpg 218KB
214833-120P41A43836.jpg 218KB
214833-120P41A11846.jpg 213KB
214833-120P41A11846.jpg 213KB
214833-120P41A11846.jpg 213KB
214833-120P41AK868 .jpg 205KB
214833-120P41AK868 .jpg 205KB
214833-120P41AK868 .jpg 205KB
214833-120P4164K869.jpg 205KB
214833-120P4164K869.jpg 205KB
214833-120P4164K869.jpg 205KB
play.jpg 87KB
play.jpg 87KB
play.jpg 87KB
LICENSE 1KB
README.md 6KB
background.png 533KB
background.png 533KB
background.png 533KB
play2.png 382KB
play2.png 382KB
play2.png 382KB
PADDING.png 146KB
PADDING.png 146KB
PADDING.png 146KB
HJ.png 111KB
HJ.png 111KB
HJ.png 111KB
HK.png 110KB
HK.png 110KB
HK.png 110KB
DK.png 110KB
DK.png 110KB
DK.png 110KB
SQ.png 109KB
SQ.png 109KB
SQ.png 109KB
DJ.png 109KB
DJ.png 109KB
DJ.png 109KB
HQ.png 108KB
HQ.png 108KB
HQ.png 108KB
DQ.png 106KB
DQ.png 106KB
DQ.png 106KB
CQ.png 105KB
CQ.png 105KB
CQ.png 105KB
SJ.png 103KB
SJ.png 103KB
SJ.png 103KB
SK.png 103KB
SK.png 103KB
SK.png 103KB
CJ.png 103KB
CJ.png 103KB
CJ.png 103KB
CK.png 98KB
CK.png 98KB
CK.png 98KB
BLACK JOKER.png 70KB
BLACK JOKER.png 70KB
BLACK JOKER.png 70KB
dizhu.png 66KB
dizhu.png 66KB
dizhu.png 66KB
H10.png 61KB
H10.png 61KB
H10.png 61KB
RED JOKER.png 58KB
共 238 条
- 1
- 2
- 3
资源评论
- xxxcjql2024-03-09资源内容总结地很全面,值得借鉴,对我来说很有用,解决了我的燃眉之急。
- lyk8282024-01-04果断支持这个资源,资源解决了当前遇到的问题,给了新的灵感,感谢分享~
- m0_748129882024-04-22发现一个宝藏资源,赶紧冲冲冲!支持大佬~
- m0_737468642023-09-03超级好的资源,很值得参考学习,对我启发很大,支持!
神仙别闹
- 粉丝: 3785
- 资源: 7469
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 汇编语言安装文件:nasm-2.16.03
- Java 插件框架 (PF4J).zip
- image-svnadmin-2.5.3.tgz 正在使用ing,方便简单使用,运维好工具
- 地平线ros2文件.zip
- Java 多线程课程的代码及少量注释.zip
- 数据库课程设计-基于的个性化购物平台的建表语句.sql
- 数据库课程设计-基于的图书智能一体化管理系统的建表语句.sql
- Java 代码覆盖率库.zip
- Java 代码和算法的存储库 也为该存储库加注星标 .zip
- 免安装Windows10/Windows11系统截图工具,无需安装第三方截图工具 双击直接使用截图即可 是一款免费可靠的截图小工具哦~
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功