C语言俄罗斯方块源码实战:数据结构、旋转与碰撞检测详解
简介这是一份用C语言结合Windows API实现的俄罗斯方块完整工程源码面向初学Windows编程或对经典小游戏实现感兴趣的学习者。程序支持左右键移动、下键加速、上键变形、空格暂停源码中附有详细注释便于理解窗口创建、消息循环、绘制与碰撞检测等核心知识点。压缩包共28个文件约1.12MB主要包含cpp源文件、h头文件、ico图标素材以及可直接运行的exe还带有dsp/dsw工程配置适合用VC6.0直接打开学习。已有4514人学习下载。通过这份资料读者能获得一个可运行、可修改的完整游戏项目既能巩固C语言语法又能入门Windows API的消息处理与图形绘制还可在此基础上扩展计分、关卡等功能。1. 用 C 语言编写的俄罗斯方块附源码为什么这个终端小项目值得你亲手敲一遍C 语言编写的俄罗斯方块附源码这类项目看起来只是一个在终端里跑的小游戏真正动过手的人才知道旋转、碰撞、消行这三件事任何一件都能让新手卡上一整天。方块转到一半穿进墙里、按一次键连走两格、消掉一行后上面的方块纹丝不动——这些坑我在自己写的版本里全踩过。这个项目的价值不在于做出一个能玩的“俄罗斯方块”而在于它把 C 语言最常用的几块内容一次性串了起来二维数组与边界、结构体与坐标变换、状态机主循环、终端 IO 与输入时序。做完它你对 C 语言“底层感”的理解会明显不一样。它适合刚学完函数和指针、想找完整项目练手的人也适合要交课程设计的学生。拿到“附源码”先别急着编译看效果我建议你先读数据结构和碰撞检测绘制放在最后看——顺序反了你只会改参数不知道自己在改什么。2. 俄罗斯方块的数据结构游戏区、方块坐标与旋转矩阵怎么选读“附源码”时我建议你先找两个东西游戏区用什么存、方块用什么表示。最劝退的写法是把方块存成“旋转后的字符画数组”然后用一堆 switch 枚举四种旋转态最后旋转逻辑写成一大坨 if-else想改一个方块形状得动好几处。我的推荐是各司其职游戏区用二维数组方块用四个相对坐标点旋转用坐标变换公式。这三个东西定下来后面所有逻辑都顺。2.1 游戏区二维数组与坐标边界约定标准俄罗斯方块游戏区是 10 列宽、20 行高。宽 10 是流传下来的经典尺寸做课程设计不需要改但建议用宏定义方便以后做迷你版或加宽版。#define COLS 10 #define ROWS 20 int area[ROWS][COLS]; // 0 表示空格非 0 表示已落定的方块 void init_area(void) { for (int r 0; r ROWS; r) for (int c 0; c COLS; c) area[r][c] 0; }这里要说明一个容易混淆的点area只存“已经落定、不再移动”的方块。正在下落的那一块不写进area而是单独用一个结构体保存位置。这样碰撞检测时只需要把候选位置和area里的已占格比对不用区分哪些格子属于当前活动块。坐标系约定为 x 向右、y 向下x范围 0 到 COLS-1y范围 0 到 ROWS-1。y为负数表示方块还在顶部之外游戏允许它暂时“悬空”出现左右越界和触底则直接判定碰撞。为什么area用int而不用char调试时看整型数组比看字符数组直观而且以后要扩展颜色编号、消行动画状态时不用改类型。2.2 方块形状基础坐标与旋转归一化每个方块由四个小方格组成。经典俄罗斯方块有七种形状I、O、T、S、Z、J、L。我习惯用“基础形状 当前旋转态”的方式而不是把四种旋转态全部预先写死在代码里。typedef struct { int x; // 方块锚点的列坐标 int y; // 方块锚点的行坐标 int type; // 方块类型 0~6 int rotation; // 当前旋转态 0~3 int dx[4]; // 四个小格相对锚点的列偏移 int dy[4]; // 四个小格相对锚点的行偏移 } Block; // 七种方块的基础形状x 向右y 向下 static const int base[7][4][2] { {{0,0},{1,0},{2,0},{3,0}}, // I {{0,0},{1,0},{0,1},{1,1}}, // O {{0,0},{1,0},{2,0},{1,1}}, // T {{1,0},{2,0},{0,1},{1,1}}, // S {{0,0},{1,0},{1,1},{2,1}}, // Z {{0,0},{0,1},{1,1},{2,1}}, // J {{2,0},{0,1},{1,1},{2,1}} // L };新方块生成时把base[type]复制进Block的dx、dyx、y设到出生位置。移动时只改x、y四个相对坐标完全不动这比存储四个绝对坐标再逐个加减省事得多。旋转是重头戏。屏幕坐标系 y 向下绕原点逆时针旋转 90 度的公式是dx -dy, dy dx。但直接套用这个公式旋转后方块的包围盒会漂移——明明在原地转视觉上却“跳”了一下。原因是旋转围绕的是坐标原点而不是方块自己的中心。解决办法是旋转后做一次归一化把最小偏移平移到 0。void rotate(Block *b) { int ndx[4], ndy[4]; for (int i 0; i 4; i) { ndx[i] -b-dy[i]; // 逆时针旋转 90 度 ndy[i] b-dx[i]; } // 归一化让旋转后的包围盒回到 0..3避免视觉漂移 int minx ndx[0], miny ndy[0]; for (int i 1; i 4; i) { if (ndx[i] minx) minx ndx[i]; if (ndy[i] miny) miny ndy[i]; } for (int i 0; i 4; i) { b-dx[i] ndx[i] - minx; b-dy[i] ndy[i] - miny; } b-rotation (b-rotation 1) % 4; }参数说明minx和miny是旋转后所有小格坐标的最小值减去它相当于把整个方块平移回左上角对齐。比如 I 方块横着时是{0,0},{1,0},{2,0},{3,0}旋转后坐标是{0,0},{0,1},{0,2},{0,3}已经落在 0..3 范围内但 L 方块旋转后会出负数坐标不归一化的话方块会一边转一边“走位”。这一步不做后面做墙检测时还会连锁产生穿墙误判。3. 终端绘制与按键输入让方块在命令行里真正动起来数据模型就绪后下一步是让方块显示出来并且能控制。C 语言做图形界面方案很多但课程设计和练手项目里最稳的做法是终端加 ANSI 转义序列零依赖任何带终端的环境都能跑逻辑透明出问题也好定位。3.1 ANSI 转义序列全量重绘一个 draw 函数搞定刷新绘制方案我选择“每帧全量重绘”而不是只擦掉旧位置再画新位置。原因有两个终端刷新率本来就低游戏每秒渲染 10 到 20 帧一帧最多输出 200 个字符性能完全不是问题全量重绘逻辑简单不会出现“上次画的位置没擦干净”的残影问题。#include stdio.h void draw(int area[ROWS][COLS], Block *b) { printf(\033[H); // 光标回到终端左上角 printf(\033[?25l); // 隐藏光标避免闪烁 for (int r 0; r ROWS; r) { for (int c 0; c COLS; c) { int filled area[r][c]; for (int i 0; i 4; i) { // 检查当前活动块是否覆盖此格 if (b r b-y b-dy[i] c b-x b-dx[i]) filled 1; } printf(filled ? [] : ); } printf(\n); } printf(\033[0m); // 重置样式 fflush(stdout); // 强制输出不能省 }逻辑说明\033[H是 ANSI 转义序列中的“光标归位”把光标挪回左上角\033[?25l隐藏光标防止方块下落时光标在屏幕上乱跳。每一格先看area里有没有已落定方块再看当前活动块的四个小格是否覆盖到这里两者都满足就画成方块。fflush(stdout)是最容易漏的一步。printf默认走行缓冲输出到终端时可能因为没换行而积压在缓冲区里表现为画面卡顿或残缺。关掉缓冲也行但我更推荐显式fflush只在需要刷新的一帧调用其他日志输出不受影响。退出程序前记得用printf(\033[?25h)恢复光标显示否则关掉程序后终端一直不显示光标第一次遇到会以为终端卡死了。3.2 非阻塞输入termios 的 VMIN 与 VTIME 配置新手最常见的翻车点是getchar()的阻塞行为按一下方向键程序不响应非要再按一次回车才动一下。原因是终端默认处于“规范模式”输入要等回车才会交给程序。解决方法是把终端切到“非规范模式”也就是关闭 ICANON同时关掉 ECHO 防止按键字母回显到屏幕上。#include termios.h #include unistd.h static struct termios saved_tio; void set_raw_mode(int enable) { if (enable) { tcgetattr(STDIN_FILENO, saved_tio); struct termios raw_tio saved_tio; raw_tio.c_lflag ~(ICANON | ECHO); // 关行缓冲与回显 raw_tio.c_cc[VMIN] 0; // 不等待字符 raw_tio.c_cc[VTIME] 0; // 不等待超时 tcsetattr(STDIN_FILENO, TCSANOW, raw_tio); } else { tcsetattr(STDIN_FILENO, TCSANOW, saved_tio); } }参数说明VMIN 0表示读不到字符就立刻返回VTIME 0表示不做超时等待这两个值配合起来就是真正的非阻塞读。ICANON关掉后每次按键立即生效ECHO关掉后按下的键不会显示在屏幕上。退出游戏前一定要调用set_raw_mode(0)恢复原始终端状态这是唯一后悔药——不恢复的话终端会停留在不回显、不换行的模式所有 shell 命令都像“坏掉”了一样。方向键不是单字节而是 ESC 开头的三字节序列比如上键是ESC [ A。读输入时要解析完整序列enum { KEY_LEFT 1, KEY_RIGHT, KEY_DOWN, KEY_UP, KEY_ESC }; int read_input(void) { int ch getchar(); if (ch -1) return 0; // 无按键 if (ch 27) { // ESC 开头方向键是多字节 int ch2 getchar(); if (ch2 [) { switch (getchar()) { case A: return KEY_UP; case B: return KEY_DOWN; case C: return KEY_RIGHT; case D: return KEY_LEFT; } } return KEY_ESC; // 单独的 ESC 当作退出键 } return ch; }注意非阻塞模式下getchar()可能返回 -1调用方要忽略这种情况。Windows 控制台没有 termios常见做法是#ifdef _WIN32分支改用_kbhit()加_getch()这两个函数天然非阻塞省去配置 raw 模式的步骤。4. 碰撞检测、消行与计分把规则补成一局能玩的游戏绘制和输入通了之后游戏还只是“一块方块直直往下掉按左右键画面跟着动”。要成为一局完整的游戏核心是三类规则碰撞检测决定它能不能动落定逻辑决定它停在哪消行计分决定它怎么结束。4.1 碰撞检测三步左右墙、底部、已填充格碰撞检测的规则只有三条超出左右边界算碰撞触底算碰撞撞到area里已有的落定方块算碰撞。但是“顶部之上”不算碰撞——方块出生时有一截可能在屏幕外如果顶部也算碰撞新方块一出来就 game over。int is_collision(Block *b, int area[ROWS][COLS]) { for (int i 0; i 4; i) { int x b-x b-dx[i]; int y b-y b-dy[i]; if (x 0 || x COLS) return 1; // 左右越界 if (y ROWS) return 1; // 触底 if (y 0 area[y][x]) return 1; // 撞到已落定方块 } return 0; }y 0这个条件不能省y 为负数时数组下标越界直接访问area[y][x]是未定义行为轻则读到脏数据重则程序崩溃。只做下边界判定不做上边界判定是为了允许方块在顶部之外生成。移动方块时不要直接修改再检测那样改坏了还要改回去。用“拷贝一份试移动检测通过才提交”的模式int try_move(Block *b, int dx, int dy) { Block tmp *b; tmp.x dx; tmp.y dy; if (is_collision(tmp, area)) return 0; *b tmp; return 1; }落定时把当前块的四个小格写进area同样要跳过 y 为负的格子void lock_block(Block *b, int area[ROWS][COLS]) { for (int i 0; i 4; i) { int x b-x b-dx[i]; int y b-y b-dy[i]; if (y 0 y ROWS x 0 x COLS) area[y][x] 1; } }先拷贝再提交这个模式在所有方块类游戏里都通用。它让碰撞检测函数保持“只判断、不修改”的语义后续做旋转踢墙时同样的函数可以直接复用。4.2 消行与计分从下往上扫描与等级加速表消行的正确姿势是从最底行往上扫。找到满行后把这一行上面的所有行整体往下移一行最顶行补 0。这里有个细节最容易踩搬完一行后要把扫描下标r加回去因为上面又移下来一行当前位置还没检查过。int clear_lines(void) { int cleared 0; for (int r ROWS - 1; r 0; r--) { int full 1; for (int c 0; c COLS; c) { if (area[r][c] 0) { full 0; break; } } if (full) { cleared; for (int rr r; rr 0; rr--) for (int c 0; c COLS; c) area[rr][c] area[rr - 1][c]; for (int c 0; c COLS; c) area[0][c] 0; r; // 当前位置从上面移下来新行需要重新检查 } } return cleared; }提示r这一行看着像多余不写的话连续两行同时消掉时只会消掉下面那行上面那行会漏掉。这种“漏消行”问题在调试里非常难发现因为界面看起来只是分数少了玩家很难察觉。可以写一个测试用例预先构造连续两行满格调用clear_lines()后断言两行都被清空。计分规则我用经典倍数单次消 1/2/3/4 行分别得 100/300/500/800 分。等级按累计消行数提升每消 10 行升一级下落间隔线性缩短但设一个下限防止最后快到没法玩单次消行数得分说明1100单行2300双行3500三行4800一次四行俗称 Tetris主循环要分清两类驱动按键是事件驱动只在按下时触发下落是时间驱动要按帧检查是否到了下落时刻。混在一起写会导致按住下键时方块加速失控。骨架如下while (!game_over) { int ch read_input(); if (ch q || ch KEY_ESC) break; if (ch KEY_LEFT) try_move(cur, -1, 0); if (ch KEY_RIGHT) try_move(cur, 1, 0); if (ch KEY_DOWN) try_move(cur, 0, 1); if (ch KEY_UP) try_rotate(cur); if (now_ms - last_fall_ms fall_interval_ms) { if (!try_move(cur, 0, 1)) { lock_block(cur, area); // 落定 int n clear_lines(); // 先消行 score score_table[n]; // 再计分 spawn_new_block(cur); // 后生成新块 if (is_collision(cur, area)) // 出生就被占满 game_over 1; } last_fall_ms now_ms; } draw(area, cur); }now_ms需要平台相关函数获取Windows 用GetTickCount()Linux 用clock_gettime()这里不展开。注意顺序先落定再消行再计分最后生成新块。生成新块后立刻做一次碰撞检测判定游戏是否结束——这一步漏掉的话方块会堆到顶部之后游戏还在继续跑画面看起来像方块穿过了天花板。5. 俄罗斯方块常见问题排查五个高频翻车点与检查顺序功能写完只是第一步。如果你正在跑自己的版本大概率已经遇到花屏、穿墙、按键失灵、速度不变这类诡异现象。这章列五个我实际踩过、也帮别人排查过的高频问题按“现象、原因、解决”的顺序写。排查时建议从上往下对照大部分问题都能在前三条里定位。5.1 方块一出生就报游戏结束现象新方块刚出现游戏立刻判定 game over或者方块悬空卡在已经堆满的行中间。 原因有两个常见来源一是出生坐标的 y 设成了 0而 I 方块横向有 4 格宽某些方块占 2 行高出生瞬间就与顶部已堆方块重合二是生成新块后没有调用is_collision做检查落定逻辑把 y 为负的格子也写进了area。 解决出生 y 坐标设为 -1 或 -2让方块先出现在屏幕外lock_block里跳过所有 y 为负的小格生成新块后立即检测碰撞才置 game over。这三处配合好顶部行为就和街机一致了。5.2 按一次方向键连走两格现象轻按一下左键方块连续向左移动两次节奏完全不受控制。 原因非阻塞模式下getchar()在一次循环内读到多个字符。方向键是 ESC 开头的三字节序列如果解析函数没有读完整三个字节剩余字节会在下一次循环被当成独立按键处理表现为“多走一步”。另外用户快速连按也会在缓冲区里留下多个按键事件。 解决方向键解析必须一次读满三字节读完后如果还有残留字符可以用tcflush(STDIN_FILENO, TCIFLUSH)清空。但注意tcflush会同时丢弃玩家已经按下但还没处理的合法按键所以只在检测到明显残留时调用不要放在每帧循环里。这个问题的玄学之处在于它不稳定复现——跟按键速度、终端转义序列的延迟都有关系建议先在固定种子的调试环境里测。5.3 旋转后穿墙或位置漂移现象方块贴着左墙旋转结果半个身子跑到墙外面I 方块旋转后位置发生一次明显跳动。 原因旋转函数只做了坐标变换没有做越界修正旋转后的新位置被直接赋值给方块绕过了碰撞检测。 解决旋转前先拷贝一份做尝试旋转后做碰撞检测碰撞就尝试左右平移“踢墙”踢不动就放弃这次旋转。这就是简化版的 wall kickint try_rotate(Block *b) { Block tmp *b; rotate(tmp); for (int kick 0; kick 2; kick) { tmp.x b-x kick; // 先向右踢 if (!is_collision(tmp, area)) { *b tmp; return 1; } tmp.x b-x - kick; // 再向左踢 if (!is_collision(tmp, area)) { *b tmp; return 1; } } return 0; // 踢两格都撞放弃旋转 }注意这里rotate(tmp)已经对 tmp 做了归一化所以踢墙偏移的基准是b-x而不是tmp.x旋转前的位置。这个简化版足够课程设计和大多数练手场景不用纠结完整版 SRS 系统——除非你想复刻街机手感那是另一个深坑。5.4 Windows 控制台花屏与光标乱跑现象同一份代码在 Linux 上跑得好好的放到 Windows 控制台里全是[H、[0m这种可见字符方块区域乱成一团光标不停闪烁。 原因Windows 老版本控制台默认不解析 ANSI 转义序列printf(\033[H)会原样输出字符。 解决两条路线。最简单是#ifdef _WIN32分支里用system(cls)清屏代替光标归位但会有闪烁。更现代的做法是通过 Windows API 开启虚拟终端处理#ifdef _WIN32 #include windows.h void enable_ansi(void) { HANDLE h GetStdHandle(STD_OUTPUT_HANDLE); DWORD mode 0; GetConsoleMode(h, mode); SetConsoleMode(h, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); } #endif在main开头调用enable_ansi()之后的 ANSI 转义序列就和 Linux 表现一致。同一套绘制代码两个平台都能用不用再单独维护一份 cls 版本。这个建议对 Windows 10 及以上的新终端都有效。5.5 下落速度“感觉没变”现象消了 20 行等级升了好几次但方块下落速度完全没变化游戏越来越拖沓。 原因等级对应的下落间隔没有更新或者时间单位搞混了。常见是把usleep参数写成毫秒值usleep(500)实际只休眠 0.5 毫秒方块几乎瞬移反过来把fall_interval当成微秒用又会让下落慢到无法玩。 解决全局统一用毫秒做时间单位。速度表可以这样设计fall_interval_ms 800 - level * 50最小 50 毫秒。每次消行后重新计算并赋值确保速度随等级实时变化。验证速度不要靠“感觉”实测最靠谱开一局30 秒内数方块自然下落了多少格和理论值对比。我一般会在调试输出里打印当前等级和间隔看到数值变化比盯着画面猜快得多。6. 进阶验证用固定随机序列回放一局再给方块加暂存与预览调通基本功能后我想推荐两个投入产出比很高的进阶动作。第一个和调试直接相关俄罗斯方块的方块序列是随机的这导致同一个 bug 很难稳定复现——上一局穿墙下一局又不穿了。解决办法是用固定随机种子让每局的方块序列完全一致。// 调试阶段用固定种子正式发布再换成 time(NULL) srand(20241117); int next_type rand() % 7;固定种子之后同一局可以反复回放。我调试旋转穿墙时会先构造一个必现的场景固定序列开局连续下落若干步然后停在特定位置旋转。每改一次代码跑同样序列观察行为是否变化。这个习惯帮我省下了大量“碰运气”式调试时间比加断点逐行看更高效。第二个进阶是给游戏加“暂存块”和“下一个块”预览。暂存块逻辑不复杂按 C 键时把当前块与暂存槽里的块交换。有一个细节要注意——每个块只能暂存一次否则玩家可以在两个槽位间来回交换相当于凭空获得无限换块能力。常见的做法是给 Block 加一个swapped标志落定或交换后重置。预览功能的实现更直接在生成方块时预先生成下一个类型绘制函数在游戏区右侧画一个 4x2 的小区域。代码量不大但对游戏体验的提升非常明显玩家不再是“盲等下一块”有了规划空间。我最早写俄罗斯方块时卡在旋转上整整一个下午最后把“旋转”和“踢墙”拆成两个独立函数才理顺。这个项目的价值就在于这些坑你亲手踩过一遍之后再写贪吃蛇、2048、甚至状态机驱动的客户端逻辑都会顺很多。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Photoshop移动UI设计从入门到精通:画布搭建、控件绘制与切图导出全流程

Photoshop移动UI设计从入门到精通:画布搭建、控件绘制与切图导出全流程

简介:这份PPT讲义面向移动UI设计初学者与希望系统提升的设计师,围绕Photoshop在移动端界面设计中的应用展开,帮助读者从零建立移动UI设计认知并逐步进阶。内容按模块递进:新手导航讲解手机与平板界面差异、iOS/Android/Windows Ph…

2026/10/14 12:58:58 阅读更多 →
MCP Python SDK:模型上下文协议的高效实现与应用

MCP Python SDK:模型上下文协议的高效实现与应用

1. 项目概述:MCP Python SDK 是什么? 在当今数据驱动的技术环境中,模型上下文协议(Model Context Protocol,简称MCP)正逐渐成为连接机器学习模型与实际业务场景的关键桥梁。作为一名长期从事AI工程化的开发…

2026/10/14 12:58:58 阅读更多 →
PyInstaller 3.2.1实战:老版本打包器解决Python旧工程分发难题

PyInstaller 3.2.1实战:老版本打包器解决Python旧工程分发难题

简介:PyInstaller 3.2.1是一份面向Python开发者的跨平台打包工具资源,旨在解决Python程序在无解释器环境下的分发难题,适合需要将脚本封装为独立可执行文件的入门及进阶用户。压缩包内含790个文件,约3.01MB,以py源码、…

2026/10/14 12:58:58 阅读更多 →

最新新闻

整车八自由度Simulink动力学模型搭建:从方程到仿真验证

整车八自由度Simulink动力学模型搭建:从方程到仿真验证

做整车动力学仿真的人,几乎都会经历从二自由度自行车模型起步,再逐步往多自由度模型走的过程。二自由度模型能把横摆和侧向运动的基本逻辑讲清楚,但一涉及到载荷转移、侧倾对轮荷分布的影响、四个车轮独立的转速动力学,它就完全不…

2026/10/14 13:48:57 阅读更多 →
IMX6ULL嵌入式Linux文件系统目录操作指南

IMX6ULL嵌入式Linux文件系统目录操作指南

1. 项目概述作为一名嵌入式Linux开发者,我最近开始深入研究IMX6ULL这款性价比极高的ARM Cortex-A7开发板。在嵌入式Linux开发中,文件系统目录结构的理解和常用目录操作命令的掌握是基础中的基础。这篇文章将分享我在IMX6ULL开发板上学习Linux文件目录结构…

2026/10/14 13:48:57 阅读更多 →
快慢指针原理与实战:链表中间节点、环检测与入口定位

快慢指针原理与实战:链表中间节点、环检测与入口定位

1. 为什么快慢指针是链表问题的“万能钥匙”?——从三个经典问题看算法设计的本质快慢指针不是什么高深莫测的黑科技,它本质上是一种空间换时间的朴素思想在链表结构上的极致应用。我带过不少刚学数据结构的学生,他们第一次看到“用两个指针一…

2026/10/14 13:48:57 阅读更多 →
Workbench齿轮动力学仿真与工程优化实践

Workbench齿轮动力学仿真与工程优化实践

1. 项目概述:齿轮仿真的工程价值齿轮传动作为机械工业的"细胞",其动态特性直接影响着整个传动系统的可靠性、噪声水平和寿命。传统设计方法依赖经验公式和静态计算,难以捕捉高速运转下的真实行为。Workbench平台提供的齿轮动力学仿…

2026/10/14 13:48:57 阅读更多 →
C# OPC客户端调试:DA与UA双协议连接、读取、订阅全链路诊断

C# OPC客户端调试:DA与UA双协议连接、读取、订阅全链路诊断

简介:本资源是一个面向工业自动化与.NET开发者的C# OPC客户端实战项目,聚焦于使用OPC Net Api Chs库实现与OPC服务器的连接、数据读写、事件订阅及异常处理等核心通信功能,适用于具备基础C#和WinForm开发能力的中高级工程师学习工业协议集成。…

2026/10/14 13:48:57 阅读更多 →
ponytail:一个轻量原生JS前端插件,轻松搞定H5底部导航与运营浮层

ponytail:一个轻量原生JS前端插件,轻松搞定H5底部导航与运营浮层

ponytail 这个名字,好多人第一次听到都以为是来聊发型的。其实它是我很早就为了处理移动端 H5 底部导航和运营浮层写的一个微型前端插件,核心干的事情就一件:在页面任意指定位置追加一块内容,同时把动画、状态记忆、批量挂载这些看…

2026/10/14 13:47:56 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →