淘宝斗地主残局玩法技术方案汇总
项目介绍
当前互联网应用一个非常重要的方面就是内容建设,通过内容吸引用户。对于我们来说,它是每天吸引用户打开淘宝的动力。希望用户每天点击淘宝都能看到——我现在很好。然后打开淘宝拿点金币,去淘宝生活,玩斗地主,打麻将,看看淘宝乐园的小游戏等等。
笔者这次以斗地主为例。作为棋牌游戏,它针对的人群广泛,具有很强的即时满足感。一场游戏两分钟就能玩完,上下班、食堂、卫生间等碎片时间也能玩。这类互动内容的建设,为淘宝提供了巨大的用户成长和成长的机会。在用户使用时间方面带来了一定的好处。
斗地主的玩法和规则相信大家都知道,这里就不多说了。淘宝斗地主目前拥有经典玩法、炸弹房、实体大奖赛、好友对战等游戏模式。还形成了任务中心、钻石一点等交易所、道具商城的运营体系。但游戏想要继续吸引玩家,就必须不断引入新的。
因此,我们需要在经典玩法的基础上探索新的玩法,就像9月份爆火的《羊了个羊》游戏一样。针对这种解密、闯关的游戏,我们制作了斗地主的残局玩法。你可以想象国际象棋的残局。同样,双方都可以看到对方的牌,玩家的获胜路线也是独一无二的。玩家面对从不犯错的AI,从敌我复杂的卡牌中,在重重障碍中找到获胜之道,获得击败AI的成就感。作为斗地主部分玩家的双十一活动,残局为玩家尤其是高端玩家提供了新颖的游戏体验。后期则充当对外招商的“钩子”,希望能够吸引更多感兴趣的玩家,吸引新玩家并进行转化。
残局目前以活动形式推出,每天的关卡都不同。欢迎大家每天来挑战~
项目分析
经典斗地主模式分为以下几个阶段:
配对——发牌——叫地主——加倍阶段——打牌阶段——结算
在经典的游戏玩法中,玩家使用HTTP 请求来打牌,并使用套接字将牌推送给三个玩家。然而,残局玩法实际上是用户和AI之间的一对一的打牌场景。根据地主的出牌规则,按照出牌规则进行出牌;残局玩法是玩家与AI之间的战斗,不涉及多人匹配;同样,由于是单人游戏,不涉及异步请求或游戏推送问题,因此不需要长链接。不需要使用socket来推送游戏信息,只需在玩家每次出牌时使用HTTP请求服务器即可;在经典玩法中,托管机器人使用延迟消息来推进游戏,并且没有托管或残局提示。不需要使用消息来提前请求算法;残局没有抢地主、翻倍等阶段,业务逻辑会比经典玩法简单。系统需要保证的是游戏能够按预期进行,尤其是有时候会出现各种超时或者依赖下游抖动,无法阻挡玩家。
商业思维
首先是定义我们的斗地主结局是什么,以及如何确保游戏具有挑战性和趣味性。
流程概述
触发活动,获得当日卡牌游戏
游戏要求:玩家必须有机会获胜,但出牌获胜的方式只有一种;制作的卡牌游戏必须保证某一步是唯一的解决方案。不可能发生用户无论如何都能赢AI的情况,也不可能发生无论如何都赢不了AI的游戏。
进入游戏
进入游戏后,只有玩家和AI对手两个角色,双手的牌直接显示。
用户打牌
游戏开始后,直接进入打牌阶段。玩家是第一个玩的。比赛过程中,玩家这边没有设置倒计时。每一步都没有超时,他们可以无限期地等待。
AI和用户轮流打牌
每当玩家出牌时,AI都会有5S倒计时时间出牌。 AI每次出牌时,AI会间隔1到5S随机出一张牌。
AI卡策略
当玩家打出一张牌并走上“获胜”的道路时,AI需要尽力确保后续打出的牌只有一种策略【如果AI认为是,则无法打掉它会输]
当玩家的牌打法不是“获胜”路径时,AI需要使用合理的牌序策略来击败玩家【只要玩家犯了错误,他就输了】
如果一方完成,则进入结算。
直到双方其中一方打出自己手上的所有牌时游戏结束,AI打完所有牌后用户输,否则玩家获胜。
当用户击败AI时,可以获得相应等级的奖励(通常是斗地主道具或者豆子、钻石),从而吸引用户在其他游戏中使用它们,从而延长用户的游戏时间。
游戏保留逻辑
玩家的游戏缓存会保存一定时间。中途退出后,游戏不会自动主持。游戏将当场保存。用户当天的下一次挑战将从上次结束的地方继续,除非用户手动点击重新开始或游戏进入结算。
手牌选择和更新的原则
要求用户短时间内(30天内)不遇到重复的卡牌游戏;
半夜12点玩游戏的用户较多,所以每日关卡改为凌晨5点刷新。
功能上的挑战
自动生成卡牌游戏:如此大量的残局无法手动产生,需要通过训练生成,并且残局要求卡牌强度相等。对于用户来说,有少量必胜路径(1到2),尤其是大规模高质量的残局。产生用户请求是很困难的。如何保证当天的关卡不重复并且有一定的容错能力。卡牌游戏信息存储的选型和可扩展设计,最大限度减少缓存占用。高度依赖AI卡的稳定发挥,尤其是通话量大的情况下。为确保高可用性和高性能:准确度高:100%准确度;当用户走上获胜路线时,AI可以合理出牌;当用户犯错时,AI可以100%反击; b.高性能:AI打牌低Delay; c.掩盖能力:当AI不可用时,服务器必须具备掩盖能力,不能屏蔽用户。设计时考虑交付和AB测试能力,增加多个降级和紧急离线开关以及掩盖工作数据表。数据分析能力、监控报警、数据仪表盘、灰度、可观察、回滚能力等。
技术方案及思路
技术模块拆解
1.用户触发活动2.获得今日等级3.用户与AI对战4.结算及奖励发放
系统链路图
技术模块拆解
游戏数据存储
一般储存方法:
单机内存、分布式数据库、分布式缓存
由于游戏更新频繁,在线玩家越多,并发量越大,对RT和性能越敏感。不过,系统不需要详细记录游戏的具体过程,也不需要采用永久存储的方式。综合考虑,基于Redis的缓存是目前比较合适的方法。
残局场景涉及两个缓存信息:
1、十张牌游戏信息同时作为触发标志。
存储包括挑战进度以及十场残局对应的信息(gameId;用户手牌;AI手牌)
2、用户当天挑战的游戏信息
用户触发活动逻辑
当用户进入斗地主首页时,会检查用户是否可以触发该Activity。如果在触发活动范围内,则判断疲劳程度,确定是否出现活动弹窗引导用户进入残局玩法。下图是用户进入首页时的验证触发逻辑:
这里设计中使用了两个开关,一个是通用活动开关,另一个是新用户触发开关;考虑到出现问题时能够提供一键降级的能力,还为操作提供了关闭新用户触发器的入口。
进入游戏并请求一手牌
每个用户每天十场挑战的级别是不同的。当用户点击开始挑战时,就会输入当天的挑战进度。此时会判断当天是否还有未完成的比赛。如果是,则会直接恢复到玩家上次离开时的状态。如果发现没有游戏缓存或者本关卡已经结束,则使用十个游戏缓存中的数据和进度信息初始化游戏并写入到一个游戏缓存中,用户开始本关卡的挑战。
值得注意的是,要求用户每天第一次进入一级挑战时请求今天的十级挑战,以避免上一步触发时调用算法,造成大量无用请求;为什么请求统一在这里而不是每个请求?关东请求算法:为了能够分配不同的卡牌策略,算法端的同学会根据不同的策略来筛选和分配卡牌。例如,A桶中的前5级是简单的,B桶中的奇数级是简单的,等等;并会尽力分解游戏,获取更多真实的用户挑战记录,以供后期数据分析。
前面提到,如何防止用户在一个月内请求同一个卡牌游戏,我最初想到的解决方案是通过布隆过滤器来实现。后来我简化了一个方案,将所有卡牌游戏分成了31个区域,每个区域自然就请求不同区域的游戏即可。
打牌并跳过
下面的框图显示了玩家的打牌逻辑。在调用算法接口获取AI打牌信息之前,会对用户的打牌情况进行预判。由于斗地主涉及多种异常信息,需要做很多异常信息的判断和处理,以及需要向用户公开哪些异常,例如:卡类型不符合要求(不是单卡) 、对子、三连、顺子、炸弹等),是否能压倒前一个玩家的牌,是否可以跳过(对手不想要的时候玩家不能跳过),该牌是否玩的是在玩家手里(防止直接刷界面)等
检查没有问题后,会将玩家本轮打出的牌、玩家剩余的牌、AI剩余的牌进行集合,并对请求进行打包。 RPC请求算法会获取本轮AI打出的牌,并在获取AI打出的牌后更新游戏信息。然后判断是否已结算。如果此时一方手牌为空,则等级结算;否则,游戏信息缓存将被更新,玩家将在下一轮中继续打牌。
结算逻辑:
设计上的考虑
算法不稳定的备份和掩盖解决方案,减少依赖
由于残局严重依赖算法端,如果请求算法出现问题导致无法获取今天的牌局,或者玩家出牌后无法获取AI出牌信息等情况,游戏将无法正常进行。将无法正常进行并且播放器进程将被阻塞。在实际联调过程中,发现调用过程中会出现算法侧报错或者RPC超时等问题。另外,本着不信任、不依赖的原则,一定要确定。面对这些问题,设计了以下解决方案:
1、配置监控报警,监控调用算法的时长和成功率指标,出现抖动时及时报警。
2. 设计掩盖计划:
第一层备份:将可能出牌的情况写入图数据库中。当未获取到算法侧返回的AI打牌信息时,会构造查询key直接查询图数据库。这样可以减少一些查询算法失败,直接到图数据库。第二层泄密:当数据库出现问题或者查询不到的时候,系统的业务逻辑会自己做一层泄密,根据当前手牌和出牌情况进行出牌双方的信息,但这个策略是自己实现的,所以打出的牌不保证100%符合机器人胜利原则。最终答案:当一切都不顺利时,选择最简单的方法。如果此时玩家出牌,机器人就不会出牌。如果玩家此时跳过,机器人此时不能跳过,选择自己的手牌。第一个。 【目前认为本游戏为玩家奖励游戏】
针对请求中可能出现的各种异常进行稳健的设计
斗地主之类的游戏场景与一般要求不同。端的渲染信息和服务器端存储的信息必须一致。但交互过程中可能出现的异常情况包括:
终端网络问题:
前端请求服务器失败,前端请求成功,服务器响应,但是网络出现问题。前端没有得到结果。服务器依赖的下游出现问题。
游戏缓存更新失败:游戏缓存更新超时并返回错误,但实际上更新成功。
上面提到的问题会有一个表现:用户打完一手牌后,前端没有得到请求的结果,或者得到打包异常。此时,本轮卡牌的渲染出现了问题。
如果这次对服务器的请求确实失败了,其实没有问题,用户可以重新玩;但麻烦的是,服务器去掉了业务逻辑,更新了缓存,但最后由于各种原因未能正常渲染,当玩家再次出牌时,会抛出异常,认为自己的牌在手牌已打完,这将阻止用户。因此设计了如下解决方案:
参考CAS的思想,在用户的每个请求参数中添加订单字段:这个顺序字段实际上就是游戏的回合。当请求的顺序与Redis中的版本不一致时,会直接返回最新的游戏缓存。最终重新渲染,玩家获取最新游戏信息; b.更新缓存时,会比较版本字段,只有匹配当前轮次才会更新缓存; c.每次缓存更新后,缓存的版本会自动+1,并且该版本将作为顺序字段,因此无需手动维护。考虑到缓存操作的多并发情况,更新时不会使用参数0强制更新,而是使用version字段进行更新。前端有状态锁防止连接点,出现特定异常时直接拉取最新卡牌游戏的逻辑
两个缓存状态一致性问题
这里涉及到两个缓存。理论上,这两种缓存都需要数据一致性,但Redis不具备传统的事务特性。两种状态想要实现强一致性几乎是不可能的,所以作者在设计时就考虑到了这一点。以下解决方案可确保玩家不会因数据不一致而被屏蔽或失去权益:
使用基于消息队列的重试方案。当更新缓存发生异常时,将发送一条MQ消息。使用消息重试机制来保证缓存更新尽可能成功。配置监控报警,检查用户进入游戏时状态是否不一致。将打印错误日志。如果当前游戏的缓存更新失败,其实此时已经向上抛出了异常,十个游戏的缓存中的进度信息将不会被更新。此时用户测试中的表现:如果上次出牌失败,则可以重新打出最后一手牌,并重新结算;如果本次游戏的缓存更新成功,但是十场游戏的缓存中的游戏进度更新失败,此时用户端的表现是:本次结算失败,玩家手动重试并返回结算逻辑;奖励发放结构是幂等的,保证当天完成同一游戏的用户奖励不会重复发放,不会出现资金损失。问题:在数据库中记录每场比赛的状态,可以通过定期扫描表检查是否有问题来进行对账。
沉淀数据和信息来衡量游戏的难度和投放策略
当游戏结束(结算或用户选择重新开始)时,游戏中玩家和AI的出牌记录、玩家挑战次数、挑战时长、进度等信息都会打印到日志并通过日志同步在数据平台中,联合算法将不同玩家的卡牌分配策略表连接起来,以确定什么样的分配策略可以提高用户的停留时间和留存率。它还用于分析如何衡量不同的残局难度,并为未来提供固定级别的卡牌。局方选择沉淀信息。
总结
用户评论
我在淘宝找到了一个斗地主残局玩法解决方案,真的是打开了新世界的大门!
有11位网友表示赞同!
这个淘宝上推出的斗地主技巧方案,让我在残局中逆转局势,胜率大大提升。
有14位网友表示赞同!
尝试了这个斗地主的淘宝独家版策略后,发现残局不再是难以克服的难题。
有15位网友表示赞同!
不得不佩服,淘宝上的这个斗地主残局玩法分析,确实是高手进阶神器。
有9位网友表示赞同!
用上淘宝提供的这份斗地主技巧方案,在实战中多次成功翻转败局,超有成就感。
有6位网友表示赞同!
淘宝上找到了一份详尽的斗地主残局解决方案,每一步都清晰明了,新手也能学得会。
有5位网友表示赞同!
通过淘宝的学习资源,我掌握了斗地主游戏中的高级残局技巧,玩起来更得心应手。
有13位网友表示赞同!
最近在淘宝学到的斗地主残局策略帮助我在竞技中获胜次数大大提高,感觉像是获得了新技能。
有19位网友表示赞同!
这个淘宝斗地主残局玩法的技术总结真的很实用,对提升个人水平有很大帮助。
有19位网友表示赞同!
淘宝上分享的那个斗地主破解残局攻略,让我的游戏体验上升了一个档次。
有20位网友表示赞同!
得益于淘宝上的那份斗地主高阶教程,我在面对残局时不再慌乱。
有8位网友表示赞同!
在淘宝学习到的斗地主残局技术方案,让我从新手变成了可以应对各种复杂局面的老手。
有8位网友表示赞同!
使用淘宝提供的这个斗地主攻略后,我发现残局并不像我之前想象的那么难以捉摸。
有14位网友表示赞同!
淘宝上这份详细的斗地主要局解策略不仅理论讲解清晰,还有实际案例分析,超有帮助!
有6位网友表示赞同!
跟着淘宝教程玩斗地主,发现残局不再是我的弱点了,反而成了我的强项之一。
有5位网友表示赞同!
淘宝的斗地主残局玩法技巧分享让我从失败中找到了进步的方向,游戏体验大大提升。
有15位网友表示赞同!
在淘宝学习到的各种斗地主残局策略,帮助我在比赛和日常游戏中保持优势。
有12位网友表示赞同!
淘宝上那个详尽的斗地主高分攻略真是救了我,在面对复杂局势时不至于乱了阵脚。
有15位网友表示赞同!
凭借淘宝上的技术指南,我在斗地主残局中找到了破解之法,整体水平明显提升。
有19位网友表示赞同!
通过淘宝平台了解的这些斗地主技巧,让我在玩残局的时候更有信心,胜率大大增加。
有12位网友表示赞同!