掼蛋火爆出圈,游戏AI智能体或是棋牌界的“王炸”!以《欢乐掼蛋》为例,网易数智游戏 AI 智能体技术方案详细解析!(二)

带朋友们来回顾下上篇内容~今天,给大家带来AI 智能体技术方案详细解析!(二),欢迎大家关注点赞收藏👍

前段时间,360 公司董事长周鸿祎用个人账号在视频平台上发布一条动态:“红衣大叔成就解锁:万米高空掼蛋初体验”,视频中,他在前往美国的飞机上偶遇四位企业家,一同在万米高空玩掼蛋游戏。网友看了直呼:“这是一场千亿级别的掼蛋啊!”

(图源:网易视频)

掼蛋起源于江苏淮安,由当地的扑克游戏“跑得快”和“八十分”演化而来,在淮安方言里,“掼”是摔、砸的意思,打牌人将手中的“蛋”,即“炸弹”砸向桌面的动作,即为“掼蛋”。简单来说,掼蛋需要两副 108 张扑克牌,4 人两两组队进行,游戏规则综合了“跑得快”“八十分”“斗地主”等牌类游戏,哪队玩家最先出完手中的牌,即为胜。

淮安当地流传着一句话:“饭前不掼蛋,等于没吃饭;饭后不掼蛋,等于白吃饭!” ,从江苏火到全国,从体制内火到金融圈,掼蛋成为了新晋“社交密码”。游戏规则简单、容易凑到局、变幻莫测的配牌出牌方式,让每一局游戏都充满了悬念和挑战。这就是掼蛋独特魅力。

(图片来源:网络)

线下的掼蛋爱好者们打得火热,线上的掼蛋游戏也因方便、快捷等优点,成为大家休闲娱乐的热门选择。与其他手游相比,棋牌类型游戏更聚焦于玩家心态,是否能抓住玩家心理,是决定玩家留存率的关键因素,甚至能够直接影响游戏营收。

例如,在游戏上线初期、冷启动阶段或非高峰时段,如半夜,常常难以聚集足够的真人玩家,这限制了玩家的游戏体验。另外,传统的规则机器人缺乏智能性,无法提供有挑战性和策略性的对抗,玩家需求得不到满足,游戏体验感差,这直接导致用户留存率和活跃度的大幅下降。随着市场竞争的加剧,获取游戏新用户的成本也在不断上升,这对游戏公司的财务状况也构成了重大压力。

上一篇(一)请查看👇

掼蛋爆火出圈,AI智能体或是棋牌界的“王炸”!以《欢乐掼蛋》为例,网易数智游戏 AI 智能体技术方案详细解析!-CSDN博客文章浏览阅读851次,点赞9次,收藏19次。使用 3*14 的矩阵,对卡牌中的级牌信息进行编码,对于级牌分为两种:第一种是红心级牌:逢人配牌,可以变成大小王以外的任何牌,在组牌时点数不具有意义。掼蛋起源于江苏淮安,由当地的扑克游戏“跑得快”和“八十分”演化而来,在淮安方言里,“掼”是摔、砸的意思,打牌人将手中的“蛋”,即“炸弹”砸向桌面的动作,即为“掼蛋”。饭后不掼蛋,等于白吃饭!普通牌型的大小比较依据牌点数决定,通常 A 最大,2 最小,但同花顺中的牌型比较特殊,最小的同花顺是 A-2-3-4-5,最大的同花顺是 10-J-Q-K-A;_网易数智https://blog.csdn.net/weixin_43099039/article/details/138216234?spm=1001.2014.3001.5501

方案详情:

大规模预训练模型, 深度强化学习,深度模仿学习等技术开发的智能竞技机器人,带来更加真实的游戏体验,助力提升游戏品质。游戏AI智能体解决方案已落地多项游戏!欢迎大家前来畅聊探讨~

  • 方案详情可以👉 ✉ V:LTT936 
  • 或查看以下卡片点击按钮【立即咨询】👇

游戏AI竞技机器人 - 网易智企大规模预训练模型, 深度强化学习,深度模仿学习等技术开发的智能竞技机器人,为游戏玩家带来更加真实的游戏体验,助力提升游戏品质https://grow.163.com/solution/combat-robot?from=csdn_yxzy_0426

 领取干货资料:

03

动作空间定义

掼蛋的动作表示的是玩家根据当前手牌进行组合得到的合法动作,总共有十种牌型,分别是单张、对子、三张、三带二、三连对(也称为两连对)、钢板(三顺)、顺子、同花顺、天王炸和普通炸弹。

我们同样使用之前所定义的卡牌的矩阵表示对出牌动作的卡牌进行编码。然而,出牌者在决定出牌时不仅要考虑如何获得牌权,还需要思考出了这张牌之后剩余的手牌如何组合。因此,我们还扩充了在执行该动作后的手牌信息作为动作的一部分,如下表所示:

特征

大小

出牌

1*9*14

剩余手牌

1*9*14

04

二分类问题

为了使用模仿学习训练智能体,需要从游戏内部收集用户数据。通过玩家的评级来筛选比赛数据来获取高水平玩家的专家轨迹。通过将每一次出牌视为一个实例,并使用监督损失来训练网络。这个问题可以被形式化为一个分类问题,我们的目标是基于给定状态来预测专家采取的动作。

然而,在实践中大多数动作都是非法的,并且遍历所有可行动作的成本很高。受 Q 网络设计的启发,我们将问题转化为一个二元分类任务,智能体所需要做的是根据每个动作判断它是否是专家所执行的动作。然而,由于专家动作数量与负样本数量的极度不平衡,采取下采样的方法进行训练:

  • 正样本:专家执行的动作;

  • 负样本:从合法动作中随机抽样,且保证 pass 和逢人配牌的负样本存在。

05

模型训练

1.网络结构

在构建智能掼蛋 AI 的过程中,对网络结构的设计与优化至关重要,特别是在处理复杂多变的状态-动作信息时。为了充分提取并利用这些蕴含丰富时序特征的数据,我们采用了精心设计的前置处理步骤,以确保主网络能够高效且精准地进行决策。具体而言,我们实施了两种关键操作:Inter-group Regularization(组间正则化) Channel-wise Attention(通道注意力机制)。在将经过这两步处理后的特征编码输入到主网络之前,我们还利用长短期记忆网络(LSTM)来捕获时序信息,以增强 AI 智能体在复杂掼蛋场景中的决策能力。

Inter-group Regularization(组间正则化): 在掼蛋游戏中,普通牌(非级牌)的花色在大多数情况下仅在特定牌型(如同花顺)的构建中具有特定意义,而在其他牌型组合或常规出牌策略中,不同花色的普通牌本质上并无区别。鉴于此,采取组间正则化策略,对普通牌的特征表示进行统一处理。具体来说,网络中卡牌矩阵的前 4 行(对应普通牌)通过共享权重的一维卷积模型进行处理,确保不同花色的普通牌在特征提取阶段得到一致的对待。这种设计既减少了网络参数,避免了模型过拟合,又确保了模型对普通牌的处理具备普适性和公平性,有利于提升 AI 智能体在普通牌决策上的泛化能力。

Channel-wise Attention(通道注意力机制): 为进一步挖掘掼蛋状态-动作信息中隐藏的关联性,我们在通道层面引入了注意力机制。在特征编码的各个通道上施加注意力操作,能够动态地突出重要通道,抑制无关或次要信息,从而提炼出对当前决策最具影响力的特征。通过学习每个通道的重要性权重,AI 智能体能够敏锐地捕捉到不同特征之间的相互作用与依赖关系,特别是在处理级牌、特殊牌型组合以及与队友配合等复杂情境时,通道注意力机制有助于 AI 智能体做出更为精准且符合游戏策略逻辑的决策。

利用 LSTM 提取时序信息: 在上述特征编码经过组间正则化和通道注意力机制处理后,我们将其作为输入馈送给长短期记忆网络(LSTM)。LSTM 作为一种专门设计用于处理时序数据的递归神经网络结构,具备独特的门控机制,能够有效地捕获并保留长期依赖关系。在掼蛋游戏中,时序信息尤为重要,如玩家之前的出牌顺序、牌池变化趋势、玩家间的交互历史等,这些因素对当前决策有着深远影响。

2.输入输出

模型的输入融合了当前棋局状态、可能的出牌动作以及丰富的历史信息,从而精确预测每个候选动作属于专家出牌的概率。在推理阶段,模型以高效批量处理方式对所有合法动作进行评估,最终选取概率最高的动作作为 AI 智能体的实际出牌决策。

模型输入构造:

前棋局状态与可能出牌动作的拼接:模型首先将当前详尽的棋局状态与所有可能的出牌动作进行融合,形成一个维度为 12×9×14 的三维矩阵;

对局信息向量模型进一步接收一个维度为 1×125 的一维向量,汇总了当前游戏级牌,玩家剩余手牌等关键信息;

历史出牌序列:模型还纳入了过去 8 次出牌的历史轨迹,以一个维度为 2×504 的二维矩阵表示。便于模型捕捉双方出牌模式的互动与演变。

模型输出与推理过程:

模型的输出是一组对应所有合法出牌动作的专家出牌概率。在推理阶段,模型以组 batch 的形式一次性接纳所有可能的出牌动作作为输入,经过神经网络推理,为每个动作生成一个对应的概率值。这些概率值反映了模型对每个动作符合专家级出牌策略程度的估计。

决策策略:

在获得所有合法动作的概率分布后,模型遵循最大化期望收益的原则,选择概率最高的动作作为最终的出牌决策。这意味着 AI 智能体在当前棋局状态下,将执行最有可能被专家级玩家采纳的出牌动作,力求在遵循策略深度的同时,最大化地模拟真实高手的实战智慧。

06

难度分级

掼蛋 AI 致力于打造一种兼具挑战性与公平性的对弈环境,通过精密调整关键决策参数,实现对各类玩家技能水平的精准匹配,助力玩家技能提升与沉浸式游戏享受。

1.核心技术:策略适应性与信息控制

历史信息管理:面向新手玩家,我们审慎地限制AI的历史出牌记录长度(0-8),以减轻新手承受的信息负荷,避免因过深的记忆链条而感到挫败。同时,我们运用特征mask技术对四家出牌信息进行有针对性的隐藏,使AI在与新手对弈时展示更为直观、易于理解的出牌逻辑,有利于新手快速熟悉规则并进步。

策略输出优化:AI 通常依据专家策略概率选择最高概率的出牌选项。为了适应不同难度需求,我们引入了 Thresholds 机制,设定一个概率阈值 b,允许 AI 在一定概率范围内执行次优动作,增加出牌的不可预测性与对手应对的挑战。这一设计旨在打破单一最优路径,丰富游戏战术维度与不确定性。

炸弹使用策略:通过调节 BoomProbs 参数,我们控制 AI 使用炸弹的频率。面对初级玩家,我们会适当调低此参数(如0.7-0.9),减少 AI 主动发起的高压攻势,创造相对轻松的游戏氛围。随着玩家技能提升,我们会逐步提高BoomProbs,促使AI更积极地运用炸弹等强牌,提升对局紧张度,激发玩家提升防御与反击策略。

2.精细难度分层与实证评估

我们严谨地调整各项参数,构建了包含多种策略特性的 48 种 AI 变体,它们在记忆深度、决策随机性及炸弹使用策略等方面表现出多样化的梯度。我们进行了大规模的两两对战实验,以量化分析各变体之间的相对实力,并以热力图形式清晰呈现各变体间的胜率分布。

基于实验数据,从中精选出五种具有代表性的 AI 智能体,其胜率均匀分布,分别对应五个难度等级,全面覆盖从新手入门至高手对决的技能跨度。这一设计确保每一位玩家都能找到与自身当前技能水平相匹配的 AI 对手,实现动态平衡且公正的对战条件。

方案详情:

大规模预训练模型, 深度强化学习,深度模仿学习等技术开发的智能竞技机器人,带来更加真实的游戏体验,助力提升游戏品质。游戏AI智能体解决方案已落地多项游戏!欢迎大家前来畅聊探讨~

  • 方案详情可以👉 ✉ V:LTT936 
  • 或查看以下卡片点击按钮【立即咨询】👇

游戏AI竞技机器人 - 网易智企大规模预训练模型, 深度强化学习,深度模仿学习等技术开发的智能竞技机器人,为游戏玩家带来更加真实的游戏体验,助力提升游戏品质https://grow.163.com/solution/combat-robot?from=csdn_yxzy_0426

 领取干货资料:

07

模型部署

掼蛋 AI 采用服务端部署模式,游戏状态以 proto 进行序列化传递至 AI 服务进行推理,推理结果异步返回,确保与游戏逻辑的无缝对接。系统具备以下核心优势:

1.异步处理,保障游戏流畅

AI决策过程与游戏主线程分离,采用异步通信。当需要 AI 决策时,当前游戏状态被快速序列化为 protobuf 格式发送至 AI 服务。服务接收到请求后,独立进行推理计算,而游戏客户端则可继续执行其他操作,如查看回放、交流等,无需等待 AI 决策完成。这种设计有效避免了因 AI 推理导致的卡顿,确保玩家体验流畅。

2.分布式架构,弹性应对负载

AI 服务采用分布式部署,可根据实际需求动态调整计算资源。在高峰期,可通过增加服务器节点迅速提升处理能力,确保 AI 决策响应速度。低峰期则可减少资源,降低成本。分布式架构还提高了系统的容错性,即使个别服务器故障,其他节点仍能正常提供服务,确保游戏连续性。

3.全面监控,透明管理

对 AI 服务集群进行全方位资源占用监控,包括 CPU、内存、网络等关键指标,实时掌握服务运行状况,及时优化性能。同时,提供对 AI 开局数量、历史调用量及对局表现的可视化监控,既有助于服务优化与资源调度,也增强了玩家对 AI 竞技公正性的感知,提升游戏透明度与信任度。

我们的掼蛋 AI 服务通过异步处理、分布式部署与全面监控,实现了与游戏逻辑的紧密集成,确保了服务的高性能、高可用性与可扩展性,为玩家带来流畅、稳定且具有挑战性的 AI 对战体验,同时强化了服务的透明度与玩家信任。

随着 AI 技术的不断进步,我们有理由相信,AI 智能体将在未来的游戏中扮演更加关键的角色,为玩家带来更加丰富、智能的游戏体验,同时也为游戏产业的发展注入新的活力。

方案详情:

大规模预训练模型, 深度强化学习,深度模仿学习等技术开发的智能竞技机器人,带来更加真实的游戏体验,助力提升游戏品质。游戏AI智能体解决方案已落地多项游戏!欢迎大家前来畅聊探讨~

  • 方案详情可以👉 ✉ V:LTT936 
  • 或查看以下卡片点击按钮【立即咨询】👇

游戏AI竞技机器人 - 网易智企大规模预训练模型, 深度强化学习,深度模仿学习等技术开发的智能竞技机器人,为游戏玩家带来更加真实的游戏体验,助力提升游戏品质https://grow.163.com/solution/combat-robot?from=csdn_yxzy_0426

 领取干货资料:

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
淮安是一种流行的扑克牌游戏,可以用C++语言编写。以下是一个简单的示例,仅供参考: ```c++ #include <iostream> #include <vector> #include <algorithm> #include <ctime> using namespace std; // 定义牌的种类和值 const vector<string> card_types {"♠", "♥", "♦", "♣"}; const vector<string> card_values {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}; // 定义牌的结构 struct Card { string type; string value; int point; Card(string t, string v, int p) : type(t), value(v), point(p) {} }; // 定义玩家结构 struct Player { string name; vector<Card> cards; int score; Player(string n) : name(n), score(0) {} }; // 创建一副牌 vector<Card> create_deck() { vector<Card> deck; for (auto t : card_types) { for (int i = 0; i < card_values.size(); i++) { int point = i < 9 ? i + 2 : 10; deck.push_back(Card(t, card_values[i], point)); } } return deck; } // 洗牌 void shuffle_deck(vector<Card>& deck) { srand(time(NULL)); // 以时间为种子生成随机数 random_shuffle(deck.begin(), deck.end()); } // 发牌 void deal_cards(vector<Card>& deck, vector<Player>& players) { for (int i = 0; i < players.size(); i++) { for (int j = 0; j < 13; j++) { players[i].cards.push_back(deck.back()); deck.pop_back(); } } } // 排序函数 bool cmp(Card c1, Card c2) { if (c1.type != c2.type) { return c1.type < c2.type; } else { return c1.point < c2.point; } } // 玩家出牌 Card play_card(Player& player, Card& card) { auto it = find(player.cards.begin(), player.cards.end(), card); if (it != player.cards.end()) { player.cards.erase(it); return card; } else { cout << "你没有这张牌!" << endl; return Card("", "", 0); } } // 计算得分 int calculate_score(vector<Card> cards) { int score = 0; for (auto c : cards) { if (c.value == "10" || c.value == "K" || c.value == "A") { score += 10; } else if (c.value == "5") { score += 5; } } return score; } // 判断是否为炸弹 bool is_bomb(vector<Card> cards) { if (cards.size() != 4) { return false; } for (int i = 1; i < cards.size(); i++) { if (cards[i].value != cards[0].value) { return false; } } return true; } // 判断胜负 bool is_win(vector<Card> cards1, vector<Card> cards2) { int score1 = calculate_score(cards1); int score2 = calculate_score(cards2); if (is_bomb(cards1)) { score1 *= 2; } if (is_bomb(cards2)) { score2 *= 2; } return score1 > score2; } int main() { vector<Player> players; players.push_back(Player("玩家1")); players.push_back(Player("玩家2")); vector<Card> deck = create_deck(); shuffle_deck(deck); deal_cards(deck, players); sort(players[0].cards.begin(), players[0].cards.end(), cmp); sort(players[1].cards.begin(), players[1].cards.end(), cmp); while (players[0].cards.size() > 0 && players[1].cards.size() > 0) { // 玩家1出牌 cout << players[0].name << "的手牌:"; for (auto c : players[0].cards) { cout << c.type << c.value << " "; } cout << endl; string type, value; cout << "请" << players[0].name << "出牌(输入牌的花色和点数):"; cin >> type >> value; Card card(type, value, 0); Card played_card = play_card(players[0], card); if (played_card.value != "") { // 玩家2出牌 cout << players[1].name << "的手牌:"; for (auto c : players[1].cards) { cout << c.type << c.value << " "; } cout << endl; int index = rand() % players[1].cards.size(); played_card = play_card(players[1], players[1].cards[index]); if (played_card.value != "") { if (is_win({card}, {played_card})) { cout << players[0].name << "赢了这一轮!" << endl; players[0].score++; } else { cout << players[1].name << "赢了这一轮!" << endl; players[1].score++; } } } } if (players[0].score > players[1].score) { cout << players[0].name << "赢了游戏!" << endl; } else if (players[0].score < players[1].score) { cout << players[1].name << "赢了游戏!" << endl; } else { cout << "平局!" << endl; } return 0; } ``` 这个示例程序只是一个简单的框架,还有很多地方需要完善。例如: - 玩家出牌的逻辑需要更加灵活,可以考虑加入提示、判断牌是否符合规则等功能。 - 计分规则可以根据实际情况进行修改,比如加入对炸弹的特殊处理。 - 程序没有图形面,需要在命令行中输入数据,可以考虑使用QT等GUI库进行开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值