尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python与Pyglet复刻Minecraft:从零构建体素渲染与碰撞检测
简介这是一份用Python和Pyglet实现的Minecraft风格迷你演示程序面向想入门3D编程或游戏开发的Python学习者也适合编程教师用作少儿兴趣案例。项目刻意保持轻量与可读main.py演示了窗口创建、纹理加载、方块放置和简单交互代码量不大便于逐行拆解、改参数和二次扩展。整个压缩包共4个文件包括1个Python脚本、1张纹理PNG、1份README和1份LICENSE整体仅16KB结构非常紧凑代码风格也直白友好适合作为课程设计基础。作者在说明中明确希望把它变成教育工具让孩子通过熟悉的Minecraft世界接触Python因此除直接运行外读者还可以从源码中学习Pyglet的基本用法、三维坐标系与事件循环思路并借助README了解配置方式和扩展方向。当前已有511人学习/下载整体适合用于课堂演示、编程工作坊或个人练手也可作为基于Python的简易体素世界模板。1. 用 Python 和 Pyglet 复刻 Minecraft 的“盒中世界”一个能跑能玩的体素课堂看到这个标题的第一反应大多数人会以为是拿 Python 做个 Minecraft 的“低配复刻”但真去写过的人知道它其实是把方块世界和第一人称操作这两块硬骨头一次性啃完的练手项目。用 Python 和 Pyglet 写一个受 Minecraft 启发的简单程序技术上等于自己搭一个最小体素引擎方块存储、纹理映射、视野裁剪、碰撞检测一样都绕不开。这个方向值不值得做对三类人特别值想理解体素游戏底层逻辑的开发者做毕设或课程设计的学生以及想找个 3D 渲染实战项目的 Python 爱好者。做完你会得到一个能走能跳、能挖能放、勉强能看的“盒子世界”更重要的是能彻底想明白那些商业体素引擎背地里到底在算什么。有几点需要提前说清楚这不是商业游戏的替代品渲染用的还是 OpenGL 教学里最朴素的四边形绘制方式它追求的也不是画面而是机制完整。下面我按照“为什么这么选 → 怎么跑通 → 坑在哪 → 怎么升级”的顺序讲。2. 为什么用 Python 和 Pyglet技术选型与渲染架构老规矩先说结论这个项目能跑起来靠的不是哪个大而全的引擎而是 Python 标准库加 Pyglet 这一个窗口库。很多人第一反应是问为什么不用 PyQt5、pygame 或者 Panda3D因为做这种教学向体素程序选型的核心是“依赖最少、看得见底层”。Pyglet 恰好站在那个位置上。2.1 Pyglet 是 OpenGL 的薄封装不是游戏引擎Pyglet 在社区里的定位是一个媒体库它把窗口创建、事件循环、键盘状态、图像加载和 OpenGL 绑定都封装好了但游戏循环、场景图、碰撞体系一概不管。这意味着你用 Pyglet 写的每个方块顶点都是你亲手填的渲染调用也是你亲手发的。对“受 Minecraft 启发”这种教学项目来说这是优点不是缺点。对比一下就清楚。pygame 的强项是 2D 表面的 blit 和 sprite 系统要做 3D 得自己在 SDL 表面之上再加一层软渲染等于凭空多写一层东西PyQt5 倒是能挂 QOpenGLWidget但 Qt 的事件循环和信号槽会把项目绑得很死窗口库的复杂度反过来干扰游戏逻辑。Panda3D、Godot 的 Python 绑定很强可对“简单程序”而言自带场景图、光照和角色控制器反而让你看不到体素引擎真正要处理的问题。所以社区里这类教程几乎都默认 Pyglet。还有一层原因Pyglet 对老式 OpenGL 立即模式glBegin/glEnd没有限制新手可以用最直白的方式描述“一个方块由六个四边形组成”等理解了再跳到 VBO。坏处后面第 4 章会说立即模式确实慢但那是优化问题不是选型问题。2.2 体素世界怎么存字典比三维数组更合适决定画方块之前先决定世界数据怎么放。最常见的三种做法是三维列表、NumPy 数组、字典映射。教程版本里出现频率最高的是字典dict因为体素世界天然是稀疏的。三维列表看着直观但代价是“先分配再填充”。假设世界范围是 32×32×128开一个三维列表就有 13 万个元素其中绝大部分是空气。空气占了存储却没有任何渲染价值更麻烦的是遍历整个世界画方块时list 版本得扫一遍所有空气才能知道它们不存在。NumPy 数组能压缩内存但 shape 的顺序x, y, z 还是 z, y, x和切片方向经常把人绕晕跑着跑着发现地形是躺着的。字典的做法很简单键是坐标三元组x, y, z值是方块类型 id。空气根本不进字典查询一个坐标是否存在方块就是一次哈希查找删除方块用del world[(x,y,z)]就能释放内存。对“简单程序”这个目标它是清晰度和性能之间最合理的平衡点。不过有个细节值得一开始就注意到Python 的整数和元组都有内存开销一个坐标元组加上键值对大概吃掉 100 字节左右。世界方块数量在几千个时无所谓到几百万个时就不行了。到那时候有两个常见升级路径一是把坐标打包成一个整数用位运算解压二是把世界切成固定大小的 chunk每个 chunk 内部用紧凑数组。第 5 章会讲打包的写法这里只是让你知道为什么老版本教程后期都往 chunk 方向改。2.3 纹理图集与对面剔除两个经典省性能手段“受 Minecraft 启发”的程序里看起来最简单的部分其实是渲染。每个方块有六个面每个面是一张四边形纹理但如果你真的对每个方块调用六次纹理绑定几百个方块就能让帧率掉到没法看。原因是 OpenGL 切换纹理是状态变更状态变更越多驱动端的开销越大。解决方案是纹理图集texture atlas把草方块顶面、草方块侧面、泥土、石头这些所有用得到的纹理拼进一张 PNG渲染时一次只绑定这一张大图画不同方块时只改 UV 坐标。一块纹理在图集里的位置是固定的比如图集横竖各两格那么草顶占左上四分之一石头占右下四分之一。这样一次绑定全场景受益。另一个手段是“对面剔除”face culling这个词容易和 OpenGL 自带的背面剔除混淆含义不同。这里说的是如果一个方块的某个面与另一个非空气方块直接相邻那这个面根本看不见不用画。看数据一个 64×64、平均高度 16 层的世界如果六个面全画画面里有大量隐藏面剔除相邻面之后地表那一层的可见面往往只剩四分之一。写进代码里就是判断相邻坐标在不在 world 字典里代价是一次哈希收益是几何级数下降。3. 从 Python 环境到第一个方块用 Pyglet 跑通最小体素世界这一段进入正题。先说环境项目依赖只有两个pyglet 和 pillow。pillow 不是必须的如果你已经有纹理图集图片就不用装但作为从零开始的教程用它生成占位贴图最省事。pip install pyglet pillowPython 版本建议 3.8 以上Pyglet 2.x 对 3.11、3.12 都支持得很稳。老教程大多是 Pyglet 1.5 时代的写法2.x 里pyglet.app.run()和窗口 API 基本没变可以直接抄只有少数常量位置有出入。3.1 初始化窗口、事件循环与鼠标视角第一个代码块负责窗口、输入状态和主循环入口。import math import pyglet from pyglet.gl import * WINDOW_WIDTH, WINDOW_HEIGHT 800, 600 FOV 70.0 window pyglet.window.Window(WINDOW_WIDTH, WINDOW_HEIGHT, captionMiniCraft, resizableTrue) # 键盘状态全局只 push 一次 keys pyglet.window.key.KeyStateHandler() window.push_handlers(keys) # 视角状态yaw 绕Y轴旋转pitch 绕X轴 yaw, pitch 0.0, 0.0 # pos 和 velocity 将在 3.5 节定义 # on_draw 运行时它们已经是全局变量所以这里可以引用 window.event def on_mouse_motion(dx, dy): global yaw, pitch yaw (yaw dx * 0.15) % 360.0 pitch max(-89.0, min(89.0, pitch - dy * 0.15)) window.event def on_resize(width, height): glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(FOV, width / float(height), 0.1, 100.0) glMatrixMode(GL_MODELVIEW) window.event def on_draw(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() glRotatef(pitch, 1, 0, 0) glRotatef(yaw, 0, 1, 0) glTranslatef(-pos[0], -pos[1], -pos[2]) draw_scene() # 3.4 节实现 # pyglet.app.run() 放在整个程序最后这个块的作用是把窗口、输入和 OpenGL 的投影矩阵、视图矩阵搭起来。on_mouse_motion里 dx、dy 是鼠标相对位移乘 0.15 是灵敏度系数很多人第一次做会漏掉这个乘数结果视角转得像抽风pitch 限制在 ±89 度是为了防止视角翻到头顶。on_resize里gluPerspective的近裁剪面设 0.1远裁剪面 100这决定了你能看多远的世界配合后面第 4 章的视野裁剪使用。on_draw里的三行glRotatef/glTranslatef把摄像机放在 pos 位置并看向 yaw、pitch 方向这是 OpenGL 老式固定管线做视角变换的标准顺序先转后移。3.2 生成一方地形简单高度函数与字典写入第二个代码块是地形生成。目标很朴素扫一遍平面的 x、z 坐标算出每个坐标的高度然后把“石头地基 → 泥土 → 草顶块”从下往上填进 world 字典。GRASS, DIRT, STONE 1, 2, 3 world {} SEED 20240601 WORLD_RADIUS 32 # 半宽生成 64x64 的地表 def terrain_height(x, z): 叠加两个正弦波得到一个起伏但不至于离谱的高度 return int(16 math.sin(x * 0.3 SEED) * 4 math.cos(z * 0.25 SEED) * 3) def generate_world(): for x in range(-WORLD_RADIUS, WORLD_RADIUS): for z in range(-WORLD_RADIUS, WORLD_RADIUS): h terrain_height(x, z) for y in range(h): if y 0: world[(x, y, z)] STONE elif y h - 1: world[(x, y, z)] GRASS else: world[(x, y, z)] DIRT generate_world()逻辑说明外层两个 for 循环遍历地表坐标内层 for 循环从 y0 填到高度 h。高度函数用两个不同频率的正弦波叠加效果比单个 sin 波自然一点SEED 是一个固定值这样每次运行世界都一样便于调试。如果想让每次生成不同世界把 SEED 换成随机数即可。参数说明。WORLD_RADIUS32 意味着生成 64×64 的地表每个柱子的平均高度约 16 层方块总量在 6 万左右立即模式渲染时这个规模明显卡但用来验证逻辑完全够。想快速验证世界结构可以临时打印一个横截面把 world 里 y8 那层扫出来按字符输出比直接开窗口调试快得多。3.3 纹理素材与 UV 映射让方块有颜色第三步是纹理。你说“我还没有方块贴图”——没关系先用 Pillow 生成一张 2×2 格子的测试图集四个格子分别是草顶、草侧、泥土和石头每格 16×16 像素。以后有美术素材了直接替换这张 PNG 就行。from PIL import Image img Image.new(RGB, (32, 32)) img.paste((100, 180, 80), (0, 0, 16, 16)) # 草顶偏绿 img.paste((150, 110, 60), (16, 0, 32, 16)) # 草侧土绿 img.paste((120, 80, 40), (0, 16, 16, 32)) # 泥土棕色 img.paste((130, 130, 130), (16, 16, 32, 32)) # 石头灰 img.save(textures.png) # 注意纹理加载必须在 Window 创建之后 tex pyglet.image.load(textures.png).get_texture() def uv(block_id, face): 返回该方块该面在图集里的 (u0, v0, u1, v1) if block_id GRASS: tx, ty (0, 0) if face top else (1, 0) elif block_id DIRT: tx, ty 0, 1 else: # STONE tx, ty 1, 1 # Pyglet 的纹理坐标原点在左下PIL 的 Y 轴方向相反所以翻转 v u0, v0 tx / 2, 1.0 - (ty 1) / 2 u1, v1 (tx 1) / 2, 1.0 - ty / 2 return u0, v0, u1, v1为什么要把图集设成 2×2 格子因为最常用的方块类型就 4 个每格 16×16 像素够用像素少了会糊多了浪费显存。后续要加沙子和木头把图集改成 3×3 或 4×4 即可唯一要改的是 uv 函数里除以的倍数。这里必须提醒一个像素级翻车点PIL 保存图片时第 0 行是图像顶部OpenGL 纹理坐标里 v0 在图像底部。如果直接拿 ty 算 v 坐标草顶和泥土会上下颠倒视觉上拼接处不对。上面代码里的 v 翻转是必要操作不是玄学。3.4 绘制方块与场景六个面一个不少渲染部分拆成两层draw_block 负责画一个方块draw_scene 遍历 world 字典并做距离裁剪。注意一个方块必须画出完整的六个面否则从侧面看会漏进世界内部。def draw_block(x, y, z, block_id): u0, v0, u1, v1 uv(block_id, side) glBindTexture(GL_TEXTURE_2D, tex.id) glBegin(GL_QUADS) # (x,y,z) 是方块左下后角按逆时针顺序画每个面 faces [ # 顶面 ((x, y1, z), (x1, y1, z), (x1, y1, z1), (x, y1, z1)), # 底面 ((x, y, z), (x, y, z1), (x1, y, z1), (x1, y, z)), # 北侧z 负方向 ((x, y, z), (x1, y, z), (x1, y1, z), (x, y1, z)), # 南侧z 正方向 ((x, y, z1), (x, y1, z1), (x1, y1, z1), (x1, y, z1)), # 西侧x 负方向 ((x, y, z), (x, y1, z), (x, y1, z1), (x, y, z1)), # 东侧x 正方向 ((x1, y, z), (x1, y, z1), (x1, y1, z1), (x1, y1, z)), ] for f in faces: glTexCoord2f(u0, v0); glVertex3f(*f[0]) glTexCoord2f(u1, v0); glVertex3f(*f[1]) glTexCoord2f(u1, v1); glVertex3f(*f[2]) glTexCoord2f(u0, v1); glVertex3f(*f[3]) glEnd() def draw_scene(): glEnable(GL_DEPTH_TEST) px, py, pz pos for (bx, by, bz), bid in world.items(): if abs(bx - px) 8 and abs(bz - pz) 8 and abs(by - py) 8: draw_block(bx, by, bz, bid)draw_scene 里的距离判断就是 2.3 节说的简单视野裁剪只处理玩家周围半径 8 格内的方块。这个数字先写死跑起来之后调成变量你就能直观感受到帧率和渲染量之间的关系。顶面到底用哪套 UV上面的简化版统一用了侧面纹理草顶绿色效果看不到。如果你想让草顶显示绿色需要在 draw_block 里对顶面单独调用uv(block_id, top)再画这也是教材版本里最常见的进阶改动。先跑通再调别在这个阶段钻进去。3.5 键盘移动与碰撞检测三轴分离的 AABB最后一步是让人能走起来。这里的核心不是键盘监听那个已经在 3.1 里通过 KeyStateHandler 解决了而是碰撞检测。做法是把玩家近似成一个 0.6×1.8×0.6 的长方体用它的边角点去查 world 字典只要任意一个角点落在方块里就算碰撞。移动时三个轴分开处理先动 X不行就回退并清零该轴速度再动 Z最后动 Y这样能避免斜向穿墙和“卡墙角”两大经典事故。GRAVITY 25.0 WALK_SPEED 5.0 JUMP_SPEED 7.0 velocity [0.0, 0.0, 0.0] pos [0.0, 20.0, 0.0] # 出生在 y20 上空等它落下来 def collides(x, y, z): 用身体包围盒的 8 个角点检测是否与方块重合 for ox in (-0.3, 0.3): for oy in (-0.9, 0.9): for oz in (-0.3, 0.3): if (int(x ox), int(y oy), int(z oz)) in world: return True return False def move_player(dt): global pos, velocity # 地面移动把 yaw 角度换算成前进/横移向量 sin_y, cos_y math.sin(math.radians(yaw)), math.cos(math.radians(yaw)) fwd (int(keys[pyglet.window.key.W]) - int(keys[pyglet.window.key.S])) * WALK_SPEED strafe (int(keys[pyglet.window.key.D]) - int(keys[pyglet.window.key.A])) * WALK_SPEED velocity[0] fwd * sin_y strafe * cos_y velocity[2] fwd * cos_y - strafe * sin_y # 跳跃与重力 if keys[pyglet.window.key.SPACE] and on_ground(): velocity[1] JUMP_SPEED velocity[1] - GRAVITY * dt # 三轴分离移动 for axis in range(3): old pos[axis] pos[axis] velocity[axis] * dt if collides(*pos): pos[axis] old velocity[axis] 0.0 def on_ground(): 脚底正下方 0.31 格处有没有方块 return collides(pos[0], pos[1] - 0.31, pos[2]) pyglet.clock.schedule(move_player) pyglet.app.run() # 整个程序的最后一行逻辑关键在最后的 for 循环一次只移动一个轴发生碰撞就把这个轴回退速度清零。这样即使斜着走也不会把两个轴向的误差叠加到穿模。on_ground 用 y-0.31 而不是正好贴在脚边是因为整数坐标转换的误差可能让你跳不起来留一点余量即可。参数参考。GRAVITY25.0 比真实重力加速度大不少游戏手感会更“沉”WALK_SPEED5.0 是每秒 5 格JUMP_SPEED7.0 配合 25 的重力跳起高度大概接近 1 格刚好能跳上草地台阶。这三个参数直接决定手感别照抄边改边找感觉。4. 常见问题与性能排查新手最容易翻车的五个点网上流传的免费 python 源码大全里体素 demo 永远是最多的一类但那些“python 的 mc 代码免费复制”版本绝大多数第一次跑都跑不起来或者跑起来几秒就扑街。下面这五条是我觉得最典型的每一条都按现象 → 原因 → 解决来写。4.1 现象所有方块贴图全黑或者整块方块是一种颜色原因最常见的是没有启用纹理。OpenGL 里纹理默认是关闭的你需要至少调用一次glEnable(GL_TEXTURE_2D)另一个常见原因是 UV 方向写反导致图片像素被采样到图集外的区域。还有一种坑pyglet.image.load返回的对象在窗口初始化前加载会报错纹理加载一定要放在 Window 创建之后。解决在 draw_block 前调用glEnable(GL_TEXTURE_2D)或用glTexParameteri把纹理环绕方式设为 GL_CLAMP_TO_EDGE。UV 方向问题就按 3.3 节的 v 翻转处理。如果报错信息里带 “No window found”直接把纹理加载那两行挪到 Window 创建之后。4.2 现象帧率从几十帧突然掉到个位数原因尺寸没控制好。64×64 地表 立即模式 六个面全画 距离裁剪半径过大四个条件凑齐就算高性能显卡也救不回来命令提交的 CPU 开销就够卡了。解决优先做两件事。第一把 draw_scene 里半径 8 改成可调参数先压到 5 验证是不是裁剪问题第二开启 2.3 节说的对面剔除判断相邻坐标是否在 world 里在的话就跳过那个面。如果还卡把world.items()的遍历改成按 chunk 维护的局部坐标列表提前一轮循环刷掉距离太远的方块别等到 draw_block 里面再判断距离。4.3 现象角色站在方块边缘慢慢往下陷或者跳一下直接穿过天花板原因碰撞检测只检测脚下那一格无视了玩家身体体积或者一次移动的位移量大于方块边长。帧率掉到 10 帧以下时每帧位移 5/100.5 格刚好和方块边长同一个量级穿模就出现了。解决用 3.5 节的 AABB 包裹体采样保证三个轴都有体积约束同时把最大位移钳制在一帧不超过 0.4 格超过就插值。最直观的调试法是把碰撞体画出来在 pos 周围画 8 个glPointSize大一点的 GL_POINTS 标记点贴着墙走一遍就能看到是哪个角点先撞墙。4.4 现象窗口黑屏、鼠标锁死或者 glBegin 直接报 GLError原因常驻三个源头。一是 Pyglet 2.x 在高版本 OpenGL 环境下创建的上下文可能是 core profile立即模式函数 glBegin/glEnd 在 core profile 里不存在一调用就 GLError 或黑屏二是set_exclusive_mouse(True)在窗口未聚焦时调用造成鼠标锁死三是纹理在窗口创建之前加载造成的空上下文错误。解决先确认是不是 core profile最直接的办法是打印pyglet.gl.current_context.get_version()如果拿到 3.3立即模式基本没法用直接升级到第 5 章的 batch 绘制。如果是鼠标独占把 set_exclusive_mouse 延后到第一次鼠标移动事件之后用标志位控制只执行一次。如果纹理加载报错把加载挪到 Window 创建之后。4.5 现象源代码目录跑得好好的打成 exe 给朋友运行时报找不到 textures.png原因打包后当前工作目录不是 exe 所在目录资源文件用相对路径加载时指向的是启动时的工作目录。解决资源路径用绝对路径定位最稳妥的是这样写from pathlib import Path RESOURCE_DIR Path(__file__).parent tex pyglet.image.load(str(RESOURCE_DIR / textures.png)).get_texture()如果你用的打包工具是把文件打进临时目录比如 PyInstaller 的 onefile 模式还要再加上sys._MEIPASS判断。这条属于“最后调试半天其实是路径玄学”的典型坑先记住__file__才是你的家。5. 从简单程序到可扩展的小世界VBO、存档与验证三板斧最后一章不谈大道理只给三个能立刻动手的升级方向以及对应的验证办法。5.1 升级渲染用 VBO 把顶点一次性丢给显卡立即模式慢的根源是每个顶点都从 CPU 走一遍驱动。改成 VBO 之后静态方块未被破坏、未放置的顶点只在生成时算一次后续每帧只发一次glDrawArrays。做法是遍历 world把每个可见面的四顶点坐标和 UV 拼进 Python list再用pyglet.graphics.vertex_list创建批次。方块被挖掉或放置时只重建该 chunk 的顶点列表。这一步做完同屏方块数量上十倍基本不卡。5.2 存档把世界字典序列化世界数据就是一团 dict存档再简单不过用 gzip 压缩后 pickle.dump 到文件。读取时 pickle.load 回来再重新生成纹理和 VBO。要谨慎的是存盘点策略不要在游戏循环里每帧都写我见过有人这么干然后存档文件一秒钟写坏一次改成按“放置/破坏事件”触发写入或者每 30 秒自动存一次。5.3 验证方法对准三个数字第一个数字是帧率写一个计时器打印每帧 draw_scene 耗时目标是从几百毫秒降到 16 毫秒实测优化效果第二个是内存用 tracemalloc 统计 world 字典占用量当你把坐标打包成整数后对比数字能直接看到省了一半以上第三个是逻辑正确性做一个自动化测试脚本让玩家站到指定坐标断言脚下有方块、头顶无方块、跳起后能落地三轴碰撞的 bug 用这种方式回归测试比手动走位靠谱得多。我自己做第一版的时候把碰撞检测放在最后写结果角色一直穿地debug 两天才发现是忘了把身体高度算进碰撞体。这种血泪经验不实际走一遍很难真正记住。这个方向值得投入的地方不在像不像 Minecraft而在于它把游戏开发里最基础也最容易出错的几个系统都串起来了希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

中亚五国矢量图shp格式详解:数据获取、坐标系与QGIS/Python实战

中亚五国矢量图shp格式详解:数据获取、坐标系与QGIS/Python实战

简介:一份聚焦中亚五国的矢量地理数据集,含哈萨克斯坦、乌兹别克斯坦、吉尔吉斯斯坦、塔吉克斯坦和土库曼斯坦完整国界与属性信息,面向需要在ArcGIS、QGIS等主流平台开展制图、空间规划与区域分析的GIS从业者和研究者。压缩包共8个文件&#…

📅 2026/10/10 14:27:26
react-nodegui 的 RNAction 组件全解析:在 React 中驾驭 Qt 菜单动作与快捷键

react-nodegui 的 RNAction 组件全解析:在 React 中驾驭 Qt 菜单动作与快捷键

桌面应用跨平台 【免费下载链接】react-nodegui Build performant, native and cross-platform desktop applications with native React powerful CSS like styling.🚀 项目地址: https://gitcode.com/gh_mirrors/re/react-nodegui 点击查看 免费下载 …

📅 2026/10/10 14:22:25
快速带你入门深度学习与实战2

快速带你入门深度学习与实战2

3.1 逻辑回归模型先导 回归和分类的区别 有监督学习:数据带有标签(比如之前的小明的学习时长) 无监督学习:数据不带有标签(最典型的算法,聚类算法,输入一部分数据,将这些数据的类…

📅 2026/10/10 14:22:25
MORE NEWS

更多资讯

📰

给PL/0增加%和^:运算符优先级与结合性的完整实现指南

简介:这是一份编译原理课程设计资源,围绕经典PL/0教学编译器进行系统性修改与扩充,适合高校计算机专业学生完成课程设计、准备实验报告或答辩演示。基础部分已完成两类扩充:一是新增和-复合赋值运算符;二是加入Pascal风…

📰

如何快速安装Calabash-Android:从环境准备到零踩坑的完整教程

移动开发开发工具 【免费下载链接】calabash-android Automated Functional testing for Android using cucumber 项目地址: https://gitcode.com/gh_mirrors/ca/calabash-android 点击查看 免费下载 Calabash-Android 是一款用于 Android 原生与混合应用的免费开源…

📰

南航编译原理课程设计:Java手写词法与语法分析器实战指南

简介:本资源是南京航空航天大学《编译原理》课程设计的完整实现包,面向计算机专业本科生及编译技术初学者,聚焦词法分析与语法分析核心环节,提供可直接运行、经验证无BUG的工程级实践方案。压缩包共32个文件,涵盖8个关…

📰

用Python实现本地模拟横向联邦学习:从FedAvg到单机可复现实验

简介:面向机器学习初学者与联邦学习研究者的横向联邦学习本地模拟资源,使用Python构建,以公开数据集搭建可复现的单机模拟环境,让没有分布式集群的读者也能体验多客户端协作建模的完整过程。资源从数据加载、模型定义、客户端本地…

📰

Java+SSM+Django仓库管理系统:从业务建模到并发控制实践

基于JavaSSMDjango的仓库管理系统,放在毕业设计和公司信息化项目里都是老牌选题了。但网上能找到的同类源码,大多数只是把增删改查套上一个库存表的壳子,真正能对接“明嘉新材料公司”这类生产制造场景的并不多。这篇内容不是列功能清单&…

📰

YOLO实时物体检测实战:从齿条螺栓螺母裂纹数据集到TensorRT部署

简介:面向工业质检与计算机视觉开发者的YOLO实时物体检测工程包,聚焦齿条、螺栓、螺母及裂缝等目标的识别与定位,适合有深度学习基础的开发者进行算法研究或项目移植;YOLO本身将检测任务转化为单个回归问题,通过网格与…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬