基于QT与C++的中国象棋游戏开发实战:从MVC架构到AI算法
1. 项目概述为什么选择QT与C来复刻中国象棋如果你对桌面应用开发感兴趣或者想找一个能串联起C面向对象编程、图形界面设计和游戏逻辑的实战项目那么用QT和C来开发一个中国象棋游戏绝对是一个“黄金级”的练手选择。这不仅仅是因为象棋规则本身逻辑清晰、复杂度适中更因为通过这个项目你能把学校里学的那些看似枯燥的C类、继承、多态、STL容器以及QT的信号槽、绘图事件、控件布局等知识全部串联起来变成一个看得见、摸得着、能运行、能对战的完整程序。我当初选择这个项目就是厌倦了控制台的黑白世界。QT框架提供了强大的跨平台图形界面能力让你能用C写出媲美现代软件的界面而象棋的棋盘、棋子、走法规则恰好是检验你数据结构设计和算法逻辑的绝佳试金石。这个项目麻雀虽小五脏俱全它涉及界面渲染QT绘图、事件处理鼠标点击、核心算法棋规判定、对象建模棋子类甚至还能扩展到网络对战Socket通信和AI对战搜索算法。对于想找C/QT方向工作的同学来说这样一个完整的项目经历写在简历上比空谈“熟练掌握C”要有说服力得多。接下来我会带你从零开始拆解整个开发过程。我会重点分享我在实现过程中踩过的坑、做出的设计抉择以及那些教科书里不会写的调试技巧。我们的目标是最终得到一个界面美观、逻辑正确、代码结构清晰并且具备一定可扩展性的中国象棋程序。2. 整体架构与核心模块设计在动手写第一行代码之前花点时间思考整体架构是至关重要的。一个混乱的架构会让后续的添加功能比如悔棋、网络对战变得举步维艰。我的设计核心是“模型-视图-控制器MVC”的变体在QT项目中这通常演化为数据模型、界面视图和业务逻辑分离。2.1 核心类设计整个项目我主要设计了以下几个核心类ChessPiece棋子类这是所有棋子的基类。它应该包含棋子的基本属性颜色红方或黑方、类型车、马、炮等、在棋盘上的位置行列坐标、是否已被吃掉的状态。更重要的是它需要有一个纯虚函数比如bool canMoveTo(int targetRow, int targetCol, const ChessBoard board)用于判断该棋子能否移动到目标位置。然后为每种棋子车、马、象、士、将、炮、兵创建派生类重写这个移动规则函数。这是多态性的经典应用。ChessBoard棋盘类这是游戏的核心数据模型。它不应该直接处理界面绘制而是专注于维护游戏状态。其核心成员是一个二维数组或std::vectorstd::vectorstd::shared_ptrChessPiece来表示9x10的棋盘格点存储着棋子对象的指针空指针表示无子。它还应该记录当前行棋方红先黑后、棋局状态进行中、红胜、黑胜、和棋以及一个走法历史记录列表用于实现悔棋。GameController游戏控制类这是连接数据ChessBoard和界面MainWindow的桥梁是业务逻辑的集中地。它负责响应用户的界面操作如点击棋子调用ChessBoard和ChessPiece的规则进行逻辑判定并更新棋盘数据最后通知界面重绘。它也是处理游戏流程开始、结束、悔棋、重新开始的总指挥。MainWindow主窗口类由QT的QMainWindow派生而来主要负责界面展示。它包含一个用于绘制棋盘和棋子的自定义Widget例如ChessWidget以及一些按钮开始、悔棋、认输等。它的职责是接收鼠标事件将其转化为逻辑坐标后传递给GameController并根据控制器的指令更新界面。2.2 数据流与信号槽QT的灵魂是信号与槽Signals Slots我们用它将各个模块松耦合地连接起来。用户交互流用户在ChessWidget上点击鼠标 -ChessWidget捕获鼠标事件计算点击的棋盘格 -ChessWidget或MainWindow发出一个自定义信号如pieceClicked(int row, int col)-GameController的对应槽函数接收该信号 - 控制器调用ChessBoard的接口处理走法逻辑 - 逻辑处理后控制器发出另一个信号如boardStateChanged()-ChessWidget接收到状态变化信号调用update()触发重绘从最新的ChessBoard数据中读取并绘制棋盘棋子。设计心得尽量避免在视图类ChessWidget里直接操作模型数据ChessBoard也避免在模型类里直接调用界面更新。所有修改都通过控制器中转。这样做的好处是假设未来我想把界面从QT换成其他库或者为游戏添加一个命令行界面我只需要替换视图部分核心的ChessBoard和GameController逻辑几乎不用改动。这就是关注点分离带来的好处。3. 核心实现细节与难点攻克有了架构蓝图我们来深入几个最关键、也最容易出错的实现细节。3.1 棋盘与棋子的绘制绘制是给用户的第一印象。我们使用QT的QPainter在ChessWidget的paintEvent函数中完成。棋盘绘制计算好棋盘左上角的起始坐标根据棋盘格大小比如60像素绘制9条竖线和10条横线。使用QPainter::drawLine即可。楚河汉界可以用QPainter::drawText来绘制文字。棋子绘制这是重点。我推荐使用贴图而非纯色绘制效果更好。为红黑两方的7种棋子准备14张透明的PNG图片。在绘制时遍历ChessBoard中的二维数组。对于每个非空的位置根据棋子的颜色和类型选择对应的图片。计算该棋子在屏幕上的圆心坐标centerX startX col * gridSize gridSize/2。使用QPainter::drawPixmap将图片绘制在指定区域可以以圆心为基准进行绘制。踩坑提示1抗锯齿与高质量渲染直接绘制线条和图片可能会有锯齿。务必在QPainter对象使用前设置渲染提示painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿 painter.setRenderHint(QPainter::SmoothPixmapTransform); // 平滑像素图变换这能让你的棋盘和棋子边缘看起来非常平滑质感提升一个档次。棋子选中效果当用户点击一个己方棋子时需要高亮它。我常用的方法是在棋子图片外围绘制一个半透明的圆环。在绘制棋子图片后判断如果该棋子是被选中的棋子则用QPainter设置一个半透明的笔刷QBrush(QColor(255, 255, 0, 100))和较粗的画笔绘制一个比棋子略大的圆。3.2 象棋规则的精确定义与实现这是项目的逻辑核心必须严谨。每种棋子的移动规则都在其派生类的canMoveTo函数中实现。这里以几个易错点为例马的走法马走日与蹩马腿 马可以走“日”字。但关键在于如果马要前往的某个目标点其前进方向上的“相邻点”马走日的第一步落脚点有任意棋子则不能走俗称“蹩马腿”。// 伪代码示例判断马从(r1,c1)到(r2,c2)是否合法 int dr abs(r2 - r1); int dc abs(c2 - c1); if (!((dr 2 dc 1) || (dr 1 dc 2))) { return false; // 不是日字格 } // 检查蹩马腿 int blockRow, blockCol; if (dr 2) { // 竖向走日 blockRow (r1 r2) / 2; blockCol c1; } else { // 横向走日 blockRow r1; blockCol (c1 c2) / 2; } if (board.getPieceAt(blockRow, blockCol) ! nullptr) { return false; // 马腿被蹩 } return true;炮的走法炮打隔山子 炮移动时路径上必须无子和车一样。但吃子时目标位置和目标位置与炮之间必须有且仅有一个棋子即“炮架”。// 伪代码判断炮的移动/吃子 int piecesBetween countPiecesBetween(r1, c1, r2, c2, board); ChessPiece* targetPiece board.getPieceAt(r2, c2); if (targetPiece nullptr) { // 移动 return piecesBetween 0; } else { // 吃子 return piecesBetween 1; }将/帅的走法与“王不见王” 将帅只能在九宫内移动每次一步。此外还有一个特殊规则如果双方将帅在同一直线上且中间没有任何棋子则不允许形成“对脸”或称为“王不见王”此时先手方可以直接获胜或判负规则可自定义。这个规则需要在GameController进行走法验证时作为一个全局规则额外检查。踩坑提示2坐标系统一内部逻辑数组下标和界面绘制像素坐标一定要建立清晰的映射关系并封装成函数。我定义棋盘逻辑坐标是(row, col)row从0到9从上到下col从0到8从左到右。鼠标点击的像素坐标(x, y)需要通过转换函数pixelToLogic(x, y)得到逻辑坐标(r, c)再进行逻辑判断。反之绘制时需要logicToPixel(r, c)。混乱的坐标系统是BUG的主要来源之一。3.3 游戏状态管理与流程控制GameController是游戏的大脑它需要处理回合切换每次成功走子后切换当前行棋方从红方切换到黑方或反之。胜负判定在每次走子后检查是否擒获了对方的将/帅。更复杂的判定还包括长将、长捉等竞赛规则作为初级项目可以只实现“将死”判定。走法历史记录为了实现悔棋需要记录每一步的完整信息。我定义了一个MoveStep结构体包含起始位置、目标位置、被吃掉的棋子如果有。使用一个std::vectorMoveStep来保存历史。悔棋时从末尾弹出一步并根据记录的信息恢复棋盘状态。游戏重置将ChessBoard的二维数组重置为初始布局清空历史记录当前行棋方设为红方。4. 功能扩展与性能优化思路一个基础版本完成后你可以考虑以下扩展让项目更加出彩4.1 网络对战功能这是从单机游戏迈向联机游戏的关键一步。核心是引入网络模块采用客户端-服务器C/S或点对点P2P架构。C/S架构开发一个简单的服务器负责匹配玩家、转发棋步、校验规则可选。两个客户端分别连接服务器只负责界面和发送/接收棋步。服务器可以用C配合Boost.Asio或QT自身的QTcpServer/QTcpSocket实现。P2P架构一方作为主机另一方连接主机的IP和端口。棋步数据直接在两个客户端间通过Socket传输。QT的QTcpSocket可以胜任。协议设计你需要设计一个简单的应用层协议来传递消息。例如可以用字符串格式如MOVE:2,7,4,7表示从(2,7)移动到(4,7)CHAT:Hello表示聊天信息。更规范的做法是使用二进制协议或JSON。实操心得网络同步与状态验证网络对战的难点在于状态同步和防作弊。一个简单的策略是权威服务器或主机权威。即只有服务器或主机进行完整的规则校验客户端只做初步校验如是否轮到本方走子和发送意向。主机校验通过后再将合法的棋步广播给双方双方根据这个权威指令更新本地棋盘。这样可以避免因客户端被篡改而导致的规则破坏。4.2 集成简单AI对手实现一个“人机对战”模式会极大提升项目的技术含量。这涉及到基本的搜索算法。评估函数首先你需要一个函数来评价当前棋盘局面对于某一方的好坏。最简单的评估可以基于棋子价值车9马4.5炮4.5象/士2兵1将无穷大和棋子位置加分。搜索算法从最简单的极大极小搜索Minimax开始。AI黑方试图最大化评估值而假设玩家红方会最小化评估值。算法递归地模拟未来几步的所有可能走法选择对AI最有利的。性能优化纯Minimax搜索深度非常有限。必须引入Alpha-Beta剪枝来大幅减少需要搜索的节点数。即使这样搜索深度可能也只能达到4-6层但对于初级AI已经足够。实现步骤为AI生成所有合法走法。对每个走法模拟执行调用Minimax(深度-1)递归搜索。在搜索叶子节点深度为0或游戏结束时调用评估函数。选择评估值最优的走法执行。// 极小极大算法伪代码框架 int minimax(ChessBoard board, int depth, bool isMaximizingPlayer) { if (depth 0 || gameIsOver(board)) { return evaluate(board); // 评估函数 } if (isMaximizingPlayer) { int maxEval -INFINITY; for (Move move : generateAllMoves(board, BLACK)) { // AI是黑方 board.makeMove(move); int eval minimax(board, depth - 1, false); board.undoMove(move); maxEval max(maxEval, eval); } return maxEval; } else { int minEval INFINITY; for (Move move : generateAllMoves(board, RED)) { // 玩家是红方 board.makeMove(move); int eval minimax(board, depth - 1, true); board.undoMove(move); minEval min(minEval, eval); } return minEval; } }4.3 性能与内存优化对于象棋游戏性能瓶颈主要出现在AI搜索时。除了Alpha-Beta剪枝还可以考虑走法生成优化预计算每种棋子在空棋盘上所有可能的移动偏移量在实际生成时再结合棋盘状态判断合法性比每次都从头计算快。置换表使用哈希表存储已经搜索过的棋盘局面及其评估结果避免重复搜索。这需要为棋盘状态生成一个唯一的Zobrist哈希值。智能指针管理在ChessBoard中使用std::shared_ptrChessPiece来管理棋子对象可以方便地处理棋子的创建和销毁如被吃掉时避免内存泄漏。注意避免循环引用。5. 开发环境搭建与调试技巧工欲善其事必先利其器。一个顺手的开发环境能事半功倍。5.1 QT与C环境配置QT安装直接从QT官网下载开源版本或安装器。对于初学者建议安装带有QT Creator IDE的版本它集成了设计、编码、调试、编译于一体对QT项目支持非常好。版本选择上QT 5.15 LTS或QT 6.2都是稳定可靠的选择。编译器在Windows上安装QT时会自动勾选安装MinGW编译器。你也可以使用MSVCVisual Studio编译器这需要你事先安装Visual Studio即使是Build Tools版本。在Linux上使用系统的g即可。在macOS上使用Xcode的命令行工具。项目管理QT使用.pro文件qmake或CMakeLists.txtCMake来管理项目。对于新手QT Creator创建的qmake项目更简单直观。在.pro文件中你需要添加QT core gui等模块。VSCode配置如果你偏爱VSCode可以安装C扩展和QT Configure扩展。配置c_cpp_properties.json中的包含路径使其指向你的QT安装目录下的include文件夹。配置tasks.json来调用qmake和make进行构建。调试则需要配置launch.json。5.2 调试与问题排查实录在开发过程中你一定会遇到各种奇怪的问题。以下是我遇到的一些典型问题及解决方法问题1程序运行时崩溃报错“pure virtual method called”现象在操作过程中程序突然崩溃。排查这个错误通常意味着你在基类的构造函数或析构函数中调用了虚函数。在构造/析构期间对象的虚函数表可能还未完全建立或已被销毁此时调用虚函数会导致未定义行为。解决绝对不要在构造函数和析构函数中调用虚函数。如果需要在初始化时进行多态操作可以考虑使用“初始化函数”并在构造完成后调用。问题2界面刷新不正常棋子有残影或绘制错位现象移动棋子后原位置有残留图像或者新位置绘制不正确。排查这通常是paintEvent函数逻辑问题或刷新区域计算错误。解决确保在paintEvent中使用QPainter绘制时是绘制整个棋盘和所有棋子。不要尝试只绘制“脏矩形”除非你非常确定。在棋子移动后确保同时调用update()来触发整个棋盘区域的重绘或者计算新旧位置的两个矩形区域调用update(rect)进行局部更新。检查你的坐标转换函数logicToPixel是否正确特别是行列索引与像素坐标的对应关系。问题3鼠标点击事件不灵敏或响应区域错误现象点击棋子边缘没反应或者点击空白处却选中了棋子。排查鼠标事件判断逻辑有问题。解决在mousePressEvent中你获取的是鼠标点击的像素坐标(x, y)。你需要将其转换为棋盘逻辑坐标(r, c)。然后你需要判断这个(r, c)是否在棋盘范围内0r10, 0c9。最后判断该位置是否有棋子。关键点判断是否有棋子应该使用逻辑坐标去查询ChessBoard模型而不是依赖于你绘制的图像区域。因为绘制可能有偏移但模型数据是精确的。问题4发布程序后在其他电脑上运行缺少DLL现象在自己电脑上运行正常打包发给别人后无法启动提示缺少Qt5Core.dll等。解决这是QT程序发布的常见问题。你需要将程序依赖的QT动态库DLL文件复制到可执行文件同级目录。最稳妥的方法是使用QT自带的命令行工具windeployqtWindows或macdeployqtmacOS。在构建目录下运行windeployqt your_program.exe它会自动扫描依赖并复制所有必要的库和资源文件。对于Linux通常需要告知用户安装对应的QT运行时库。开发这样一个项目最大的收获不是最终那个可以运行的游戏而是在解决上述一个个具体问题的过程中对C面向对象设计、QT框架机制、以及算法逻辑实现的深刻理解。从棋盘数据结构的定义到QT信号槽的巧妙连接再到马蹩腿、炮翻山这些具体规则的代码实现每一步都充满了挑战和乐趣。当你最终看到两个人在你亲手编写的程序中对弈时那种成就感是无与伦比的。这个项目完全可以作为你C/QT学习之路上的一个里程碑它的代码和设计思路也能为你今后开发更复杂的桌面应用打下坚实的基础。

相关新闻

Unity InputSystem 从入门到精通:告别旧版输入系统,掌握现代化输入处理

Unity InputSystem 从入门到精通:告别旧版输入系统,掌握现代化输入处理

1. 项目概述:为什么是时候拥抱InputSystem了?如果你还在Unity项目里用着那个老旧的InputManager,每次处理复杂输入组合(比如“冲刺跳跃切换武器”)时,都得写一堆Input.GetKeyDown和状态管理代码&#xff0c…

2026/8/3 12:09:30 阅读更多 →
Unity跨平台时间处理:ISO 8601解析、时区转换与DateTimeOffset实战

Unity跨平台时间处理:ISO 8601解析、时区转换与DateTimeOffset实战

1. 项目概述与核心痛点在Unity项目开发中,尤其是涉及全球运营、多地区玩家数据同步或后端服务交互时,处理时间数据绝对是一个高频且容易踩坑的领域。我们经常遇到这样的场景:后端服务返回一个形如2024-05-27T15:30:45.123Z的时间字符串&#…

2026/8/3 12:09:30 阅读更多 →
软件工程项目管理实战:需求控制与质量保障方法论

软件工程项目管理实战:需求控制与质量保障方法论

1. 项目复盘与目标达成方法论 刚接手这个代号XXXX的项目时,团队正面临典型的多重困境:需求频繁变更导致开发进度滞后30%,跨部门协作存在信息孤岛,测试阶段暴露出大量接口对接问题。作为技术负责人,我决定采用软件工程方…

2026/8/3 12:09:30 阅读更多 →

最新新闻

UWPHook:3步将Windows商店游戏整合到Steam的终极解决方案

UWPHook:3步将Windows商店游戏整合到Steam的终极解决方案

UWPHook:3步将Windows商店游戏整合到Steam的终极解决方案 【免费下载链接】UWPHook 🔗 Add your Windows Store or UWP games to Steam 项目地址: https://gitcode.com/gh_mirrors/uw/UWPHook 你是否面临Windows商店游戏无法在Steam中统一管理的困…

2026/8/3 12:40:50 阅读更多 →
3步掌握Tacview:飞行数据分析的终极指南

3步掌握Tacview:飞行数据分析的终极指南

3步掌握Tacview:飞行数据分析的终极指南 【免费下载链接】Tacview The Universal Flight Analysis Tool 项目地址: https://gitcode.com/gh_mirrors/ta/Tacview Tacview是一款专业的飞行数据分析工具,它能够记录、分析和理解任何飞行数据&#xf…

2026/8/3 12:40:50 阅读更多 →
后置埋件设计中化学螺栓与膨胀螺栓混用问题

后置埋件设计中化学螺栓与膨胀螺栓混用问题

后置埋件设计中化学螺栓与膨胀螺栓混用问题 目前幕墙后置埋件的设计中很多采用化学螺栓与膨胀螺栓混用的个案(如立柱预埋件分别为一对角线两枚化学螺栓,另一对角线两枚膨胀螺栓),但此类埋件计算如何取参数、公式?请大家讨论,化学螺栓与膨螺栓混用合理吗?两种螺栓混用幕…

2026/8/3 12:40:50 阅读更多 →
JavaScript进程与线程:浏览器与Node.js并发模型解析

JavaScript进程与线程:浏览器与Node.js并发模型解析

1. JavaScript中的进程与线程基础概念 在浏览器和Node.js环境中,JavaScript处理并发任务的方式与传统编程语言有着显著差异。我们先明确几个核心概念: **进程(Process)**是操作系统资源分配的基本单位,每个进程都有独…

2026/8/3 12:40:50 阅读更多 →
Laravel大文件导出优化:异步队列与分块处理实战

Laravel大文件导出优化:异步队列与分块处理实战

1. 项目概述 大文件导出是Web开发中常见的需求场景,但在Laravel框架下实现时往往会遇到请求超时、内存溢出等问题。我在最近一个电商后台项目中,就遇到了需要导出10万行订单数据的需求。最初采用常规的CSV导出方案,结果频繁出现504 Gateway T…

2026/8/3 12:40:50 阅读更多 →
基于Hadoop大数据的手机销售数据的分析与研究(源码+lw+部署文档+讲解等)

基于Hadoop大数据的手机销售数据的分析与研究(源码+lw+部署文档+讲解等)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/3 12:39:49 阅读更多 →

日新闻

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码。…

2026/8/3 0:00:47 阅读更多 →
[具身智能-181]:PC+服务器+具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构

[具身智能-181]:PC+服务器+具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构

PC服务器具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构一、前言:具身智能需要“混合算力闭环系统”传统人工智能依赖云端静态数据集训练,不具备物理交互能力,无法适应真实世界的不确定性。具身智能(Embodied…

2026/8/3 0:00:47 阅读更多 →
[具身智能-181]:大分布式通信模型对比:看懂为什么 DDS 是 ROS2 底层通信最优解

[具身智能-181]:大分布式通信模型对比:看懂为什么 DDS 是 ROS2 底层通信最优解

前言构建机器人、具身智能这类分布式实时系统,通信底座直接决定整套系统的实时性、容错性、组网能力。分布式领域长期存在 4 类经典通信架构:点对点模式、Broker 中间代理模式、广播模式、以数据为中心(DDS)模式。很多开发者疑惑&…

2026/8/3 0:00:47 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/3 4:58:13 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/3 1:53:31 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/3 4:36:35 阅读更多 →

月新闻

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

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

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

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

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

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

2026/8/3 5:19:38 阅读更多 →
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/3 8:27:36 阅读更多 →