蓝桥杯“赢球票”问题解析:队列模拟与约瑟夫环变体实战
1. 项目概述从“赢球票”到经典队列模拟问题“赢球票”是第七届蓝桥杯软件类国赛C/C组的一道经典编程真题。初次看到这个标题你可能会联想到某种抽奖或游戏活动但在算法竞赛的语境下它实则是一个精妙的队列模拟与策略优化问题。题目描述了一个有趣的场景有N张写有数字的卡片围成一圈你从第一张开始按顺序报数从1开始。当报出的数字与当前卡片上的数字相等时你就赢得这张卡片获得其数字作为积分并将其移出队列然后从下一张卡片重新从1开始报数。如果报数超过了卡片上的数字则没有赢得任何卡片游戏结束。目标是找到一种起始卡片的策略使得最终获得的总积分最高。这道题之所以在众多参赛者心中留下深刻印象是因为它完美地将生活化的游戏规则抽象成了一个计算机科学中的经典模型——约瑟夫环问题的变体。它考察的核心能力远不止于简单的模拟更在于对队列/环形数据结构的高效操作、对模拟过程剪枝的优化意识以及对问题边界条件的严谨把控。对于学习算法和数据结构的同学而言通过这道题可以深入理解如何将看似复杂的流程转化为清晰、可执行的循环与判断逻辑是锻炼编程思维和代码实现能力的绝佳材料。2. 核心思路解析为什么是队列如何抽象问题拿到题目后第一步不是急着写代码而是彻底理解规则并将其转化为可计算模型。我们先把题目中的关键元素提取出来N张卡片形成一个环形序列。这是最重要的数据结构特征意味着在遍历时索引需要循环回绕。卡片上的数字是一个正整数代表“中奖”的目标报数值。报数规则从1开始连续报数每经过一张卡片报数值加1。获胜条件当前报数值 当前卡片数字。获胜后积分增加该卡片被移除报数重置为1并从被移除卡片的下一位继续。失败条件当前报数值 当前卡片数字。游戏立即终止此前获得的积分被保留即此次尝试的最终得分。我们需要枚举所有可能的起始卡片对每一种起始情况模拟完整的游戏过程得到该起始位置下的最终得分最后取所有得分中的最大值。2.1 数据结构选型数组模拟队列 vs. 链表模拟过程中最频繁的操作是“移除当前卡片”和“移动到下一张卡片”。这本质上是对一个动态变化的线性表进行删除和遍历操作。方案一使用vector或普通数组配合索引标记删除。做法用一个数组cards存储卡片数字用一个等长的布尔数组removed标记卡片是否已被移除。模拟时用一个索引pos表示当前位置。移动时pos (pos 1) % N并跳过所有removed[pos]为真的位置。优点实现简单内存访问连续。缺点随着游戏进行移除的卡片增多每次移动都需要循环跳过已移除项最坏情况下时间复杂度会退化。在N较大时虽然本题N通常不大这可能成为性能瓶颈。方案二使用list双向链表。做法将卡片存入链表迭代器it表示当前位置。移除卡片时直接调用list.erase(it)并获取下一个位置的迭代器。由于链表删除是O(1)操作且迭代器会自动指向下一元素如果是环状处理则需要额外判断移动效率高。优点删除操作高效更贴合“物理移除”的语义。缺点链表内存不连续缓存不友好且代码中对迭代器失效的处理需要小心。方案三使用队列 (queue) 或双端队列 (deque) 进行重构模拟。做法这不是用队列存储所有卡片而是每一轮模拟都根据起始点重构一个“游戏队列”。将卡片按顺序从起始点开始环形放入队列。报数时从队头取卡片判断若未中奖则重新放回队尾模拟跳过若中奖则移除不再放回并重置报数器。优点非常直观地模拟了“轮转”过程代码逻辑清晰。缺点每次模拟都需要重新构建队列有一定开销。在实际竞赛中由于N的范围通常限制在100左右方案一数组标记法因其编码简单、不易出错而被广泛采用。这也是下面我们将重点详解的实现方式。它平衡了效率与代码复杂度是快速解题的可靠选择。2.2 算法流程设计确定了数组标记法后整个算法的骨架如下输入读取卡片数量N和N个卡片数字存入数组cards。枚举起始点for start 0 to N-1每个start代表一次独立的游戏尝试。单次游戏模拟 a. 初始化score 0本次得分count 1当前报数值pos start当前位置removed数组全部置为false。 b. 循环条件游戏未失败即count cards[pos]且还有卡片未被移除。 c. 循环体内 i.判断是否中奖如果count cards[pos]则得分增加score cards[pos]标记该卡片为已移除removed[pos] true报数重置count 1。然后需要将pos移动到下一个未被移除的卡片位置。 ii.判断是否失败如果count cards[pos]直接跳出循环本次模拟结束。 iii.若未中奖也未失败则报数递增count并将pos移动到下一个未被移除的卡片位置。 d. 移动pos的函数需要实现环形遍历并跳过已移除项。更新全局答案每次模拟结束后用max_score max(max_score, score)更新最高分。输出max_score。关键思考为什么报数重置为1后pos需要移动到下一张未移除的卡片因为规则明确写道“然后从下一张卡片重新从1开始报数”。这里的“下一张”指的是被移除卡片在原环中的下一张且必须是仍然在游戏中的卡片。3. 核心细节与实操要点理解了骨架我们深入每个环节的代码实现细节和易错点。3.1 环形遍历与跳过已移除项这是模拟过程中的核心辅助操作。我们需要一个函数getNextPos(int currentPos)它返回从currentPos的下一个位置开始顺时针找到的第一个未被移除的卡片索引。int getNextPos(int currentPos) { // 从下一个位置开始找 int next (currentPos 1) % N; // 循环查找直到找到一个未被移除的位置 while (removed[next] next ! currentPos) { // 避免全部移除后的死循环 next (next 1) % N; } // 这里有一个边界情况如果所有卡片都被移除了返回-1或进行特殊处理 // 但在我们主循环条件中通常用剩余卡片数0来控制所以这里简单返回找到的next即可。 // 如果removed[next]为真说明一圈找完又回到了currentPos且它已被移除意味着游戏应结束。 return next; }注意事项while循环的终止条件next ! currentPos至关重要它防止了当所有卡片都被移除后陷入无限循环。在主模拟循环中调用getNextPos后需要判断返回的位置是否有效即是否所有卡片已移除。更常见的做法是主循环的条件直接包含“仍有卡片未被移除”。3.2 单次游戏模拟的循环控制主模拟循环的结束条件有两个1) 报数超过当前卡片数字失败2) 所有卡片已被移除自然胜利。在代码中可以这样组织int simulate(int start) { vectorbool removed(N, false); int score 0; int count 1; int pos start; int remaining N; // 剩余卡片数用于控制循环 while (remaining 0) { // 条件1还有卡片 if (count cards[pos]) { // 条件2报数超过失败退出 break; } if (count cards[pos]) { // 中奖 score cards[pos]; removed[pos] true; remaining--; count 1; // 重置报数 // 移动到下一个未移除的卡片 if (remaining 0) break; // 如果刚移除了最后一张游戏结束 pos getNextPos(pos, removed); // 需要传入removed数组 } else { // 未中奖报数增加移动到下一张 count; pos getNextPos(pos, removed); } } return score; }实操心得 在“中奖”分支里重置count1后必须立即检查remaining是否为0。如果为0说明这是最后一张卡片游戏已经圆满结束不应该再调用getNextPos否则可能访问无效索引或进入死循环。这是一个非常隐蔽的边界条件很多初版代码会在这里出错。3.3 枚举起点的优化空间最朴素的算法是枚举每个起点进行O(N)次模拟每次模拟最坏可能进行O(N^2)次操作每次移动都可能循环遍历总复杂度约为O(N^3)。对于N100这完全在可接受范围内100^3 1e6运算量。但我们可以进行一个有效的剪枝如果从某个起点start开始模拟在第一张卡片就失败了即cards[start] 1但报数从1开始所以等价于cards[start] 0不卡片数字至少为1那么这次模拟的得分就是0。更进一步如果游戏早期就失败得分很低它不可能成为最大得分。然而最大得分可能恰恰需要完整的遍历。所以这个剪枝效果有限。一个更有效的观察是由于卡片是环形的且游戏规则对称模拟过程存在大量重复计算。但设计一个通用的记忆化搜索状态很复杂状态包括当前剩余卡片集合、当前位置、当前报数。对于竞赛场景优先保证正确性和编码速度O(N^3)的朴素算法通常是首选。4. 完整代码实现与逐行解析下面给出一个使用数组标记法的完整C实现并附上详细注释。#include iostream #include vector #include algorithm using namespace std; int main() { int N; cin N; vectorint cards(N); for (int i 0; i N; i) { cin cards[i]; } int maxScore 0; // 枚举所有可能的起始位置 for (int start 0; start N; start) { vectorbool removed(N, false); int score 0; int count 1; // 当前报数值 int pos start; // 当前位置 int remaining N; // 剩余卡片数 // 辅助函数获取下一个未被移除的位置 auto getNext [](int cur) - int { int nxt (cur 1) % N; while (removed[nxt]) { // 如果转了一圈又回到自己说明所有卡片都被移除了但此时remaining应为0循环应已结束。 // 此处为安全起见仍做判断。 if (nxt cur) { return -1; // 表示找不到游戏应结束 } nxt (nxt 1) % N; } return nxt; }; // 开始模拟 while (remaining 0) { // 情况1报数超过当前卡片数字游戏失败 if (count cards[pos]) { break; } // 情况2报数等于当前卡片数字中奖 if (count cards[pos]) { score cards[pos]; removed[pos] true; remaining--; count 1; // 关键重置报数 if (remaining 0) { break; // 没有卡片了游戏胜利结束 } // 移动到被移除卡片的下一个未移除位置 int nxt getNext(pos); if (nxt -1) break; // 理论上不会发生安全处理 pos nxt; } else { // 情况3报数小于当前卡片数字继续 count; int nxt getNext(pos); if (nxt -1) break; // 理论上不会发生安全处理 pos nxt; } } // 更新最大得分 maxScore max(maxScore, score); } cout maxScore endl; return 0; }逐行解析与关键点输入处理标准输入读取N和卡片值。外层循环for (int start 0; start N; start)枚举每个起始索引。状态初始化每次模拟都需要独立的removed、score、count、pos、remaining。Lambda表达式getNext这是一个在main函数内部定义的匿名函数用于捕获removed数组和N方便地计算下一个位置。这是C11的特性让代码更紧凑。你也可以将其写为一个独立的私有函数。主循环while (remaining 0)循环继续的条件是还有卡片剩余。失败判断if (count cards[pos])这是根据规则“报数超过卡片数字则游戏结束”的直接翻译。注意是而不是。中奖处理score cards[pos]积分增加。removed[pos] true; remaining--;标记移除并更新计数器。count 1;最容易忘记的一步必须重置报数。if (remaining 0) break;关键边界处理。如果这是最后一张卡片游戏结束避免后续无效操作。移动位置到下一个未移除的卡片。未中奖处理count然后移动到下一张卡片。更新最大值每次模拟结束后更新全局最大得分。5. 常见问题与调试技巧实录即使思路清晰实现时也难免踩坑。以下是我在解决和教学过程中遇到的几个典型问题5.1 问题一死循环现象程序运行后无法停止或者在某些起始点模拟时卡住。原因分析getNext函数没有正确处理“所有卡片都已移除”的情况。如果remaining已经为0但循环还在继续getNext可能会在一个所有removed都为true的环里无限寻找。在中奖并移除最后一张卡片后没有立即跳出循环而是继续执行了后续的移动或判断逻辑。解决方案在getNext函数中加入if (nxt cur) return -1;这样的自环检查。更根本的方法是严格用remaining 0作为主循环条件并在中奖分支里一旦remaining--后变为0立即break。这是最清晰的逻辑。5.2 问题二得分低于预期现象程序能运行结束输出一个数字但与手工计算或已知答案不符。原因分析报数重置错误在中奖后忘记将count重置为1而是继续递增。这会导致后续中奖条件永远无法满足除非卡片数字恰好是递增的。移动位置错误中奖后pos应该移动到被移除卡片的下一个未移除位置。错误实现可能移动到了(pos1)%N而不管其是否被移除或者错误地重置了pos。失败条件判断错误规则是“报数超过卡片数字时失败”即count cards[pos]。如果写成count cards[pos]那么恰好等于时也会被判为失败导致中奖不被计分。调试技巧小数据测试构造N3, 4的小例子用手工逐步模拟打印出每一步的pos,count,cards[pos],score,removed状态与程序输出对比。单元测试思维针对特定场景写测试。场景A所有卡片数字都为1。理论上从任何位置开始都能依次赢得所有卡片总分为N。场景B卡片数字是递增的如[1,2,3,...,N]。从位置0开始应该能赢得所有卡片。场景C第一张卡片数字很小如1第二张很大如100。从位置0开始赢得第一张后重置报数然后报数从1开始到100中间会经过很多轮需要仔细验证。5.3 问题三性能疑虑现象当N较大时比如5000程序运行较慢。原因分析我们算法的时间复杂度是O(N^3)。getNext函数在最坏情况下是O(N)的它被嵌套在单次模拟的循环最多O(N)次和起始点枚举O(N)中。优化思路使用链表如前所述使用list可以避免“跳过已移除项”的循环将getNext的复杂度降为O(1)。但链表操作需要细心处理迭代器。使用“下一个未移除索引”数组可以维护一个nextUnremoved数组nextUnremoved[i]表示如果i被移除下一个未被移除的索引是谁。在移除卡片时需要更新相关索引。这类似于并查集的“链表”思想可以将“查找下一个”的操作均摊到近O(1)。但实现稍复杂。竞赛建议蓝桥杯本题的N通常不会设置到需要优化算法的程度。优先保证正确性。如果真遇到大数据链表是更优选择。5.4 一份更鲁棒的链表实现参考为了对比和应对可能的数据规模这里给出一个使用std::list的实现版本。它更高效且代码别有一番风味。#include iostream #include list #include algorithm using namespace std; int main() { int N; cin N; listint cards; for (int i 0; i N; i) { int val; cin val; cards.push_back(val); } int maxScore 0; // 枚举起始点需要操作原列表的拷贝 for (int start 0; start N; start) { listint game cards; // 拷贝卡片列表 auto it game.begin(); advance(it, start); // 将迭代器移动到起始位置 int score 0; int count 1; while (!game.empty()) { if (count *it) { break; // 失败 } if (count *it) { // 中奖 score *it; count 1; it game.erase(it); // 移除当前卡片it指向下一元素 // 如果删除后链表为空结束 if (game.empty()) break; // 如果it指向end()需要环回到begin() if (it game.end()) { it game.begin(); } } else { // 未中奖 count; it; // 环状处理 if (it game.end()) { it game.begin(); } } } maxScore max(maxScore, score); } cout maxScore endl; return 0; }链表实现的注意点advance(it, start)将迭代器移动到起始位置时间复杂度O(start)。it game.erase(it)是关键。erase返回被删除元素的下一个元素的迭代器这完美契合了我们的需求。需要小心处理迭代器到达end()的情况此时应将其环回到begin()。每次模拟需要拷贝整个链表listint game cards;这是O(N)的开销。总复杂度约为O(N^2)。对于大N这比数组标记法的O(N^3)要好。6. 总结与思维延伸“赢球票”这道题是一个绝佳的算法思维训练案例。它从一个有趣的游戏出发引导我们思考如何用程序模拟一个动态变化的环形过程。解决它的关键在于严谨地将自然语言规则转化为无歧义的程序逻辑尤其是处理好状态重置报数归1和元素移除后的遍历。通过这道题我们巩固了以下知识点环形结构的模拟使用取模运算% N实现索引循环。标记数组的使用一种高效处理“逻辑删除”的常见技巧。边界条件的周全考虑游戏胜利无卡片剩余和失败报数超限的退出条件、移除最后一张卡片后的处理、查找下一个有效位置时的循环终止条件。不同数据结构的权衡数组标记法编码简单链表法操作高效。根据问题规模选择合适的工具。这道题还可以做一些有趣的延伸思考如果卡片数字可能非常大比如10^9我们的模拟步骤是否会太多实际上当报数count远大于当前剩余卡片数字的最大值时游戏必然失败。我们可以利用这一点进行加速吗或者是否存在某种数学规律可以直接计算出最优起始点而无需模拟这些问题留给大家在掌握基础解法后进一步探索。在竞赛中先把清晰、正确的模拟写出来就是走向成功的第一步。

相关新闻

Pads软件在Win10/Win11系统安装卡死与运行卡顿的全面解决方案

Pads软件在Win10/Win11系统安装卡死与运行卡顿的全面解决方案

1. 从一次痛苦的安装经历说起如果你是一名电子工程师,或者正在学习PCB设计,那么Pads这个名字对你来说一定不陌生。作为一款经典的PCB设计软件,它在很多公司,尤其是消费电子、工控、通信等领域,依然有着庞大的用户基础。…

2026/8/24 10:02:25 阅读更多 →
Paper2GUI Figma 界面设计新手教程:把 AI 工具界面做得开箱即用

Paper2GUI Figma 界面设计新手教程:把 AI 工具界面做得开箱即用

Paper2GUI Figma 界面设计新手教程:把 AI 工具界面做得开箱即用 【免费下载链接】paper2gui Convert AI papers to GUI,Make it easy and convenient for everyone to use artificial intelligence technology。让每个人都简单方便的使用前沿人工智能技术…

2026/8/24 10:01:24 阅读更多 →
RPCS3汉化补丁轻松跑通指南:新手半小时上手游玩

RPCS3汉化补丁轻松跑通指南:新手半小时上手游玩

RPCS3汉化补丁轻松跑通指南:新手半小时上手游玩 【免费下载链接】rpcs3 PlayStation 3 emulator and debugger 项目地址: https://gitcode.com/GitHub_Trending/rp/rpcs3 装好之后,你得到的是一台能跑PS3游戏的中文模拟器:游戏里的菜单…

2026/8/24 10:01:24 阅读更多 →

最新新闻

【非标自动化】2、认识元器件(远程I/O)

【非标自动化】2、认识元器件(远程I/O)

远程I/O远程I/O,也叫:Remote I/O 分布式I/O 远程输入输出站它的本质是:把PLC的输入输出接口从主控制柜“搬到”设备现场,通过工业通信总线与PLC交换信号。传统接线方式是每个传感器、按钮、电磁阀的信号线都拉回主控制柜&#xff…

2026/8/24 12:47:41 阅读更多 →
Unicorn引擎实战:从零构建动态代码分析沙箱,突破混淆与虚拟化保护

Unicorn引擎实战:从零构建动态代码分析沙箱,突破混淆与虚拟化保护

逆向工程,尤其是针对移动应用和Web端的逆向分析,正从一个“小众黑客技能”演变为安全研究、漏洞挖掘、协议分析乃至合法业务逻辑复现的必备能力。然而,很多开发者或安全爱好者止步于使用现成的工具进行简单的抓包和脱壳,一旦遇到强…

2026/8/24 12:47:41 阅读更多 →
普通人如何防住网络诈骗,这十条安全意识要记牢

普通人如何防住网络诈骗,这十条安全意识要记牢

数据时代的隐形战场:你我都是守护者 在这个万物互联的时代,网络早已像空气和水一样渗透进生活的每一个角落。我们用它购物、社交、办公,甚至管理家庭财务。然而,便利的背后往往潜伏着危机。对于普通网民和家庭用户而言&#xff0…

2026/8/24 12:47:41 阅读更多 →
Unicorn引擎实战:逆向工程中的代码仿真与反混淆技术

Unicorn引擎实战:逆向工程中的代码仿真与反混淆技术

这次我们来看一个专注于逆向工程与反混淆实战的教程资源。标题虽然带有“B站”字样,但核心内容是关于Unicorn引擎的高级应用,这是一个在安全研究、漏洞分析、恶意代码检测等领域至关重要的仿真框架。对于从事软件安全、移动应用(Android/iOS&…

2026/8/24 12:47:41 阅读更多 →
Unicorn引擎在高级逆向与反混淆中的实战应用

Unicorn引擎在高级逆向与反混淆中的实战应用

这次我们来看一个专注于逆向工程与反混淆实战的教程资源。标题虽然带有强烈的平台指向性,但核心内容指向的是 Unicorn 引擎在高级逆向与反混淆中的应用 。对于从事安全研究、漏洞分析或软件保护的开发者来说,掌握基于 CPU 指令级模拟的逆向技术&#x…

2026/8/24 12:47:41 阅读更多 →
【非标自动化】2、认识元器件(调压阀)

【非标自动化】2、认识元器件(调压阀)

调压阀这里的调压阀,指的是气动系统中的空气减压阀/压力调节阀。它通常安装在气源处理组件中,用来把上游较高、存在波动的压缩空气压力,降低并稳定在设备需要的工作压力。例如:工厂气源压力:0.7 MPa 设备需要压力&…

2026/8/24 12:46:40 阅读更多 →

日新闻

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践 前端安全依赖分层防护。没有任何单一配置能替代输出编码、权限校验和依赖更新。 把不可信内容当作数据 默认使用框架的转义能力;确需渲染 HTML 时,先在服务端或可信的客户端库中进行白名单过滤。避免把用户输入直接赋给 inne…

2026/8/24 1:08:15 阅读更多 →
Windows登录密码存储机制全解析:从哈希算法到安全加固实战

Windows登录密码存储机制全解析:从哈希算法到安全加固实战

1. 项目概述:Windows登录密码的“黑匣子”每次你按下CtrlAltDel,输入密码,然后看到那个熟悉的桌面,这背后发生了一系列复杂而精密的操作。作为一名长期与Windows系统打交道的从业者,我经常被问到:“我的密码…

2026/8/24 1:08:15 阅读更多 →
AI面试系统安全挑战与解决方案

AI面试系统安全挑战与解决方案

1. 项目概述:AI面试系统的安全挑战去年参与某跨国企业AI面试系统部署时,遇到一个典型案例:候选人在视频面试中无意提到竞争对手产品名称,系统竟自动将该信息关联到企业知识库并生成竞品分析报告。这个看似"智能"的功能&…

2026/8/24 1:08:15 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 0:06:02 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 0:20:20 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/24 0:14:11 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/24 11:20:22 阅读更多 →