- 游戏概述 {#1-游戏概述} =================
1.1 游戏简介 {#1-1-游戏简介}
"斗地主"是流行于湖北一带的一种扑克游戏,玩法简单,娱乐性强,老少皆宜。据传在万恶的旧社会,地主横行乡里,无恶不做,人们为了发泄对地主的痛恨,常常在一天的劳作之后,一家人关起门来"斗地主"。
1.2 游戏类型 {#1-2-游戏类型}
V1.0 版游戏是第一个版本为单机版,主要是用户和机器人对战。
后续会开发出网络版......
- 游戏规则 {#2-游戏规则} =================
不同地域游戏规则可能有些许差异,游戏按照如下规则进行实现。
2.1 牌型 {#2-1-牌型}
| 牌型 | 描述 | |:-----:|:-------------------------:| | 王炸 | 大王+小王,最大的牌 | | 炸弹 | 四张同数值牌(如四个 9) | | 单牌 | 单张的牌(如红桃 3 ) | | 对牌 | 数值相同的两张牌(如梅花 4+ 方块 4 ) | | 三张牌 | 数值相同的三张牌(如三个 Q ) | | 三带一 | 数值相同的三张牌 + 1张单牌,例如: 333+6 | | 三带二 | 数值相同的三张牌 + 1对牌,例如: 666+33 | | 顺子 | 五张或更多的连续单牌,不包括 2 和双王 | | 连对 | 三对或更多的连续对牌,不包括 2 和双王 | | 飞机 | 二个或更多的连续三张牌,不包括 2 和双王 | | 飞机带翅膀 | 飞机+同数量的单牌(或同数量的对牌) | | 四带二 | 四张点数相同的牌 + 两手牌 (两单或两双) | | 王炸带二 | 王炸 + 两手牌 (两单或两双) |
2.2 牌型的大小 {#2-2-牌型的大小}
-
王炸最大,可以压任意其他的牌型。
-
炸弹比王炸小,比其它牌型大。都是炸弹时按牌的点数比大小。
-
除火箭和炸弹外,其它牌必须要牌型相同且总数量相同才能比大小。
-
单牌按点数比大小(不分花色),依次是:
大王 > 小王 > 2 > A > K > Q > J > 10 > 9 > 8 > 7 > 6 > 5 > 4 > 3
-
对牌,三张点数相同的牌都按点数比大小。
-
顺子按最大的一张牌的点数来比大小。
-
飞机带翅膀和四带二按其中的三顺和四张部分来比,带的副牌不参与牌型大小的比较。
2.3 游戏角色 {#2-3-游戏角色}
参与游戏的玩家一共需要三个人,这三个人有两种角色,分别是:
- 地主:1人,三人下注抢地主,分数最高者可称为地主,地主自己一伙。
- 农民:2人,没有抢到地主的玩家为农民,此二人一伙。
2.4 游戏规则 {#2-4-游戏规则}
-
发牌
一副牌 54 张,一人 17 张,留 3 张做底牌,在确定地主之前玩家不能看到底牌。
-
叫地主 / 抢地主
- 叫地主按出牌的顺序轮流进行,每人只能叫一次。
- 叫地主时可以叫 "1 分 " , "2 分 " , "3 分 " , " 不叫 " 。
- 后抢地主者只能叫比前面玩家高的分或者不叫。
- 抢地主结束后下注分值最大的玩家为地主;如果有玩家叫 "3 分 " 则立即结束叫地主,该玩家为地主;如果都不叫,则重新发牌,重新叫地主。
-
第一轮叫地主的玩家
- 由于是单机版斗地主,直接指定了用户玩家为第一个叫地主的玩家
- 也可以由系统随机选定
-
出牌
- 将三张底牌交给地主,并亮出底牌让所有人都能看到。
- 地主首先出牌,然后按逆时针顺序依次出牌,轮到用户跟牌时,用户可以选择 " 不出 " 或出比上一个玩家大的牌。
- 某一玩家出完牌时结束本局。
2.5 游戏的胜负 {#2-5-游戏的胜负}
任意一家出完牌后结束游戏,先出完牌的玩家代表的角色获胜:
- 地主先出完牌地主获胜
- 任意一个农民先出完牌则农民获胜
2.6 游戏计分规则 {#2-6-游戏计分规则}
- 底分:叫地主时的下注分数,可下注分数分别为:1分、2分、3分。
- 倍数:初始为 1 ,每出一个炸弹或王炸翻一倍(留在手上没出的不算)。
当一局游戏结束后,基于低分和倍数计算个玩家得分:
- 地主胜:
- 地主:
2 * 底分 * 倍数
- 农民:
- 底分 * 倍数
- 地主:
- 农民胜:
- 地主:
-2 * 底分 * 倍数
- 农民:
底分 * 倍数
- 地主:
在实现的游戏代码中,没有处理春天的情况(一个玩家牌已出完,另外两个玩家的牌一张未出),如若需要,可自行添加。
- 游戏相关的类介绍 {#3-游戏相关的类介绍} =========================
此单机版游戏共需要 7 种类型的类,依次为:卡牌类、玩家类、窗口类、游戏控制类、线程类、游戏策略类、音频类。
3.1 卡牌类 {#3-1-卡牌类}
卡牌类有两个:单张卡牌类
和多张卡牌类
。
-
单张卡牌类 Card
游戏中的每张扑克牌都有属于自己的数据属性:花色和点数,通过这个类我们就可以存储和读取每张扑克牌的数据了。
-
多张卡牌类 Cards
在游戏的过程中,每个玩家手中都有多张牌,此类对各个玩家游戏过程中手中的牌进行了管理
3.2 玩家类 {#3-2-玩家类}
游戏中的玩家类有三个,分别是:玩家类,机器人类,用户玩家类。其中机器人类和用户玩家类是玩家类的子类。
-
玩家类 Player
此类中定义了所有玩家共通一些属性和方法,比如:
- 属性:玩家的角色、玩家类型、玩家性别、玩家头像的位置等
- 方法:设置/获取玩家的姓名、性别、得分、角色;出牌过程中的玩家切换;玩家抢地主;玩家出牌等。
-
机器人玩家类 Robot:
- 继承父类属性和方法并重写父类抢地主和出牌的虚函数。
-
用户玩家类 UserPlayer:
- 继承父类属性和方法并重写父类抢地主和出牌的虚函数。
3.3 窗口类 {#3-3-窗口类}
- 游戏开始时加载动画窗口:Loading
- 游戏主窗口类 GamePanel
- 单张扑克牌窗口:CardPanel
- 每张扑克牌都对应这样的一个窗口对象
- 自定义按钮:MyButton
- 按钮美化处理
- 游戏主窗口中的按钮组窗口:ButtonGroup
- 给用户玩家抢地主、出牌使用
- 游戏分数面板窗口:ScorePanel
- 窗口右上角展示个玩家的得分
- 游戏结束玩家的成绩窗口:EndingPanel
- 游戏结束后弹出,显示各玩家成绩
- 出牌倒计时窗口:Countdown
- 用户玩家出牌倒计时,超过20未出牌,系统默认不出,直接跳过
- 特效动画窗口:AnimationWindow
- 王炸、炸弹、飞机、顺子、连对等
3.4 游戏控制类 {#3-4-游戏控制类}
游戏控制类 GameControl 是游戏中比较重要的一个类,它管理控制着游戏中的很多核心数据:
-
玩家对象的初始化
-
所有扑克牌数据的初始化
-
游戏状态:发牌、叫地主、出牌
-
玩家状态:考虑叫地主、考虑出牌、某个玩家获胜
-
游戏数据:玩家卡牌数据、玩家下注和分数翻倍数据、玩家的得分
-
游戏重置和发牌
3.5 游戏策略类 {#3-5-游戏策略类}
游戏中的游戏策略类一共有两个:出牌类和出牌策略类
-
出牌类 PlayHand
针对于斗地主的游戏规则,可以对玩家手中的牌进行牌型以及点数信息的获取,并且可以基于斗地主的游戏规则对排序进行大小的比较。
-
出牌策略类 Strategy
此类用于制定出牌策略,是整个项目中逻辑最复杂,代码量最大的一个类,通过这个类实现的一系列算法可以根据实际情况实现机器人玩家的叫地主 / 抢地主功能、机器人玩家的出牌功能。
当然通过这个类也可以实现非机器人玩家出牌的托管功能,由于游戏是单机版,添加非机器人玩家的出牌托管意义不大(三个机器人斗地主,呵呵。。。)。
3.6 线程类 {#3-6-线程类}
游戏中的线程类一共有两个,分别是抢地主线程类和出牌的线程类。
-
抢地主的线程类 RobotGrapLord
机器人玩家抢地主创建一个子线程,抢地主结束销毁这个子线程。
-
出牌的线程类 RobotPlayHand
机器人玩家出牌创建一个子线程,出牌结束销毁这个子线程。
由于涉及到线程的频繁创建和销毁,后续会将此处修改为使用线程池实现。
3.7 音频类 {#3-7-音频类}
游戏音频类 BGMControl 主要用于控制游戏中各种音乐的播放:
- 背景音乐
- 抢地主 / 叫地主 提示音乐
- 发牌音乐、选牌音乐
- 牌型、点数提示音乐
- 剩余牌量(只剩一张或两张时)提示
- 游戏主要组件 {#4-游戏主要组件} =====================
要完成此游戏的开发需要开发出如下三大组件:卡牌、玩家、窗口。
4.1 卡牌 {#4-1-卡牌}
作为一款卡牌游戏,开发这块游戏首先要准备的就是卡牌相关的信息,主要分为两部分:
-
卡牌窗口
- 游戏中的每张扑克牌都是一个窗口对象,这样才能实现在主窗口中的移动,以及相应鼠标事件,最终实现扑克牌的点选和框选功能。
- 每个扑克牌窗口都有属于自己的属性信息:
- 承载数据:花色、点数
- 展示:正面、背面
- 所有者
- 状态:选中、未选中
-
卡牌数据
卡牌数据对应两个类,基于面向对象的思想,按照最小的粒度对功能进行归类,以降低代码的耦合度,让程序更容易维护。
- 单张卡牌类:为每个扑克牌窗口对象存储数据(花色、点数)
- 多张卡牌类:管理游戏过程中各个玩家手中的牌
- 游戏开始阶段:发牌
- 游戏进行阶段:出牌
- 多张扑克牌的点数管理
- 多张扑克牌的数量管理
- 多张扑克牌的排序
4.2 玩家 {#4-2-玩家}
关于游戏玩家可以从两个角度进行分类,以方便在程序中进程处理:
-
玩家属性
- 玩家的名字、分数
- 游戏结果:赢了、输了
- 游戏角色:地主、农民
- 玩家性别:男、女
- 玩家头像的显示方位:左、右
- 玩家的类型:机器人、非机器人
-
游戏控制
-
用户玩家通过主窗口自主完成操作
- 叫地主 / 抢地主、出牌、不出牌
-
机器人玩家通过启动线程按照提供的算法完成操作
- 叫地主 / 抢地主、出牌、不出牌
-
4.3 窗口 {#4-3-窗口}
在项目中,除了游戏主窗口,还有若干子窗口,有了多个子窗口的参与才能得到一个完整的主窗口:
- 按钮组窗口(用户玩家叫地主和出牌)
- 卡牌窗口(展示玩家的扑克牌信息)
- 分数面板窗口(展示各个玩家的当前得分)
- 成绩面板窗口(游戏结束,展示三个玩家的成绩)
- 游戏特效窗口(展示特殊牌型的特效动画)
- 游戏控制 {#5-游戏控制} =================
游戏控制类可以理解为程序的神经中枢,通过这类可以将项目中所有的类统筹协调起来实现类与类之间的联动。
关于斗地主游戏的控制主要分为以下几类:
- 游戏状态控制
- 玩家状态控制
- 玩家的创建和管理
- 叫地主/抢地主
- 发牌
- 出牌
- 玩家分数管理
- 游戏的重置
以上列举的任何一种情况都会在游戏控制类的协调下完成类与类之间的数据传递或者事件传递。
- 福利 {#6-福利} =============
关注微信公众号,回复 斗地主
领取项目代码,通过微信公众号也可以观看所有B站视频呦。