L3
使用了AI的代码,所以只能归为L3。
然后 正文使用 AI 进行头脑风暴,但不是AI生成内容。
我想说的是,为了写代码而写代码,是写不好代码的。
编程是硬实力和软实力结合的体现,也许我们需要首先学习前人留下的经验来丰富自己。写给自己,可能大家过于追求效率,性能。反而忽略了自身发展,已经静不下心来看这些了吧。
代码已经不是必须品,任何一个AI都能写点东西出来。AI也能考虑架构,算法,设计。
对设计规划的影响,最后还是历经各种问题后,那个设计者的直觉。
迈出第一步
最简单的 Vibe Coding 是什么?你可以打开 gemini 输入 “帮我做一个贪吃蛇游戏” 回车。
好了,你现在已经是一个合格的 Vibe Coder 了。
这确实很爽,也能玩。但是这个代码真的写的好吗?我们可以分析一下。
如果你不会,也可以丢给其他AI进行分析一下。
1. 提速逻辑失效 (核心逻辑 Bug)
// 在 update 内部修改了 speed 变量
if (score > highScore) { ... }
if (speed > 50) speed -= 1;
// 但是计时器是在 startGame 启动时一次性绑定的
gameLoop = setInterval(update, speed);
分析: setInterval 一旦启动,其执行频率就固定了。虽然你吃到苹果后修改了全局变量 speed 的值,但计时器不会重新读取这个值。这导致无论玩家得多少分,蛇的速度永远是初始的 100ms。
2. 棋盘 tileCount 非整数导致的边界判定漂移 (数据类型 Bug)
const size = Math.min(window.innerWidth - 40, 400);
canvas.width = size;
tileCount = canvas.width / gridSize; // 结果可能是小数,如 18.75
分析: 当 tileCount 为小数时,边界判定 head.x >= tileCount 会出现偏差。例如,蛇头在坐标 18 时视觉上已经触边,但逻辑判定 18 < 18.75 依然存活,导致蛇能跑出网格线或在空隙处突然死亡。
3. 缺乏输入缓冲可能导致“自杀” (交互 Bug)
function changeDir(dir) {
switch(dir) {
case 'up': if (dy !== 1) { nextDx = 0; nextDy = -1; } break;
// ... 其他方向同理
}
}
分析: 如果蛇向右走(dx=1),玩家在极短时间内按下“上”紧接着按“左”。因为 update 还没执行,此时 dx 依然是 1,按“左”会被视为合法。下一帧更新时,蛇会瞬间 180° 原地回头撞死在自己脖子上。
4. 窗口缩放导致重置 (体验 Bug)
window.onresize = initGame;
function initGame() {
// ...
resetGameState(); // 内部重置了所有蛇的位置和分数
}
分析: 玩家在手机上不小心旋转屏幕或调整窗口大小时,onresize 会立即触发 resetGameState。这意味着玩家无论玩到多高分,都会因为一次窗口抖动而瞬间被迫重新开始。
5. 递归堆栈风险 (性能 Bug)
snake.forEach(part => {
// 递归调用自己
if (part.x === food.x && part.y === food.y) createFood();
});
分析: 在游戏后期,当蛇占据了 90% 以上的格子时,随机生成的坐标极大概率落在蛇身上。这会导致 createFood 进入极其密集的递归调用,造成画面瞬间掉帧,甚至在极端满屏情况下导致浏览器崩溃。
这些问题如果你碰到了,也不是不能让AI再次改。但你的时间精力是有限的,同时也不可能碰到所有的bug。如果一直这样进行抽卡,运气好能出来个能用的东西,运气不好就是一堆跑不通的垃圾。
从《人月神话》谈起 —— Vibe Coding
Vibe Coding 的本质不是祈祷,不是许愿。借用《人月神话》中作者强调的一个词语来说就是:
贵族专制(Aristocracy)
在 1975 年,Fred Brooks 在《人月神话》里提出了一个非常令人不快的观点:“为了获得概念的完整性,设计必须由一个人,或者非常少数互有默契的人员来实现。”
多年前,他认为,你是用户的Agent代理人,必须运用专业知识支持用户和自身的利益。
而现在,AI是你和你要做的软件之间的“代理人”
所以我们不能站在维护方——之前是程序员,现在是AI——的立场上进行辩护。
先来高兴一下,看别人碰见这些
可能你看到了会笑一笑,但是如果发生在你自己的身上了呢?
毕竟AI喜欢能不做就不做;用漂亮话糊过去;即使不确定也装得确定;过度保守或过度敷衍;为了好生成而牺牲用户真实需求。
也许是我们给AI训练的语料就是这样的 ![]()
究其原因,写代码的时候我们没有确保AI服务用户和你。
然后这里有个短语“概念的完整性”需要解释一下。
也就是说:
为了反映一系列连贯的设计思路,我们宁可省略一些不规则的特性和改进,也不提倡独立和无法整合的系统,哪怕它们其实包含着许多很好的设计。
AI 已经学习了Github上可能几十亿行的代码,它也可能已经学会了各种语言风格,但如果没有指定方向,AI会随机进行预测。因为 AI 的输出本质上是基于上下文的 Token 概率推导。
具体原理可以查看这位佬的帖子:
随便可不是个好事情,如果我们不保证约束,我们就不能保证代码的整洁。你可以一行都不亲自动手写代码,但你必须强制 AI 遵循你的指导,你的定义。
这便是 Vibe Coding 中的贵族专制——核心是审。通过个人的直觉和 AI 的效率,从繁琐的语法中解脱,省下的时间用于系统的审计。
重新定义代码
谈到审,可能会有人会问:我都开始使用自然语言描述了,这种新型的“编程语言”已经快替代已有的编程语言了。代码迟早要消失,为什么我们还要去费劲心思审阅呢?不能让AI生成总结报告吗?
先来回看过去。
2008 年 《代码整洁之道》发布,作者Martin在书的开篇说:
我们正在临近代码的终结点。很快,代码就会⾃动产⽣出来,不需要再⼈⼯编写。程序员完全没⽤了,因为商务⼈⼠可以从规约直接⽣成程序。
现在,我们到达了他的未来,代码已经终结。正如开篇的迈出第一步,你只要有想法,AI 就能源源不断的为你提供代码。
但我们永远抛不掉代码,因为代码呈现了需求的细节。
十几年前,有一群人盼望着,有一天创造出一种机器:只要我们想一想,嘴巴都不用张就能叫它依计行事。那机器能透彻的理解我们,只有这样,它才能把含糊不清的需求翻译为可完美执⾏的程序,精确满⾜需求。
到了现在,即使有了 AI 这种情况永远不会发生。
我们可以创造帮助把需求解析和汇整为正式结构的各种⼯具。然⽽,我们永远⽆法抛弃必要的精确性——所以代码永存。
困难重重
为什么代码所代表的“精确性”难以被 AI 彻底取代?
早在1986年,有人便替我们回答了这一点。
软件开发的困难可以分为两类:一类是次要的困难;另一类是根本困难。次要困难指的是那些非必要的,由于所使用工具,或者语言本身带来的困难;而主要困难则是指的那些软件本身无法避免的困难——复杂性,依从性,可变性和不可见性。
软件是复杂的,随着规模扩大,会变得理解困难,Bug频发,管理失控;代码是依从的,代码会随着时间无条件的适应,所有人为的设定;能力是可变的,软件功能是纯粹的思维产物,它面临着持续变更的压力;最后软件是无形的,你即使借助了各种图形,我们也很难构建出真正的模型。
软件的主要困难是无法消除的。Vibe Coding 只是高效的解决了一些次要困难,它可以瞬间写好代码,能消除拼写等语法错误。但构建复杂的概念结构,完善的软件功能——这些靠的是人来完成的智力活动。
AI 生成的代码好比是砖块,解决了你盖房子的材料有没有的问题。它不知道砖块的作用,是用来建高楼大厦还是别墅。你需要审阅代码,去观察,去确认。只有这样,你才能明确 AI 给你看的,是不是真正你脑海中的真正样子。
目光所至
软件是天生不可见的,我们无法避免这一点。许多人 Vibe Coding 出来的软件也大多都是能跑,但不可维护的。
这种情况不外乎就是没有审阅其中的逻辑,或者仅仅看似审阅了逻辑,但是是AI总结出来的。这种行为,为你的软件构建了一个巨大的黑盒。
一旦出现了问题,或者有了很好的点子,这个黑盒就会成为你 Vibe Coding 路上的噩梦。
设计要可见,以便审查和调试。——《UNIX 编程艺术》
你能一眼看出来的——就是软件的透明度。作为预测机,AI 生成的代码往往倾向于掩盖细节,或者为了满足你的“一句话”需求而堆砌复杂逻辑。
你的需求应该是具体的,清晰的,明确的。即使开始不明确,你也可以和 AI 进行讨论——让它列出有关的一些方向。审阅文字,也是审计的一种。当一些想法清晰后再进行开始。
帮我做一个贪吃蛇游戏。但是先不开始做,先和我讨论可能的设计考虑方向 给出10个点
制作一个“贪吃蛇”看似简单,但要做到体验流畅、代码优雅,有很多值得探讨的维度。以下是我们开发前可以考虑的 10 个设计方向:
- 核心逻辑:坐标与移动
蛇的身体本质上是一个坐标队列。
- 移动机制:是每一帧都重新渲染所有格子,还是仅仅“增加一个新的头部,删除一个旧的尾部”?后者在性能上更优。
- 网格系统:游戏区域是基于像素移动(平滑但逻辑复杂),还是基于固定网格(经典且易于实现)?
- 碰撞检测逻辑
这是游戏胜负的核心判断:
- 边界碰撞:撞墙是直接游戏结束(Game Over),还是像某些版本那样可以从另一侧穿出(环形空间)?
- 自身碰撞:如何高效检测蛇头是否触碰到了身体的其他部分?
- 食物生成算法
- 随机性与合法性:食物必须随机生成,但绝对不能生成在蛇的身体上。如果蛇占据了 90% 的屏幕,你的算法如何快速找到剩下的空位?
- 速度与难度曲线
- 动态加速:随着蛇变长,移动速度是否应该加快?
- 阶梯难度:是线性加速,还是每吃 5 个食物提升一个“等级”?
- 输入处理(输入缓冲)
- 转向保护:这是新手最容易忽略的。如果蛇向右走,玩家快速按下“上”接着“左”,可能会导致蛇直接“自杀”撞向自己。我们需要一个输入缓冲区来确保每一步转向都是合法的。
- 渲染技术选择
- HTML5 Canvas:适合高性能、流畅的动画。
- DOM 元素:适合简单的逻辑学习,通过操作
<div>的位置来实现。 - 游戏引擎(如 Phaser.js):如果你想加入复杂的粒子效果或物理特性。
- 视觉风格与 UI
- 美术风格:极简像素风、复古 GameBoy 风,还是现代发光特效(Neon Style)?
- UI 元素:实时分数显示、最高分记录、暂停菜单、以及醒目的 Game Over 界面。
- 游戏状态管理
- 我们需要一个清晰的状态机来切换:
等待开始→进行中→暂停→游戏结束。
- 扩展功能(进阶考虑)
- 特殊食物:比如金色苹果(双倍积分)、缩小药水(减短长度)或减速道具。
- 障碍物:随机生成的墙壁,增加走位难度。
- 持久化存储
- 本地最高分:使用浏览器的
localStorage来保存玩家的历史最高分,增加游戏的重玩价值。
先不看这些输出是不是对的,但它可以给你一些清晰的可能方向,这时贪吃蛇可能就会在你脑海中逐渐显现了。
这部分需要学习 提问的艺术 后面有时间会写到单独的帖子里面
做为一个 Vibe Coder 我们要做的就是逐渐清晰框架,即使人不可能考虑到方方面面,我们也可以让 AI 仅仅实现我们想过的内容,而不进行自由发挥。如果进行了自由发挥,也要强硬的要求 AI 进行重构和缩减。
正如 Eric Raymond 所说:“如果一个程序的运行逻辑并不复杂——也就是说,人们不必绞尽脑汁就能推断出所有可能情况——那么它就是简洁的。”
草稿也是成品
正如我在序言中提到,编程可以看作是绘画,不是工程。在 Vibe Coding 中,代码既是最终的软件,也是你思考过程的草稿。
AI 给了我们以极低成本获取“初稿”的能力。这意味着我们有了更多的时间去修正 ,去打磨 ,去审视 。
我们不应该期待 AI 直接给你成品。我们应该把它生成的代码看作是一块画布上的底色。需要通过不断的 Prompt 交互(也就是“再设计”),去覆盖那些错误的逻辑,去擦除那些多余的修饰。
这里化用一下这句话。
清水出芙蓉,天然去雕饰
希望我们的思想:自然、清新。
这时——代码自然生发。
此刻
好的设计往往是“再设计”(Redesign)的结果。很少有人能一次就把事情做对,就像油画允许画家反复涂抹一样,AI 生成的代码给了我们一次次涂抹的机会。
先写出粗陋的初稿,然后斟酌推敲,直至达到我们心目中的样子。在 Vibe Coding 中,AI 帮我们完成了那个“能跑但丑陋”的初稿,而我们的任务,是运用我们的品味去剔除那些多余的“雕饰”,让代码回归逻辑的本质。
这一过程消除了 Bug,同时展现了对美的追求。
当我们删繁就简,让逻辑如清水芙蓉般自然显现时,快乐自然发生。
以 《只是为了好玩》 结束
那种创建事物的纯粹快乐,那种看着自己亲手组装的零部件精妙运行的魔力。这种快乐,如同上帝创造世界,也如同孩子在玩泥巴。 —— 《人月神话》
当我们剥离了繁琐的语法记忆,越过了枯燥的代码,Vibe Coding 让我们重新直面这种最原始的冲动。
从生存(Survival),到社会秩序(Social Order),最后到达娱乐(Entertainment)。
你需要做的仅仅只是做出选择,承担代价,然后享受就好。
这,只是为了好玩(Just for Fun)。
写的好累,第一章的第一个小节就结束了。可喜可贺。
我知道很多人都看不下去这种,但是我还是写了。
我想说的是,如果只是为了完成任务而写代码,最好的方式是花钱找人写,你的钱包厚度决定了软件的好坏。
没有什么东西是一蹴而就的,失败也在所难免。
也不用焦虑,毕竟几十年前的思想现在也还没有过时。不过是新瓶装旧酒而已。
写这些更多还是一种思想,技术的话会单独写的。
PS: 多来点反馈吧
能力有限,不能保证对错。有问题可以指出来。
风格啥的 都可以交流
- 可以
- 一般
- 不行



