45岁码农用不到2年时间撸出100款扑克游戏

发表于2020-08-03
评论1 7.5k浏览

前言

扑克的玩法非常多,常见的就有斗地主、跑得快、五十K、锄大地、梭哈、十点半、二十一点、打千分、升级、拖拉机、双扣、保皇、斗牛、挖坑等等。在国内的不同地方,同类游戏的玩法也有不同讲究。粗略估计,国内的扑克玩法,超过上百种。

要短期内开发出这么多款扑克游戏,需要先对大多数扑克游戏进行系统的分析,归纳总结,然后打造一条流水线,每一款游戏都使用相同的框架,使用通用的零组件,等等。

本文主要内容就是讲述这个设计过程。

1.算法库

扑克游戏的历史很悠久,能够广为流行的一个原因就是上手比较容易。就算在今天,如果说一个人没读过书就学不会打扑克,这没人会相信。所以我估计扑克游戏的算法,都是比较简单的。归纳一下,一般包括:

  • 牌的大小(包括数字、花色等);牌的数目和分数;判断几张牌相同或连续;
  • 还需要一些对一组牌进行操作的算法,比如取出、合并等等。

基于以上的分析,我们估计可以完成一套通用的扑克的算法库,能满足所有扑克游戏。最后实践证明,扑克算法库比预期稍微复杂一点,但仍在可接受范围内。

 

此外,我们很容易发现,很多流行的手游的玩法、功能层出不穷,开发团队频繁升级迭代。相反,扑克游戏的玩法相对固定,演化相对较慢。所以,在系统设计上,我们假定扑克游戏的数量有限,玩法有限,发展慢。这样的好处是流水线设计好之后,以后改动很小,维护工作量也比较小。

 

2交互UI库

扑克游戏可以归纳出3个核心要素:牌、规则、人(玩家)。对扑克游戏的一种高度抽象的描述是:按照一定的流程和规则,每个人通过选择选项、选择牌、选择数值,来争取获胜的一种游戏。

归纳了一下,玩家的行为包括以下3种:

  • 对游戏流程中的选项,做出选择
  • 按照游戏规则,对牌进行选择。
  • 对数值(分数)进行选择。

比如斗地主中的叫地主、不抢,都是玩家自己要做的一种选择。出牌的时候选择不出,也是一种选择。后续会将“选项”称之为“命令”。

比如选择要出的牌,分组摆牌等。

比如下注。

 

以上三种玩家的行为,决定了游戏客户端需要提供哪些业务级UI库,对应下面几种:

  • 一组按钮
  • 选牌或牌分组的UI
  • 选择数值的UI

由玩家选择其中一个按钮;在业务层,称为命令选择器

允许玩家在一组牌中选出符合要求的牌。牌分组UI则允许玩家将牌放入不同分组或按不同顺序排布。这2种在业务层都称为牌选择器

可以用滑动条,也有用按钮的。在业务层称为值选择器

 

以上我们抽象出了扑克游戏的3个核心要素,以及玩家使用的3类UI。现在我们思考一下扑克游戏还需要哪些UI。

除了牌、规则、人,实际上我们还需要房间(桌子)、椅子(座位)。

一款扑克游戏有很多界面、子界面;我们大体将其分为:房间内,房间外。房间内就是一个桌面,UI都显示到桌面上。房间外包括一些扑克游戏的常用界面和功能:注册、登录、用户信息;房间列表;查询(分数记录、排名等);其他比如:公告、帮助、设置。这些都可以做成通用的几套,不同游戏选择其中的一套即可。房间内除了3类选择器,还需要下面一些界面UI:座位、牌(比如公共牌、出牌)、定时器、图片(比如筹码)、文本(用于显示数值或文字)。这里除了一些业务级别的UI对象,也包含一些基础的UI对象。

3管理员与通讯库

现实中,几个朋友坐一桌打扑克的时候,每个人都按照流程和规则来,大家共同监督。而对于线上的扑克游戏,其实有一个规则执行者,不妨称之为管理员(我们前面将选项称之为“命令”,可以理解为:管理员下达出牌的命令,由玩家选择出牌还是不出。所以,“选项”是站在玩家角度,“命令”是站在管理员角度)。那么前文的说法,可以进一步升级为:扑克游戏就是由管理员控制一套流程规则,特定的时候交由玩家来选择选项、选择牌、选择值,这样一种竞赛游戏。这里我们引入了管理员的概念。

下面说通讯库:

几个朋友坐一桌打扑克的时候,比如发牌,每个人收到的牌,其他人不能看到;再比如一个人出牌,是要给其他人看到。现实中打牌,我们是靠视觉来看,相当于靠光线传播数据(图像),而对于网络游戏,则需要的是一个通讯库通过网络传输数据。我们不能仅仅提供一个简单的基于socket、websocket、http封装(比如常见的封装接口有 read_cmd,read_version,read_int,read_string....),这太底层了,我们需要的是一个业务级别的通讯库。

比如你跟你老婆说:晚上加班要11点回去,你老婆说“好的”。通讯库应该是这样的:

创建一问一答的异步请求,发给老婆;

请求分类是告假(晚上晚回);参数是11点;

答复选项是3种:好的;不行;超时;(如果你老婆不是话痨的话)

    再比如人事部给每个员工发短信,内容是本月工资明细。通讯库就是群发短信,格式相同,但内容不同。

 

通过分析一些扑克游戏,我们从这样几个层面进行设计抽象:通讯方向、是否应答、发送目标、单发还是群发。其中:不需要答复的,我们叫通知;需要答复的,我们叫“命令”或“请求”。从客户端发向管理员,称之为“客户端请求”;从管理员向客户端发送,称之为“服务端命令”;最终,我们把通讯归纳成5种模板:客户端请求;服务端命令;服务端广播;服务端私有通知;服务端公开通知;

有了通讯库,我们需要往里面塞数据,数据包括:通讯类型名称、命令选项、数值、牌。实际上数据内容也正是对应了选择选项、选择牌、选择数值

举个例子:比如轮到一个玩家出牌了,我们使用服务端命令定义了一个出牌命令,这是一问一答的通讯,管理员发送时,不携带数据。客户端答复时,选项包括:出、不出;如果出牌,则需要携带出的牌。

再举一个例子:游戏结束时需要通知输赢,这时可以使用服务端公开通知,就是服务端给每一个玩家发送通知,通知内容是这一局输了还是赢了,赢了多少金币。那么,这个通讯中,携带的就是赢的金币(如果为负值,则表明是输)

总结一下:套用这5种模板,通过定义名称、携带的数据,来定义游戏中特定的通讯过程。比如拖拉机游戏中有以下几种通讯的定义:发牌公开通知、亮主请求、亮主结果广播、扣底牌命令、扣底牌通知、出牌命令、出牌结果广播、结算通知。此外所有游戏都会用到一些公共的通讯定义:坐下请求、站起请求、一局开始广播、一局结束广播、聊天等。

在通讯中,还涉及到数据对不同客户端的可见性的问题,这里就不再深入介绍了。

 

4流程

通过分析数十款不同特点的扑克游戏,整理了下面一种思路:

所有扑克游戏,在概念上,可以这样划分:

  • 一局
  • 阶段
  • 一轮

比如斗地主,从发牌,到出牌,到结束,这是一局。一局结束后,开始下一局。

一局游戏可以划分成几个阶段,比如发牌阶段,出牌阶段,结算阶段;

大多数扑克游戏都是每个人轮着来的。还有一些游戏(或者游戏中的某个环节)是允许抢先的(比如拖拉机的亮主)。在技术上,一轮就是一个异步循环,提供很多参数和控制。

 

以上是为了方便而从概念上划分的,并不绝对,使用这样一种套路,开发不同扑克游戏时,可以更加统一了。

 

5组装

到目前为止,我们已经完成了下面的成品模块、框架、零组件。

  • 一套扑克算法库
  • 房间内的UI库
  • 房间外的几套成品模块
  • 5种通讯类模板
  • 流程库

命令选择器;牌选择器;值选择器;头像、牌、图片、文本;

注册、登录、用户信息;房间列表;查询(分数记录、排名等);其他比如:公告、帮助、设置。

客户端请求;服务端命令;服务端广播;服务端私有通知;服务端公开通知;

提供一局、阶段、一轮等控制;

 

对于不同扑克游戏,我们首先要把游戏玩法弄清楚,然后用这些成品模块、框架、零组件,通过配置,通过编写一些代码来进行粘合,从而实现一个完整的游戏。

在实际的开发过程中我们验证了:对于简单的游戏,三五天就可以完成,对于极其复杂的游戏,一般在1~2周(比如拖拉机这类游戏)。这里说的是一个人,同时也包含自测时间。

 

为了提升粘合的效率,开发一个图形化编程工具,这里附上一些截图供参考:

 

  • 主界面
  • 函数库
  • 牌型算法的例子
  • 流程控制
  • 调试
tt1jEq6FW6Bs7KWqyok9.png

 

FSaiHqHKKGVhh6F8IVV2.png

    除了算法库、UI库以外,还包含了编程语言级别的函数、流程控制函数等。

    

cmREFjNAZDx46abfv9bD.png

有了这个工具,写牌型算法就快多了。

 

 

RDnx5dIoZprRXoIBjejo.png

这个图中的例子,包括了对一副牌进行洗牌,每次取出17张牌,在一个循环中,给每一个玩家发牌。下面是用英文显示函数的样子:

zlBhBHh8oc7F3ad1E7SN.png

    实际使用过程中,还是习惯英文编程。切换到中文相当于看看文档。

 

 

3ZoY12u38vD2u7Q1I7Tz.png

调试的时候,可以随时看一组牌是什么牌,这样很方便,对开发效率的提升很明显。

    

    以上介绍的图形化开发工具,已经具备的工程管理、图形化编程(编辑)、调试、发布、以及界面设置等辅助功能为一体的集成化开发环境。是图形化编程的一次有益的尝试。

6测试

技术人员自己可以搞定的测试是:单元测试;功能测试;性能测试(压力测试);

我们还请了专业的测试团队进行了游戏内测。

简单的公测:找老家亲戚朋友拉微信群,有些朋友人脉广,可以拉很多人。然后每天集中半小时搞一次测试,玩5局发10元红包,连续测试一周就差不多了。这种测试还挺有效,而且投入不大。

7进展

目前,项目已经基本达成了技术目标,所有扑克游戏使用了同一套算法库(C++代码使用emscripten 转为 javascript)、同一套UI库(html5/pixi.js)、两套标准的大厅,同一个服务器程序(C++),同一套通讯库(javascript)。另外还有:管理和监控后台;服务器更新;客户端更新;html5错误上报;C++错误上报等等。

除C++代码未开源,其他代码都开源了,文档齐全,放在 gitee上了,欢迎大家下载使用,欢迎提意见和交流。

(在html5浏览器兼容性方面有一些问题,比如UC浏览器、搜狗浏览器,特别需要熟悉这块的同学能给与一些支持!)

gitee.com/szcuipeng/public

后记

       作者是9年前误入游戏行业,也有幸在一家上市游戏公司担任技术副总监,并承担过游戏引擎主程的工作。其实我不是很喜欢棋牌游戏开发,如果有机会,我更想去加入古剑或河洛的团队中去学习。我大学出来后大部分时间里,从事的是GIS(地图编辑、空间分析、图形)开发,也有一部分跟AutoCAD有关,都是windows客户端。一个团队40多号人,开发企业用大型客户端,当时在国内也颇为壮观。现在看到米国禁止咱们大学用MATLAB,我也很想投入到这些领域中。

自己一直喜欢干技术,虽然早已是大龄,但也一直坚持干技术,是因为从大学时候起,就想在技术上干出一点名堂来。那时自己仰望一些技术大牛,就像小虾米仰望14本天书中的大侠一样,希望有一天像他们一样,成为技术界的侠之大者,成为对社会对行业有用的人。

 

风马 2020年7月

  • 允许他人重新传播作品,但他人重新传播时必须在所使用作品的正文开头的显著位置,注明用户的姓名、来源及其采用的知识共享协议,并与该作品在磨坊上的原发地址建立链接
  • 可对作品重新编排、修改、节选或者以作品为基础进行创作和发布
  • 不可将作品进行商业性使用

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: