C++乒乓球游戏:双缓存防闪屏与状态机驱动的图形学实战
简介这是一款基于C开发的桌面级乒乓球对战游戏面向编程初学者与图形界面实践者聚焦双缓存绘图优化、人机AI逻辑与本地PVP交互等核心知识点适用于课程设计、算法可视化练习及小型游戏开发入门。资源包共52个文件含9个头文件h定义类结构与接口、8个源码文件cpp实现游戏主逻辑如Ball.cpp、Game.cpp、Player.cpp及Computer.cpp、1个可执行文件Ball.exe开箱即玩另有调试符号pdb、编译中间文件obj/sbr及资源文件bmp/ico/rc整体2.91MB结构完整体现VC6经典MFC项目组织范式。已有826人学习下载读者可直接运行体验双人键控对战WASD方向键与人机对抗深入源码学习双缓存渲染机制、球体物理运动建模碰撞检测、反弹计算、AI状态决策逻辑及MFC消息响应流程是理解Windows桌面游戏开发全流程的优质实操样本。1. 一个能跑通、能对打、能调参的乒乓球游戏C 实现 双缓存防闪屏 人机/PVP 模式切换适合图形学入门和游戏逻辑拆解这不是一个“画个球拍拖动鼠标”的玩具 Demo。我去年在带某高校图形学实验课时用它作为第 3 周的实战项目——学生从零开始编译、修改 AI 难度、加计分逻辑、甚至把单机 PVP 改成局域网对战仅需替换输入模块。核心就三点用纯 C不依赖 Qt/SDL2 等大框架、双缓存机制彻底解决 Win32 GDI 绘图撕裂问题、人机与 PVP 模式共用同一套物理引擎和碰撞判定逻辑只是输入源不同。它不炫技但每行代码都可调试、可打断点、可改参数它不抽象球速、反弹角、AI 延迟、拍子移动加速度全暴露在 config.h 里。如果你正卡在“学完 Win32 API 不知怎么组织游戏循环”“写过控制台小游戏但一上图形界面就闪屏崩溃”“想练手状态机但找不到合适载体”这个资源就是为你拆出来的——不是教你怎么画圆而是教你怎么让圆按物理规则弹、按策略判断落点、按玩家输入实时响应。2. 从 Win32 窗口到双缓存渲染为什么不用 DirectX/OpenGL而坚持纯 GDI 内存 DC2.1 为什么选 Win32 GDI 而非现代图形 API新手常误以为“图形游戏必须用 OpenGL 或 Vulkan”。但真实工程中轻量级交互应用如教学 Demo、嵌入式 HMI、工业看板仍大量使用 GDI。本项目坚持纯 Win32 GDI原因很实在零依赖编译即运行不需额外安装运行时、不需配置 SDK 路径、不需处理着色器编译失败调试友好GDI 函数Rectangle,Ellipse,BitBlt全部是同步阻塞调用下断点能看到每一帧绘制耗时边界清晰没有管线状态管理、没有顶点缓冲区绑定所有绘图逻辑集中在RenderFrame()函数内便于初学者理解“一帧 清屏 绘制所有对象 交换缓冲”这一基本范式。提示这不是技术倒退而是做减法。就像学驾驶先练手动挡——掌握底层节奏后再上自动挡DirectX或电车Unity才真正懂加速逻辑。2.2 双缓存实现原理内存 DC 是如何吃掉撕裂和闪烁的Win32 GDI 默认是直接往屏幕 DC 绘图一旦Paint过程被系统中断如窗口被遮挡后重绘就会出现半帧残留即“撕裂”。更糟的是快速重绘时会因前后帧未完全刷新导致“闪烁”。双缓存本质是用一块内存区域内存 DC作为中间画布所有绘制操作先发往内存 DC等整帧画完再用BitBlt一次性拷贝到屏幕 DC。关键不在“多了一块内存”而在强制序列化绘制与显示。// 在 WM_CREATE 中创建内存 DC 和位图 HDC hdc GetDC(hWnd); hMemDC CreateCompatibleDC(hdc); hBitmap CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom); SelectObject(hMemDC, hBitmap); // 将位图选入内存 DC ReleaseDC(hWnd, hdc); // 在 WM_PAINT 中执行双缓存绘制 PAINTSTRUCT ps; HDC hdcPaint BeginPaint(hWnd, ps); BitBlt(hdcPaint, 0, 0, clientRect.right, clientRect.bottom, hMemDC, 0, 0, SRCCOPY); // 仅此一次拷贝 EndPaint(hWnd, ps);这段代码里hMemDC是内存设备上下文hBitmap是与其兼容的位图。所有Ellipse()画球、Rectangle()画球拍都作用于hMemDC而非hdcPaint。BitBlt是唯一与屏幕交互的函数且只调用一次。这就是防撕裂的全部秘密——不是靠硬件而是靠软件层的绘制原子性。2.3 双缓存性能实测1920×1080 下帧率稳定在 120 FPS 的关键参数很多人以为双缓存必然拖慢性能。实测数据打脸在 i5-8250U 笔记本上关闭双缓存直绘屏幕 DC平均帧率 85 FPS开启后反升至 120 FPS。原因在于屏幕 DC 频繁重绘触发显卡垂直同步VSync等待而内存 DC 绘制无此开销BitBlt拷贝是 GPU 加速的Windows GDI 自动启用远快于 CPU 逐像素写屏。但有两个致命参数必须调准否则反而卡顿位图尺寸必须与客户区严格一致若CreateCompatibleBitmap传入的宽高大于实际窗口BitBlt会触发缩放计算CPU 占用飙升内存 DC 必须复用不可每帧重建项目中hMemDC和hBitmap在WM_CREATE创建在WM_DESTROY销毁全程只初始化一次。若放在WM_PAINT内创建/销毁每秒新建销毁上千次句柄系统直接假死。3. 物理引擎与游戏状态机球的运动、碰撞、得分逻辑如何用 200 行 C 拆解3.1 球的运动模型不是匀速直线而是带加速度衰减的抛物线很多教程把乒乓球简化为“碰到边界就反转 vx/vy”这会导致球永远不减速、不旋转、不模拟空气阻力。本项目采用更贴近真实的简化模型// ball.h 中的物理更新逻辑 void Ball::Update(float deltaTime) { // 1. 位置积分x vx * deltaTime, y vy * deltaTime x vx * deltaTime; y vy * deltaTime; // 2. 速度衰减模拟空气阻力系数 0.999 vx * 0.999f; vy * 0.999f; // 3. 重力影响微小向下加速度增强下坠感 vy 15.0f * deltaTime; // 15 是调参值非真实 g // 4. 边界碰撞顶部/底部反弹x 方向不变 if (y - radius 0) { y radius; vy -vy * 0.8f; // 垂直方向能量损失 20% } if (y radius screenHeight) { y screenHeight - radius; vy -vy * 0.8f; } }注意deltaTime是毫秒级时间差由GetTickCount64()计算确保运动与帧率无关。0.8f是恢复系数coefficient of restitution调低它球会越弹越矮——这是调试 AI 难度的核心杠杆之一。3.2 球拍-球碰撞判定矩形包围盒 边缘修正拒绝“穿模”PVP 模式下玩家手速快球可能以极小角度擦过球拍边缘。若只用IntersectRect判定会漏掉大量有效击球。本项目采用两段式判定// paddle.cpp 中的 HitTest 函数 bool Paddle::HitTest(const Ball ball) const { // Step 1: 粗略包围盒检测快速剔除 RECT ballRect { (long)(ball.x - ball.radius), (long)(ball.y - ball.radius), (long)(ball.x ball.radius), (long)(ball.y ball.radius) }; if (!IntersectRect(rcIntersect, ballRect, rect)) return false; // Step 2: 精确边缘距离检测解决“擦边”问题 float closestX Clamp(ball.x, rect.left, rect.right); float closestY Clamp(ball.y, rect.top, rect.bottom); float distanceSquared (ball.x - closestX) * (ball.x - closestX) (ball.y - closestY) * (ball.y - closestY); return distanceSquared ball.radius * ball.radius; }Clamp函数将球心坐标约束在球拍矩形内得到球心到球拍的最近点再算欧氏距离。这比单纯PtInRect更鲁棒——即使球中心在球拍外只要球体与球拍相交就判为击中。这是 PVP 对战手感流畅的关键否则玩家会感觉“明明打到了却没反应”。3.3 游戏状态机设计从 START → PLAYING → SCORED → WAITING状态流转驱动一切整个游戏逻辑不靠全局变量堆砌而由GameState枚举和GameContext类封装enum class GameState { START, // 显示标题按空格开始 PLAYING, // 正常对打物理更新输入处理 SCORED, // 一方得分暂停物理显示分数 WAITING // 等待玩家按回车继续 }; class GameContext { public: GameState state GameState::START; int player1Score 0, player2Score 0; Ball ball; Paddle paddle1, paddle2; void Update(float deltaTime) { switch (state) { case GameState::START: HandleStartInput(); break; case GameState::PLAYING: UpdatePlaying(deltaTime); break; case GameState::SCORED: HandleScored(); break; case GameState::WAITING: HandleWaitingInput(); break; } } private: void UpdatePlaying(float deltaTime) { ball.Update(deltaTime); paddle1.Update(deltaTime, InputSource::PLAYER1); paddle2.Update(deltaTime, InputSource::PLAYER2); CheckCollisions(); CheckScore(); } };状态机让逻辑解耦SCORED状态下ball.Update()不执行球静止WAITING状态下paddle.Update()被跳过球拍冻结。这种设计避免了“if (gameRunning) {...} else {...}”的面条代码也方便后续扩展如加入暂停菜单、回放模式。4. 人机与 PVP 模式切换同一套物理引擎两种输入源三类 AI 策略4.1 输入抽象层InputSource 枚举统一处理键盘、AI、网络数据PVP 模式需要监听 WASD/方向键人机模式则需 AI 决策。若为每种模式写独立输入函数代码会爆炸。本项目定义InputSource枚举并在Paddle::Update()中统一调度enum class InputSource { PLAYER1, // 键盘W/S 或 ↑/↓ PLAYER2, // 键盘I/K 或 ↑/↓ AI_EASY, // 简单 AI球 Y 坐标 ± 随机偏移 AI_MEDIUM, // 中等 AI预测球落点 0.2s 延迟 AI_HARD // 困难 AI完整弹道预测 球拍加速度模拟 }; void Paddle::Update(float deltaTime, InputSource source) { float targetY 0; switch (source) { case InputSource::PLAYER1: targetY GetPlayer1TargetY(); break; case InputSource::PLAYER2: targetY GetPlayer2TargetY(); break; case InputSource::AI_EASY: targetY GetAIEasyTargetY(); break; case InputSource::AI_MEDIUM: targetY GetAIMediumTargetY(); break; case InputSource::AI_HARD: targetY GetAIHardTargetY(); break; } // 球拍平滑移动到 targetY带加速度限制 MoveToTarget(targetY, deltaTime); }MoveToTarget函数内部实现球拍的加速度、最大速度、惯性——这保证无论输入源是人还是 AI球拍运动物理一致不会出现“AI 移动瞬移而玩家拖不动”的割裂感。4.2 AI_EASY 策略随机扰动 基础跟随适合新手适应AI_EASY不预测只跟随。但它加了两个关键扰动避免“AI 永远完美接球”的挫败感float Paddle::GetAIEasyTargetY() const { float idealY ball.y; // 理想接球点 球当前 Y // 1. 随机偏移±15 像素模拟反应误差 float jitter (rand() % 31) - 15.0f; // 2. 滞后偏移球正在上升时AI 往下偏下降时往上偏模拟预判失误 float lagOffset (ball.vy 0) ? -10.0f : 10.0f; return idealY jitter lagOffset; }jitter让 AI 偶尔漏球lagOffset制造“明明看到球来了却拍子没到位”的真实感。这两个参数在config.h中可调学生作业常要求“调参使 AI 漏球率 ≈ 30%”。4.3 AI_MEDIUM 策略弹道预测 固定延迟平衡难度与公平性AI_MEDIUM是项目最常用模式。它不求 100% 接住而追求“看起来像在思考”float Paddle::GetAIMediumTargetY() const { // 预测球到达球拍 X 位置的时间 t float distToPaddle (isLeftPaddle ? ball.x : screenWidth - ball.x) - (isLeftPaddle ? 0 : paddleWidth); if (fabs(ball.vx) 1.0f) return ball.y; // 球几乎静止不预测 float t distToPaddle / fabs(ball.vx); // 计算 t 时间后球的 Y 位置含重力、衰减 float predictedY ball.y ball.vy * t 0.5f * 15.0f * t * t; // 应用 200ms 延迟模拟人类神经传导肌肉响应 predictedY (ball.vy 0 ? -15.0f : 15.0f) * 0.2f; return Clamp(predictedY, paddleHeight/2, screenHeight - paddleHeight/2); }这里t是预测时间predictedY是理论落点0.2f是固定延迟。关键在Clamp—— AI 不会追出屏幕这比“AI 疯狂乱甩”更符合真实选手习惯。学生反馈说这个 AI 让他们“输得心服口服”因为漏球总发生在球速突变或旋转强的回合。5. 避坑指南那些让我重装三次系统、查七小时文档才定位的 Win32 游戏开发雷区5.1 现象窗口最大化后球拍绘制错位缩小窗口又恢复正常原因WM_SIZE消息中未更新clientRect导致双缓存位图尺寸与实际客户区不匹配。CreateCompatibleBitmap用的是旧尺寸BitBlt拷贝时发生拉伸。解决在WM_SIZE处理中重建内存 DC 和位图并重新SelectObject。注意必须先DeleteObject(hBitmap)再CreateCompatibleBitmap否则句柄泄漏。5.2 现象PVP 模式下按住 W 键不放球拍只移动一帧就停止原因Win32 默认键盘消息是WM_KEYDOWN按键按下和WM_KEYUP松开但GetAsyncKeyState()才能检测“持续按下”。项目默认用后者但若忘记在Update()中每帧调用就变成单次触发。解决确认Paddle::Update()内部调用GetAsyncKeyState(VK_W)而非等待WM_KEYDOWN。并在config.h中检查INPUT_METHOD宏是否定义为ASYNC。5.3 现象AI_HARD 模式下球拍疯狂抖动像帕金森患者原因AI_HARD使用完整弹道预测含多次碰撞反弹但未限制预测深度。当球速极低时预测循环陷入无限反弹计算返回 NaN 坐标MoveToTarget传入 NaN 导致浮点异常。解决在预测函数开头加守卫if (fabs(ball.vx) 0.5f || fabs(ball.vy) 0.5f) return ball.y;并用_isnan()检查中间结果。这是血泪经验——NaN 在 Win32 GDI 中不报错只让Ellipse绘制消失。5.4 现象编译通过运行一闪而退事件查看器显示 “0xc0000005”原因WM_PAINT中未调用BeginPaint/EndPaint或hMemDC/hBitmap在WM_DESTROY前被提前释放。GDI 句柄被 Windows 回收后BitBlt访问野指针。解决用OutputDebugString在WM_CREATE和WM_DESTROY中打印句柄值确认生命周期。更可靠的是在RenderFrame()开头加if (!hMemDC || !hBitmap) return;防御性编程。5.5 现象修改config.h中BALL_SPEED后球速变化不明显原因BALL_SPEED是初始速度但Ball::Update()中的vx * 0.999f衰减项起主导作用。若0.999f未随BALL_SPEED动态调整高速球衰减慢低速球衰减快导致调节失真。解决将衰减系数改为1.0f - BALL_SPEED * 0.0001f使衰减强度与初速正相关。这是玄学调参——没有公式只有反复试出来的手感。6. 进阶技巧如何用 10 行代码把单机 PVP 升级为局域网对战验证物理一致性与网络同步的终极方法6.1 网络同步的核心矛盾客户端预测 vs 服务端权威把本地 PVP 改成网络对战最大的陷阱是“谁负责物理计算”。常见错误是让客户端各自算球轨迹结果因浮点精度、deltaTime微小差异几秒后双方看到的球位置偏差超 10 像素游戏崩溃。本项目采用服务端权威 客户端预测混合方案服务端运行在一台机器独占Ball::Update()每 15ms 计算一次球状态广播给所有客户端客户端收到包后不直接跳转球位置而是用lerp平滑插值到服务端位置同时继续用本地输入驱动球拍关键服务端不发送原始vx/vy而是发送ball.x, ball.y, ball.frameId客户端用frameId匹配本地帧避免网络抖动导致插值错乱。6.2 10 行代码改造从InputSource::PLAYER1到InputSource::NETWORK原 PVP 模式中paddle1读键盘paddle2读键盘。网络化只需改两处// game.cpp 中的 Update 函数片段 void GameContext::Update(float deltaTime) { // ... 状态机逻辑 if (state GameState::PLAYING) { ball.Update(deltaTime); // 服务端此行保留 // 客户端注释掉下面两行改用网络输入 // paddle1.Update(deltaTime, InputSource::PLAYER1); // paddle2.Update(deltaTime, InputSource::PLAYER2); // 新增从网络接收 paddle2 目标 Y if (network.HasNewPaddle2Y()) { paddle2.SetTargetY(network.GetPaddle2Y()); } paddle2.Update(deltaTime, InputSource::NETWORK); // 新增枚举值 } }InputSource::NETWORK在Paddle::Update()中跳过键盘读取直接用SetTargetY()设置目标。SetTargetY()内部仍走MoveToTarget平滑移动保证手感一致。这 10 行改动就是从单机到网络的全部桥梁。6.3 验证物理一致性的黄金方法录制-回放Replay对比表网络对战最怕“我看到球进了你那边没进”。终极验证不是抓包而是录制服务端物理状态让客户端回放并比对。项目附带replay_tool.cpp生成如下对比表帧号服务端 ball.x客户端 ball.x偏差(px)是否接受120423.781423.7800.001✅121425.215425.2130.002✅122426.648426.6450.003✅123428.080428.0720.008⚠️警告124429.511429.4950.016❌失败规则连续 3 帧偏差 0.01px或单帧 0.02px即判定同步失败。这比肉眼观察可靠 100 倍。我带的学生做课程设计时必须提交这份表格作为验收依据。从那以后我每次改物理参数都强制走一遍replay_tool录制 10 秒对打导出 CSV 用 Excel 画偏差折线图。曲线毛刺超过阈值立刻回滚。不是信不过自己而是信不过浮点数在不同 CPU 上的隐式舍入。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Ryujinx Switch 模拟器入门指南:三步在 PC 上跑起 Nintendo Switch 游戏

Ryujinx Switch 模拟器入门指南:三步在 PC 上跑起 Nintendo Switch 游戏

Ryujinx Switch 模拟器入门指南:三步在 PC 上跑起 Nintendo Switch 游戏 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx 想在不开主机的情况下,用 PC 玩 Switch…

2026/10/16 2:19:51 阅读更多 →
M3U8/MPD 流媒体下载与直播录制实战:3 条命令上手 N_m3u8DL-RE

M3U8/MPD 流媒体下载与直播录制实战:3 条命令上手 N_m3u8DL-RE

M3U8/MPD 流媒体下载与直播录制实战:3 条命令上手 N_m3u8DL-RE 【免费下载链接】N_m3u8DL-RE Cross-Platform, modern and powerful stream downloader for MPD/M3U8/ISM. English/简体中文/繁體中文. 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8…

2026/10/16 2:19:51 阅读更多 →
HTML5多图片上传预览源码解析:从选图到FormData提交

HTML5多图片上传预览源码解析:从选图到FormData提交

简介:这份资源是一套基于HTML5 File API与拖放API实现的多图片上传预览源码,适合Web前端初中级开发者、网站维护人员以及需要快速集成图片选择功能的项目团队。项目完全在浏览器端完成本地图片读取与预览,无需服务器参与:用户既可…

2026/10/16 2:19:51 阅读更多 →

最新新闻

自定义表单设计器-教学讲解

自定义表单设计器-教学讲解

自定义表单设计器 - 教学讲解目标读者:第一次接触本项目自定义表单设计器的同学 阅读时长:约 20 分钟 学完之后,你能完整说清楚下面这 3 件事: 设计器中间"手机壳"里的控件预览,到底是怎么画出来的&#xff…

2026/10/16 3:14:02 阅读更多 →
YOLO26改进:SPPF结合FFocal焦点调制提升目标检测精度

YOLO26改进:SPPF结合FFocal焦点调制提升目标检测精度

1. 为什么大家都在改SPPF?先搞清楚原始结构的真实瓶颈YOLO系列的SPPF模块,说白了就是空间金字塔池化的进化版。它的核心作用是把不同尺度的特征做融合,让网络对小目标、大目标都有感知能力。原版实现是先用一个CBS(ConvBNSiLU&…

2026/10/16 3:14:02 阅读更多 →
大模型全面开放实测:从对话、API接入到生产落地的完整指南

大模型全面开放实测:从对话、API接入到生产落地的完整指南

这个标题我看一眼就坐直了。倒不是说“全面开放”这四个字有多新鲜,而是“免费用户也能用了”这一句,直接戳中了之前所有绕过限制、寻找镜像站、甚至去买共用账号的人——包括我。我把手头的测试项目停了一下午,专门把界面点了一遍&#xff0…

2026/10/16 3:14:02 阅读更多 →
宝石装箱与容斥原理:从公式推导到代码实现

宝石装箱与容斥原理:从公式推导到代码实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:14:02 阅读更多 →
STM32移植TencentOS tiny MQTT组件实现物联网云接入

STM32移植TencentOS tiny MQTT组件实现物联网云接入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:14:02 阅读更多 →
微信小程序圆环组件开发:Canvas 2D与CSS方案选型及性能优化实战

微信小程序圆环组件开发:Canvas 2D与CSS方案选型及性能优化实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:13:02 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →