摘 要:斗地主游戏系统开发使用的是C++语言,系统使用了C/S架构。本系统建立在局域网之上,主要就是建立一个服务器用来存储数据,然后通过服务器和客户端之间的通信来实现游戏过程。此游戏系统主要包括建立服务器、建立客户端与服务器的链接、定义纸牌、发牌、抢地主、出牌、纸牌大小比较等功能。其中利用网络编程相关知识,实现三次握手四次挥手,同时还可以解决客户端与服务器之间的链接问题。实现定义纸牌模块与发牌、抢地主模块,通过定义一个K值,取1-54的数字代表整副纸牌,然后加入TYPE、NUM等变量解决出牌和纸牌牌面大小比较算法。由于受时间及技术娴熟程度的限制,其功能有待进一步完善;但游戏画面简洁明了,可进行傻瓜式操作,具有可玩性较高,流畅度高的优势。
关键词:C++;桌面游戏;斗地主游戏
中图分类号:TP317 文献标识码:A 文章编号:2096-4706(2018)11-0081-03
The Design and Implementation of the Game of the Bucket Landlord
ZHAO Juan,YI Gaizhen
(School of Computer Science,Xianyang Normal University,Xianyang 712000,China)
Abstract:The Landlords game system is developed using the C++ language,and the system uses the C/S architecture. The system is based on LAN,mainly to establish a server to store data,and then through the communication between the server and the client to achieve the game process. The game system mainly includes the establishment of servers,the establishment of client-server links,the definition of cards,licensing,landlords,cards,card size comparison and other functions. The network programming knowledge is used to realize three handshakes and four waving,and the problem of link between client and server can be solved. Realize the definition of card module and licensing,landlord robbery module,through the definition of a K value,take 1-54 digital representation of the whole deck of cards,and then add TYPE,NUM and other variables to solve the card and card size comparison algorithm. Due to the limitations of time and technical proficiency,its function needs to be further improved,but the game screen is concise and clear,can be foolish operation,with high playability,high fluency advantages.
Keywords:C++;table games;bucket landlords game
0 引 言
实现斗地主这个游戏的方法有很多,C/C++/JAVA等都可以在自己的平台上实现,并且各有其特点和优势。此游戏主要基于C++,首先需要对其运行机制与界面元素进行控制。在此基础上,斗地主游戏主要依赖于后台的算法。C++的文件读取不同于Android,Android读取文件需要一个继承Activity的类,并且只能对属于自己程序的文件进行操作,如果是原始文件则需在raw文件夹下,对其在Android中所对应的ID进行操作,但C++只需要知道文件目录任何一个类就可以对文件进行操作,所以使用C++编写该游戏系统有一定的便捷性[1]。
1 游戏设计中的数据结构及开发流程
初始化游戏的基本属性:
(1)主加载方法;
(2)NEW3个新的角色,代表玩家;
(3)NEW出54张牌,用i值(1-52)代表1-13的牌,53、54代表大小王;
(4)获取54个不同的随机数;
(5)NEW出牌的图形,使用(i-1)%4表示花色;
(6)排序--牌;
(7)排序--牌(按照4张、3张、2张、1张的顺序);
(8)排序--牌图形;
(9)把牌的值添加到每个角色中;
(10)开始发牌。
游戏实现流程如图1所示。
按照斗地主游戏约定俗成的规则,使用算法编写对玩家出的牌进行检验的代码,判断其是否符合出牌规则。思路:将玩家的牌按从小到大的方式排序,然后把牌拆分开来,分别存放于4个数组中,拆分规则如下:
假设有牌:333\444\555\789
则拆分后数组中的数据如下:
arr[0]:345789
arr[1]:345
arr[2]:345
arr[3]:1
可以看出拆分规则是:如果遇到相同数字的牌则存到下一个数组的末尾。
拆分完后可以根据各数组的存储情况判定玩家出牌的类型,上面的例子中的arr[3]为空可以排除掉4带1(2)、炸弹的情况,根据arr[2]为顺子且个数大于1,且arr[2]中存放的牌的张数乘以3刚好等于arr[0]的张数+arr[1]的张数,则可以判定是三带一的飞机。如果不是,那就判定为不符合出牌的规则,系统会判定出牌失败,需要重新选择别的牌。
2 游戏规则及相关算法设计
本游戏叫作斗地主游戏,其游戏规则为玩家三人,地主为一方,其余两家为另一方,双方对战,先出完手中牌的一方胜。游戏中的每个玩家都可以起昵称,使用类name中的Cname方法给后台传输玩家ID及其玩家地址IP,Cname方法传入一个指针参数,然后定义初始化玩家昵称为“路人甲”。当玩家运行程序后,弹出是否建立主机白框,如果建立主机,自己的IP地址为172.0.0.1,然后输出自己的昵称,创建好主机后等待玩家加入,当玩家凑齐三人且三人都准备好之后就可以开始发牌。创建及加入房间主要是由server类中的CServer方法实现,主要需要传入的参数即玩家IP及玩家昵称,当玩家选择是否创建主机即view类中的if语句来进行判断时,创建就进入server类中传入双参。而玩家加入则是由net类进行链接,net类中的CNet方法主要用于链接玩家和主机,其中包含3层if,判断是否在同一台机器、是否在同一个局域网、玩家和主机是否能链接,先判断是否在同一台机器,如果是则进行链接,如果不是就判断是否在同一个局域网,如果是则链接,不是则判断是否可以链接,再次判断为否时则提示链接失败。
定义一副纸牌即定义一个变量k,用1-52来表示四种不同花色的1-13的纸牌,用53、54分别表示小王大王,用((k-1)/4)表示牌号,然后发牌。
游戏规则(一副牌规则):
(1)发牌:扑克牌发牌算法包括定义纸牌算法和发牌算法本身,定义纸牌算法:先定义一个int型变量k,初值1,最大54,其中1-13定义为3、4、5、6、7、8、9、10、J、Q、K、A、2这13张牌,1-52是定义为4套A-K,其中用k/13得出来的0、1、2、3代表四种花色,53、54代表小大王。然后根据随机函数random来给定义的三个玩家数组分配1到13的17张牌,使用for循环来进行分配,如果分配的数字相同的纸牌数量超过4张则跳过本次循环重新分配。
(2)叫地主:谁拿到了红桃三谁先叫地主,使用一个if语句判断3个玩家的手牌数组中有没有K/4=1且K%13等于3的牌,有则先手叫地主,叫地主时可以叫“1分”“2分”“3分”“不叫”。而且每次叫地主只可以比上一次叫地主的人叫的分数更大,或者不叫,使用一个if语句判断这个玩家叫的分数是否大于上个玩家叫的分数,大于则叫牌成功,小于或等于则使用printf返回提示“请重新选择更大的分数或者不叫”。叫地主结束后所叫分值最大的玩家为地主;如果有人直接叫了3分,则直接成为地主;如果三个人没人叫地主,那就洗牌重新开始。使用一个for循环,循环3次,然后用if语句判断这个人是否比上个人叫的分数大,再用if语句判断是否到了3分,到了就直接结束if循环,输出叫3分的人为地主。
(3)出牌:成为地主之后可以得到三张底牌,但是需要展示给其他两人观看,即成为地主则他的数组大小为20,由地主第一个出牌,然后逆时针下一个出牌,到谁出牌就选择好想出的牌然后点击出牌按钮,没有就点击过牌。每一位玩家的纸牌都存储在名为card的数组当中,加入判断语句判断是否为地主,如果是地主则数组大小变为20,然后出牌则是一个循环,循环出牌,然后看谁的数组先为空,则胜利。
(4)游戏规则:王炸:就是双王(大王和小王),两张牌一起出什么牌都可以吃。即k值为53+54的时候,k值为最大,任何牌都可以吃掉。
炸弹:四张一样数字但不同花色的牌(如四个10)。
单牌:只出一张(如红桃5)。
对子:数字一样但花色不同的两张牌(如梅花4+方块4)。
三带一:数字相同的三张牌带着一张单牌或者一个对子。例如:333+7或444+99
顺子:K%值连续的五张牌但最大不可以是双王和2。
姐妹对:K%值连续并且每个值都有俩个的牌,姐妹对中不带双王和2。
飞机:两个连续的三带一(如:333444、5556667778 88)。飞机中不带双王和2。
四带二:炸弹不以炸弹的方式出牌,而是带着两张单牌或者两个对子。如:5555+3+8或4444+55+77。
牌面大小判定的算法如下:
(1)定义一个函数,有三个参数num、min、type。num表示出牌有多少张,min表示起作用的牌,type表示出牌类型。比如说对子type值是1,顺子是2,3带1 type值是3,4带2 type值是4,炸弹type值是5,王炸type是6,其中type值是5和6的可以吃掉type值为1、2、3、4的四种出牌,而type值6的则可以直接吃掉全部,也就是最大的。
(2)在纸牌大小比较中主要依靠的就是使用k%13值大小比较,k%值大的则牌面更大,如果是对子就比较单张k%值的大小,顺子则比较最后那张牌的k%值的大小,3带1比较3张一样牌k%的大小,4带2比较4张一样的。炸弹和其他的牌比较就用type值,和同样炸弹比较也是用k%13值,王炸则直接是最大的,使用type值的判断等级更高。
(3)牌面大小比较:王炸最大,能吃掉任何其他的牌。炸弹比王炸小,比其他牌大。同样是炸弹,谁的牌上数字大谁的炸弹就大。除了炸弹,其他大小比较需要在出牌数量相同的情况下才可以进行。单牌按牌面数字大小进行比较,也就是按照k%13的值的大小进行排列,k%值越大则牌面越大,依次是大王>小王>2>A>K>Q>J>10>9>8>7>6>5>4>3。对子和三带一都按照牌面数字大小进行比较。顺子按照顺子的最后一张牌的大小进行比较。飞机和四带二是按照其中三张一样的牌的牌面数字大小和四张部分来比,带的牌不影响大小。胜负判定是看谁先出完,如果地主先出完就地主胜利,其他俩人无论谁先出完都是地主失败。使用if语句判断哪个玩家的数组先为空,如果地主手牌数组先为空则弹出提示地主胜利,反之则弹出农民胜利。
3 结 论
斗地主游戏设计主要从游戏的数据结构和游戏规则的实现方面来说明整个实现过程。其中还有很多不足,例如在游戏算法中,可以更深层次地应用贪心算法和剪枝算法,既能找到最优解还能提高算法效率[2]。这些都是在今后的开发中需要注意的方面。
参考文献:
[1] 潘正辉.基于Android系统手机游戏的设计与开发研究 [J].电子世界,2016(13):128+130.
[2] 李竹林.基于Android系统的斗地主游戏的设计与实现 [J].河南科学,2015,33(2):200-203.
作者简介:赵娟(1975-),女,汉族,四川成都人,教师,讲师,硕士研究生。研究方向:软件工程。