codex秒生成的小游戏--贪吃蛇
!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title贪吃蛇/title style *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } body { background: #111; display: flex; justify-content: center; align-items: center; min-height: 100vh; font-family: Segoe UI, system-ui, sans-serif; color: #e0e0e0; } .game-wrapper { background: #1a1a2e; border-radius: 16px; padding: 24px; box-shadow: 0 8px 40px rgba(0,0,0,0.6); } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; padding: 0 4px; } .score-box { font-size: 18px; font-weight: 600; letter-spacing: 0.3px; } .score-box span { color: #f0c040; } .controls { display: flex; gap: 8px; } .controls button { background: #2d2d4e; border: none; color: #ccc; font-size: 14px; padding: 6px 18px; border-radius: 6px; cursor: pointer; transition: background 0.15s; font-family: inherit; } .controls button:hover { background: #3d3d5e; } .controls button:active { background: #4d4d6e; } canvas { display: block; background: #0f0f23; border-radius: 10px; width: 480px; height: 480px; image-rendering: pixelated; } .footer { margin-top: 12px; text-align: center; font-size: 13px; color: #666; } .footer kbd { background: #2a2a3e; padding: 2px 8px; border-radius: 4px; font-family: inherit; font-size: 12px; color: #aaa; } media (max-width: 540px) { .game-wrapper { padding: 16px; border-radius: 12px; } canvas { width: calc(100vw - 64px); height: calc(100vw - 64px); } } /style /head body div classgame-wrapper div classheader div classscore-box span idscore0/span/div div classcontrols button idrestartBtn重新开始/button /div /div canvas idgameCanvas width480 height480/canvas div classfooterkbd↑/kbd kbd↓/kbd kbd←/kbd kbd→/kbd 或 kbdW/kbdkbdA/kbdkbdS/kbdkbdD/kbd 控制方向/div /div script (function(){ const canvas document.getElementById(gameCanvas); const ctx canvas.getContext(2d); const scoreEl document.getElementById(score); const GRID_SIZE 20; // 20×20 网格 const CELL_SIZE 24; // 480/20 const TICK_MS 140; let snake, direction, nextDirection, food, score, gameOver, win; let timer null; // ---- 初始化 / 重置 ---- function init() { snake [ { x: 10, y: 10 }, { x: 9, y: 10 }, { x: 8, y: 10 }, ]; direction { x: 1, y: 0 }; nextDirection { x: 1, y: 0 }; score 0; gameOver false; win false; scoreEl.textContent 0; spawnFood(); draw(); } // ---- 生成食物不与蛇重叠 ---- function spawnFood() { const occupied new Set(snake.map(p ${p.x},${p.y})); const free []; for (let y 0; y GRID_SIZE; y) for (let x 0; x GRID_SIZE; x) if (!occupied.has(${x},${y})) free.push({ x, y }); if (free.length 0) { win true; gameOver true; food null; return; } food free[Math.floor(Math.random() * free.length)]; } // ---- 游戏逻辑 ---- function tick() { if (gameOver) return; direction { ...nextDirection }; const head snake[0]; const nx head.x direction.x; const ny head.y direction.y; // 撞墙 if (nx 0 || nx GRID_SIZE || ny 0 || ny GRID_SIZE) { gameOver true; draw(); return; } // 撞自身 for (const seg of snake) { if (seg.x nx seg.y ny) { gameOver true; draw(); return; } } // 移动 snake.unshift({ x: nx, y: ny }); const ate (food nx food.x ny food.y); if (ate) { score; scoreEl.textContent score; spawnFood(); } else { snake.pop(); } draw(); } // ---- 绘制 ---- function draw() { ctx.clearRect(0, 0, 480, 480); // 网格线很淡 ctx.strokeStyle rgba(255,255,255,0.03); ctx.lineWidth 0.5; for (let i 0; i GRID_SIZE; i) { const p i * CELL_SIZE; ctx.beginPath(); ctx.moveTo(p, 0); ctx.lineTo(p, 480); ctx.stroke(); ctx.beginPath(); ctx.moveTo(0, p); ctx.lineTo(480, p); ctx.stroke(); } // 食物 if (food) { const fx food.x * CELL_SIZE, fy food.y * CELL_SIZE; // 苹果渐变 const grad ctx.createRadialGradient(fx6, fy6, 2, fx12, fy12, 14); grad.addColorStop(0, #f55); grad.addColorStop(1, #c33); ctx.fillStyle grad; ctx.beginPath(); ctx.arc(fx CELL_SIZE/2, fy CELL_SIZE/2, CELL_SIZE/2 - 2, 0, Math.PI*2); ctx.fill(); // 高光 ctx.fillStyle rgba(255,255,255,0.25); ctx.beginPath(); ctx.arc(fx 8, fy 8, 3, 0, Math.PI*2); ctx.fill(); } // 蛇身 for (let i snake.length - 1; i 0; i--) { const seg snake[i]; const sx seg.x * CELL_SIZE, sy seg.y * CELL_SIZE; const pad 1; const radius 4; const t i / Math.max(snake.length - 1, 1); // 头部亮绿 → 尾部暗绿 const r Math.round(30 t * 20); const g Math.round(200 - t * 80); const b Math.round(80 - t * 40); ctx.fillStyle rgb(${r},${g},${b}); // 圆角矩形 const x sx pad, y sy pad; const w CELL_SIZE - pad*2, h CELL_SIZE - pad*2; ctx.beginPath(); ctx.moveTo(x radius, y); ctx.lineTo(x w - radius, y); ctx.quadraticCurveTo(x w, y, x w, y radius); ctx.lineTo(x w, y h - radius); ctx.quadraticCurveTo(x w, y h, x w - radius, y h); ctx.lineTo(x radius, y h); ctx.quadraticCurveTo(x, y h, x, y h - radius); ctx.lineTo(x, y radius); ctx.quadraticCurveTo(x, y, x radius, y); ctx.closePath(); ctx.fill(); } // 蛇眼睛头部 if (snake.length 0 !gameOver) { const head snake[0]; const hx head.x * CELL_SIZE, hy head.y * CELL_SIZE; ctx.fillStyle #fff; let e1x, e1y, e2x, e2y; if (direction.x 1) { e1xhx16; e1yhy6; e2xhx16; e2yhy16; } else if (direction.x -1) { e1xhx6; e1yhy6; e2xhx6; e2yhy16; } else if (direction.y 1) { e1xhx6; e1yhy16; e2xhx16; e2yhy16; } else { e1xhx6; e1yhy6; e2xhx16; e2yhy6; } ctx.beginPath(); ctx.arc(e1x, e1y, 3, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(e2x, e2y, 3, 0, Math.PI*2); ctx.fill(); ctx.fillStyle #111; ctx.beginPath(); ctx.arc(e1x, e1y, 1.5, 0, Math.PI*2); ctx.fill(); ctx.beginPath(); ctx.arc(e2x, e2y, 1.5, 0, Math.PI*2); ctx.fill(); } // 游戏结束遮罩 if (gameOver) { ctx.fillStyle rgba(0,0,0,0.55); ctx.fillRect(0, 0, 480, 480); ctx.fillStyle #fff; ctx.font bold 28px system-ui, sans-serif; ctx.textAlign center; ctx.textBaseline middle; const msg win ? 你赢了 : 游戏结束; ctx.fillText(msg, 240, 210); ctx.font 16px system-ui, sans-serif; ctx.fillStyle #aaa; ctx.fillText(点击「重新开始」再来一局, 240, 260); } } // ---- 键盘控制 ---- function handleKey(e) { const key e.key; if ([ArrowUp,ArrowDown,ArrowLeft,ArrowRight,w,W,s,S,a,A,d,D].includes(key)) e.preventDefault(); if (gameOver) return; const opp (d1, d2) (d1.x -d2.x d1.y -d2.y); let nd null; if (key ArrowUp || key w || key W) nd { x: 0, y: -1 }; else if (key ArrowDown || key s || key S) nd { x: 0, y: 1 }; else if (key ArrowLeft || key a || key A) nd { x: -1, y: 0 }; else if (key ArrowRight || key d || key D) nd { x: 1, y: 0 }; if (nd !opp(nd, direction)) nextDirection nd; } // ---- 启动/停止循环 ---- function startLoop() { stopLoop(); timer setInterval(tick, TICK_MS); } function stopLoop() { if (timer) { clearInterval(timer); timer null; } } function restart() { init(); startLoop(); } // ---- 绑定事件 ---- document.addEventListener(keydown, handleKey); document.getElementById(restartBtn).addEventListener(click, restart); // ---- 开始 ---- init(); startLoop(); })(); /script /body /html

相关新闻

时空态势立体感知 零断点接力追踪驱动安防全域智变技术白皮书

时空态势立体感知 零断点接力追踪驱动安防全域智变技术白皮书

时空态势立体感知 零断点接力追踪驱动安防全域智变技术白皮书编制单位:镜像视界浙江科技有限公司核心定位:基于SpaceOS全域空间计算底座、八大自研引擎,以时空态势立体感知、零断点跨镜接力追踪为核心的安防全域智能化升级体系1. 前言时空态势…

2026/6/28 1:28:09阅读更多 →
每天奋战12个小时,赚不到钱,真是天理难容 —— 这一篇文章送给自己

每天奋战12个小时,赚不到钱,真是天理难容 —— 这一篇文章送给自己

这句话,不是抱怨。是我的底气。也是我的宣言。我不相信努力一定成功。但我更不相信,真正的拼命,会一直没有结果。每天12个小时。不是坐在电脑前12个小时。不是加班12个小时。不是假装忙碌12个小时。而是12个小时都在创造价值。都在成长。都在…

2026/6/28 1:28:09阅读更多 →
【频谱分配】基于遗传算法和粒子群算法认知无线电频谱分配研究附Matlab代码

【频谱分配】基于遗传算法和粒子群算法认知无线电频谱分配研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、算法改进、程序设计科研仿真。🍎完整代码获取 定制创新 论文复现私信🍊个人信条:做科研,博学之、审问之、慎思之、明辨之、…

2026/6/28 1:23:09阅读更多 →
“原型谬误”:语法正确与语义正确的混淆

“原型谬误”:语法正确与语义正确的混淆

为什么“AI 精神病”极易在公司高管层蔓延,而一线的技术负责人对此则表现的相当警惕?因为决策者混淆了“原型”与“生产系统”的边界。 非技术背景的决策者在评估 AI 能力时,通常是在完全受控的方式下进行的。比如 AI 在几秒钟内生成一个可运…

2026/6/28 3:03:15阅读更多 →
MCP(Model Context Protocol)深度解读:为什么 AI Agent 都需要一个标准化的“连接器“

MCP(Model Context Protocol)深度解读:为什么 AI Agent 都需要一个标准化的“连接器“

最近刷到 AI Agent 时,我第一反应不是"又一个热点",而是它已经开始改变普通开发者每天工作的顺序。 一、先看现场:AI Agent发生了什么 1.1 事件、产品或趋势的核心上下文 2024 年底,Anthropic 推出 Model Context Pr…

2026/6/28 3:03:15阅读更多 →
工业化交付的基石:深度拆解 3DGS 全能预处理工厂 —— GSBox

工业化交付的基石:深度拆解 3DGS 全能预处理工厂 —— GSBox

1. 引言:渲染器只是冰山一角 在 3D Gaussian Splatting (3DGS) 的热潮中,大家往往把目光聚焦在“谁的渲染器更快、更亮”上。然而,对于真正做项目交付的开发者来说,最头疼的问题往往发生在渲染之前: 训练出来的原始 .p…

2026/6/28 3:03:15阅读更多 →
Ollama部署和LLama Factory框架安装教程

Ollama部署和LLama Factory框架安装教程

目录 一、什么是Ollama, LLama Factory 1. Ollama:本地大模型运行器 2. Qwen、Gemma、DeepSeek:模型本身 3. Miniconda:Python 环境管理工具 4. PyTorch:训练和推理的计算库 5. LLaMA-Factory:大模型微调框架 二…

2026/6/28 3:03:15阅读更多 →
智能锡膏管理技术哪家强?看这3项指标就懂

智能锡膏管理技术哪家强?看这3项指标就懂

好的,遵照您的指示,以下是基于您提供的角色、任务和规范的行业分析文章。在SMT(表面贴装技术)行业,锡膏作为关键的焊接材料,其存储、管理与使用直接关系到最终电子产品的焊接质量与可靠性。传统的“冰箱人工…

2026/6/28 3:03:15阅读更多 →
现场直击:那场让人崩溃的深夜生产事故相信很多研发和运维朋友都经历过这样的“生死时刻”:

现场直击:那场让人崩溃的深夜生产事故相信很多研发和运维朋友都经历过这样的“生死时刻”:

凌晨两点,手机突然疯狂震动,监控系统的告警短信像连珠炮一样炸开: [FATAL] 02:14:15 Core-Service CPU Usage > 92% [ERROR] 02:15:02 API Gateway 504 Gateway Timeout rate > 15%你睡眼惺忪地打开电脑,一边在群里回复“收…

2026/6/28 2:58:15阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/6/28 0:08:01阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/6/28 0:08:01阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/6/28 0:08:01阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/6/28 0:08:01阅读更多 →