编程零基础,半小时用AI做了两个经典小游戏(附完整Prompt&HTML code)

2 阅读16分钟

作为一个文科生,从来没想过自己能写出能运行的游戏代码。

上学的时候最头疼的就是计算机课,看见满屏幕的英文字母和符号就头大,工作之后更是和编程八竿子打不着关系。但是最近AI大火,看着朋友圈里各种程序员靠着AI提高效率,我心里也痒痒——像我这样完全零基础的门外汉,真的能靠AI做出东西来吗?

抱着试一试的心态,我决定体验一把最近很火的 "vibe coding" —— 不用懂复杂的架构设计,不用记语法,只需要把你脑子里模糊的想法告诉AI,AI就能帮你生成可运行的代码。没想到,我第一天接触,只用了半小时,就做出了两个完整可玩的小游戏:俄罗斯方块和2048!而且UI风格我还能自定义,常用功能完全符合我的使用习惯。

今天就把我的体验过程和prompt分享出来,和我一样零基础的朋友也能跟着试一试,五分钟就能体验到创造的乐趣~


什么是vibe coding?文科生也能玩得转

先给和我一样零基础的朋友科普一下,最近爆火的 vibe coding 到底是什么?

简单说,vibe coding就是程序员把大概的感觉(vibe)告诉AI,AI就能理解你的想法,大批量短时间帮你生成代码。放在以前,你想做一个游戏,得先学几个月编程语言,懂数据结构,懂图形渲染,可能光环境配置就能卡住你一周。但现在不一样了,你只需要:

  1. 脑子里有一个模糊的想法:"我想要一个复古风格的俄罗斯方块"

  2. 把这个想法用大白话告诉AI

  3. 等待个一两分钟,就能得到一个打开就能玩的游戏

就这么简单!真的,我一个完全不懂代码的文科生,都能一遍就跑通,你说神奇不神奇?

我为什么会突然想尝试AI编程呢?其实就是想拓展一下自己的技能池。现在这个时代,AI就是最好的工具,就算你不做程序员工作,多会用一个工具,说不定哪天就能帮到你。而且,看着自己脑子里的想法从一句话,变成一个能实实在在玩的游戏,那种成就感真的太爽了!

===============================================================================

事前准备:为什么选了AiPy?

在尝试AiPy之前,我其实也把市面上常见的Agent AI都试用了个遍。有几点体验给大家分享一下:

  - ChatGPT本身:能力很强,但对普通人来说门槛还是有点高,很多时候生成的代码有各种依赖问题,环境配置就能烦死你,而且需要你自己去调试,不懂代码根本改不动。

  - 一些低代码平台:倒是不用写代码,但模板化太严重,想做一点点自定义修改都很麻烦,很多功能都受限。

  - 国外一些新兴的AI编码Agent:对英语要求太高了,而且网络不稳定,付费也麻烦,对国内用户太不友好。

试了一圈下来,我发现 AiPy 真的是对入门期小白最友好的一个平台了。它好在哪里呢?

  1. 完全中文环境:不用你蹩脚写英文提示词,大白话直接说需求,AI就能听懂,对国人太友好了

  2. 对技术知识要求极低:你不需要懂什么是依赖,什么是环境变量,AiPy都帮你处理好了,你只需要说你想要什么,剩下的交给AI就行

  3. 可以一步步迭代:做出来不满意,直接告诉AI你想要改哪里,比如"把背景颜色改成深蓝色","把方块变大一点",AI马上就改好了,完全不用你碰代码

  4. 本地运行更安全:代码都在你自己电脑上运行,不用担心数据泄露问题

作为纯小白,第一次打开AiPy的时候我都没紧张,界面很简洁,跟着引导走两步就知道怎么用了,这点必须给个好评。


第一个游戏:零基础搞定经典俄罗斯方块

话不多说,直接进入实战环节!我第一个做的就是大家都耳熟能详的俄罗斯方块。这算是经典中的经典了,规则简单,做出来就能玩,很适合练手。


我的原始prompt(直接抄作业!)


我一开始也不知道怎么写prompt,就试着用大白话把我的需求说出来,没想到AI直接就听懂了。我给AI的指令原文是这样的:

我想做一个网页版的俄罗斯方块游戏,要求:

  1. 使用HTML+JavaScript+CSS实现,打开HTML文件就能直接玩,不需要安装任何软件

  2. UI风格使用现代简约风,配色要舒服,深蓝色主题,方块用不同的鲜艳颜色区分

  3. 包含完整的游戏功能:旋转、移动、加速下落、消行得分、下一个方块预览

  4. 要有开始按钮、暂停按钮、分数显示、最高分记录

  5. 支持键盘方向键控制,也要支持手机触摸滑动控制

  6. 代码注释清晰,结构简单,我作为初学者能看懂大致结构

  7. 游戏要响应式,在不同大小的屏幕上都能正常显示

就是这么简单的一段描述,你猜怎么着?不到两分钟,AI就把完整的HTML文件生成出来了!我当时都惊讶了,这速度也太快了吧。


生成过程和微调


AI第一次生成完,我打开就能玩!真的,直接双击HTML文件,浏览器打开就进去了,一点问题都没有。功能都齐全,就是有一点点我不太满意:

  1. 方块稍微有点小,我近视眼看着有点费劲

  2. 预览区位置我觉得放在右边不太舒服,想放在下面

  3. 背景颜色我想要更深一点的蓝

我直接把这些要求告诉AiPy,原话是:

帮我修改一下:

  1. 把方块格子整体调大20%

  2. 把下一个方块预览区从右侧移动到底部居中

  3. 把背景深蓝色改得更深一点,对比度调高一点,保护眼睛

然后不到一分钟,AI就改好了!我重新打开一看,完美!就是我想要的样子。整个过程我一行代码都没写,也没改,全都是AI处理,我只用大白话提需求就行。


最终成品代码


   

   

    经典俄罗斯方块

   

        * {

            margin: 0;

            padding: 0;

            box-sizing: border-box;

            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

        }

        body {

            background-color: #0a192f;

            display: flex;

            flex-direction: column;

            align-items: center;

            padding: 20px;

            min-height: 100vh;

        }

        h1 {

            color: #64ffda;

            margin-bottom: 20px;

            text-shadow: 0 0 10px rgba(100, 255, 218, 0.5);

        }

        .game-container {

            display: flex;

            flex-direction: column;

            align-items: center;

            gap: 20px;

        }

        .game-info {

            display: flex;

            gap: 30px;

            color: white;

            font-size: 18px;

            margin-bottom: 10px;

        }

        .info-box {

            background-color: #112240;

            padding: 10px 20px;

            border-radius: 8px;

            border: 1px solid #64ffda;

        }

        .info-box span {

            color: #64ffda;

            font-weight: bold;

        }

        #game-board {

            border: 3px solid #64ffda;

            border-radius: 4px;

            background-color: #112240;

            display: grid;

            grid-template-columns: repeat(10, 30px);

            grid-template-rows: repeat(20, 30px);

            gap: 1px;

            padding: 2px;

        }

        .next-container {

            background-color: #112240;

            border: 2px solid #64ffda;

            border-radius: 8px;

            padding: 15px;

            margin-top: 15px;

        }

        .next-container h3 {

            color: #64ffda;

            text-align: center;

            margin-bottom: 10px;

        }

        #next-board {

            display: grid;

            grid-template-columns: repeat(4, 25px);

            grid-template-rows: repeat(2, 25px);

            gap: 1px;

            background-color: #0a192f;

            padding: 2px;

        }

        .controls {

            display: flex;

            gap: 15px;

            margin-top: 15px;

        }

        button {

            background-color: #64ffda;

            color: #0a192f;

            border: none;

            padding: 12px 30px;

            font-size: 16px;

            font-weight: bold;

            border-radius: 6px;

            cursor: pointer;

            transition: all 0.3s ease;

        }

        button:hover {

            background-color: #52d8b8;

            transform: translateY(-2px);

            box-shadow: 0 4px 12px rgba(100, 255, 218, 0.4);

        }

        .cell {

            width: 100%;

            height: 100%;

            background-color: #0a192f;

            border-radius: 2px;

        }

        .cell.I { background-color: #00f0f0; border: 2px solid #00cccc; }

        .cell.J { background-color: #0000f0; border: 2px solid #0000cc; }

        .cell.L { background-color: #f0a000; border: 2px solid #cc8800; }

        .cell.O { background-color: #f0f000; border: 2px solid #cccc00; }

        .cell.S { background-color: #00f000; border: 2px solid #00cc00; }

        .cell.T { background-color: #a000f0; border: 2px solid #8800cc; }

        .cell.Z { background-color: #f00000; border: 2px solid #cc0000; }

        .instructions {

            margin-top: 20px;

            color: #8892b0;

            text-align: center;

            max-width: 500px;

            line-height: 1.6;

        }

        .instructions h3 {

            color: #64ffda;

            margin-bottom: 10px;

        }

        @media (max-width: 600px) {

            #game-board {

                grid-template-columns: repeat(10, 25px);

                grid-template-rows: repeat(20, 25px);

            }

        }

   

   

🎮 经典俄罗斯方块

   

       

           

分数: 0

           

最高分: 0

           

行数: 0

       

       

       

           

下一个方块

           

       

       

            开始游戏

            暂停

       

       

           

操作说明

           

⬅️ ➡️ 方向键左右移动 | ⬆️ 方向键旋转 | ⬇️ 方向键加速下落

           

手机端: 滑动控制移动,点击旋转

       

   

   

        // 游戏配置

        const COLS = 10;

        const ROWS = 20;

        const BLOCK_SIZE = 30;

        // 方块形状定义

        const SHAPES = {

            I: [

                [1, 1, 1, 1]

            ],

            J: [

                [1, 0, 0],

                [1, 1, 1]

            ],

            L: [

                [0, 0, 1],

                [1, 1, 1]

            ],

            O: [

                [1, 1],

                [1, 1]

            ],

            S: [

                [0, 1, 1],

                [1, 1, 0]

            ],

            T: [

                [0, 1, 0],

                [1, 1, 1]

            ],

            Z: [

                [1, 1, 0],

                [0, 1, 1]

            ]

        };

        // 颜色对应

        const COLORS = {

            I: 'I',

            J: 'J',

            L: 'L',

            O: 'O',

            S: 'S',

            T: 'T',

            Z: 'Z'

        };

        // 游戏状态

        let board = [];

        let currentShape = null;

        let currentColor = null;

        let currentX = 0;

        let currentY = 0;

        let nextShape = null;

        let nextColor = null;

        let score = 0;

        let lines = 0;

        let highScore = localStorage.getItem('tetrisHighScore') || 0;

        let gameInterval = null;

        let isGameOver = false;

        let isPaused = false;

        // DOM元素

        const gameBoard = document.getElementById('game-board');

        const nextBoard = document.getElementById('next-board');

        const scoreElement = document.getElementById('score');

        const highScoreElement = document.getElementById('high-score');

        const linesElement = document.getElementById('lines');

        const startBtn = document.getElementById('start-btn');

        const pauseBtn = document.getElementById('pause-btn');

        // 初始化最高分显示

        highScoreElement.textContent = highScore;

        // 初始化游戏面板

        function initBoard() {

            gameBoard.innerHTML = '';

            board = Array(ROWS).fill().map(() => Array(COLS).fill(0));

            for (let y = 0; y < ROWS; y++) {

                for (let x = 0; x < COLS; x++) {

                    const cell = document.createElement('div');

                    cell.className = 'cell';

                    cell.id = cell-${y}-${x};

                    gameBoard.appendChild(cell);

                }

            }

        }

        // 初始化预览面板

        function initNextBoard() {

            nextBoard.innerHTML = '';

            for (let y = 0; y < 2; y++) {

                for (let x = 0; x < 4; x++) {

                    const cell = document.createElement('div');

                    cell.className = 'cell';

                    nextBoard.appendChild(cell);

                }

            }

        }

        // 随机生成新方块

        function randomShape() {

            const keys = Object.keys(SHAPES);

            const randomKey = keys[Math.floor(Math.random() * keys.length)];

            return {

                shape: SHAPES[randomKey],

                color: COLORS[randomKey]

            };

        }

        // 绘制当前方块

        function drawCurrentShape() {

            currentShape.forEach((row, y) => {

                row.forEach((value, x) => {

                    if (value) {

                        const boardY = currentY + y;

                        const boardX = currentX + x;

                        if (boardY >= 0) {

                            const cell = document.getElementById(cell-${boardY}-${boardX});

                            if (cell) cell.classList.add(currentColor);

                        }

                    }

                });

            });

        }

        // 清除当前方块

        function clearCurrentShape() {

            currentShape.forEach((row, y) => {

                row.forEach((value, x) => {

                    if (value) {

                        const boardY = currentY + y;

                        const boardX = currentX + x;

                        if (boardY >= 0) {

                            const cell = document.getElementById(cell-${boardY}-${boardX});

                            if (cell) cell.classList.remove(currentColor);

                        }

                    }

                });

            });

        }

        // 绘制预览方块

        function drawNextShape() {

            // 清除预览

            for (let i = 0; i < nextBoard.children.length; i++) {

                nextBoard.children[i].className = 'cell';

            }

            // 居中绘制

            const offsetX = Math.floor((4 - nextShape[0].length) / 2);

            const offsetY = Math.floor((2 - nextShape.length) / 2);

            nextShape.forEach((row, y) => {

                row.forEach((value, x) => {

                    if (value) {

                        const index = (y + offsetY) * 4 + (x + offsetX);

                        nextBoard.children[index].classList.add(nextColor);

                    }

                });

            });

        }

        // 检查碰撞

        function checkCollision(shape, offsetX, offsetY) {

            for (let y = 0; y < shape.length; y++) {

                for (let x = 0; x < shape[y].length; x++) {

                    if (shape[y][x]) {

                        const boardX = offsetX + x;

                        const boardY = offsetY + y;

                        if (boardX < 0 || boardX >= COLS || boardY >= ROWS) {

                            return true;

                        }

                        if (boardY >= 0 && board[boardY][boardX]) {

                            return true;

                        }

                    }

                }

            }

            return false;

        }

        // 旋转方块

        function rotate() {

            const rotated = currentShape[0].map((_, i) =>

                currentShape.map(row => row[i]).reverse()

            );

            if (!checkCollision(rotated, currentX, currentY)) {

                clearCurrentShape();

                currentShape = rotated;

                drawCurrentShape();

            }

        }

        // 移动方块

        function move(dx, dy) {

            if (!checkCollision(currentShape, currentX + dx, currentY + dy)) {

                clearCurrentShape();

                currentX += dx;

                currentY += dy;

                drawCurrentShape();

                return true;

            }

            if (dy > 0) {

                lockShape();

                return false;

            }

            return false;

        }

        // 锁定方块到面板

        function lockShape() {

            currentShape.forEach((row, y) => {

                row.forEach((value, x) => {

                    if (value) {

                        const boardY = currentY + y;

                        const boardX = currentX + x;

                        if (boardY >= 0) {

                            board[boardY][boardX] = currentColor;

                            const cell = document.getElementById(cell-${boardY}-${boardX});

                            cell.classList.add(currentColor);

                        }

                    }

                });

            });

            clearLines();

            spawnShape();

        }

        // 清除满行

        function clearLines() {

            let linesCleared = 0;

            for (let y = ROWS - 1; y >= 0; y--) {

                if (board[y].every(cell => cell !== 0)) {

                    // 移除该行

                    board.splice(y, 1);

                    // 在顶部添加新行

                    board.unshift(Array(COLS).fill(0));

                    linesCleared++;

                    y++; // 重新检查当前位置

                }

            }

            if (linesCleared > 0) {

                lines += linesCleared;

                score += linesCleared * linesCleared * 100;

                linesElement.textContent = lines;

                scoreElement.textContent = score;

                // 更新最高分

                if (score > highScore) {

                    highScore = score;

                    highScoreElement.textContent = highScore;

                    localStorage.setItem('tetrisHighScore', highScore);

                }

                // 重绘面板

                redrawBoard();

            }

        }

        // 重绘整个面板

        function redrawBoard() {

            for (let y = 0; y < ROWS; y++) {

                for (let x = 0; x < COLS; x++) {

                    const cell = document.getElementById(cell-${y}-${x});

                    cell.className = 'cell';

                    if (board[y][x]) {

                        cell.classList.add(board[y][x]);

                    }

                }

            }

        }

        // 生成新方块

        function spawnShape() {

            currentShape = nextShape || randomShape().shape;

            currentColor = nextColor || randomShape().color;

            const next = randomShape();

            nextShape = next.shape;

            nextColor = next.color;

            drawNextShape();

            currentX = Math.floor((COLS - currentShape[0].length) / 2);

            currentY = 0;

            if (checkCollision(currentShape, currentX, currentY)) {

                gameOver();

            }

        }

        // 游戏结束

        function gameOver() {

            isGameOver = true;

            clearInterval(gameInterval);

            gameInterval = null;

            alert(游戏结束!你的分数是: ${score});

        }

        // 下落一步

        function drop() {

            if (!isPaused && !isGameOver) {

                move(0, 1);

            }

        }

        // 硬降(直接落到底)

        function hardDrop() {

            while (move(0, 1)) {}

        }

        // 开始新游戏

        function startGame() {

            initBoard();

            score = 0;

            lines = 0;

            isGameOver = false;

            isPaused = false;

            scoreElement.textContent = score;

            linesElement.textContent = lines;

            nextShape = null;

            nextColor = null;

            spawnShape();

            if (gameInterval) clearInterval(gameInterval);

            gameInterval = setInterval(drop, 1000);

        }

        // 暂停游戏

        function pauseGame() {

            if (isGameOver) return;

            isPaused = !isPaused;

            pauseBtn.textContent = isPaused ? '继续' : '暂停';

        }

        // 键盘控制

        document.addEventListener('keydown', (e) => {

            if (isGameOver || !gameInterval) return;

            switch(e.key) {

                case 'ArrowLeft':

                    if (!isPaused) move(-1, 0);

                    break;

                case 'ArrowRight':

                    if (!isPaused) move(1, 0);

                    break;

                case 'ArrowDown':

                    if (!isPaused) move(0, 1);

                    break;

                case 'ArrowUp':

                    if (!isPaused) rotate();

                    break;

                case ' ':

                    e.preventDefault();

                    if (!isPaused) hardDrop();

                    break;

            }

        });

        // 触摸控制

        let touchStartX = 0;

        let touchStartY = 0;

        document.addEventListener('touchstart', (e) => {

            touchStartX = e.touches[0].clientX;

            touchStartY = e.touches[0].clientY;

        });

        document.addEventListener('touchend', (e) => {

            if (isGameOver || isPaused || !gameInterval) return;

            const touchEndX = e.changedTouches[0].clientX;

            const touchEndY = e.changedTouches[0].clientY;

            const diffX = touchEndX - touchStartX;

            const diffY = touchEndY - touchStartY;

 

            if (Math.abs(diffX) > Math.abs(diffY)) {

                // 水平滑动

                if (diffX > 30) {

                    move(1, 0);

                } else if (diffX < -30) {

                    move(-1, 0);

                }

            } else {

                // 垂直滑动

                if (diffY > 30) {

                    move(0, 1);

                } else if (diffY < -30) {

                    rotate();

                }

            }

        });

        // 绑定按钮事件

        startBtn.addEventListener('click', startGame);

        pauseBtn.addEventListener('click', pauseGame);

        // 初始化

        initBoard();

        initNextBoard();

    

你没看错,就是这么完整的一个文件,AI直接生成好了。你只要把上面这段代码复制保存成一个.html文件,双击就能玩。我作为一个文科生,现在想想都觉得不可思议——我竟然"做"出了一个俄罗斯方块!

===============================================================================

第二个游戏:趁热打铁,再来一个2048

第一个俄罗斯方块做的这么顺利,我信心一下子就上来了。反正都花了十几分钟了,干脆一鼓作气,再做一个经典的——2048!这个更简单,规则大家都懂,AI做起来应该更快。


我的prompt分享


有了第一次的经验,第二次写prompt我就更顺手了,直接告诉AI我想要什么:

继续帮我做一个网页版的2048游戏,要求:

  1. 同样使用HTML+JavaScript+CSS,单文件就能运行

  2. UI风格要和刚才的俄罗斯方块统一,也是深蓝色主题,现代简约风

  3. 包含完整功能:随机生成方块、滑动合并、分数计算、最高分记录、重来按钮

  4. 支持键盘方向键滑动,也支持手机触摸滑动

  5. 方块颜色要根据数字大小渐变,好看清晰

  6. 游戏获胜条件是得到2048,可以选择继续玩或者重新开始

  7. 响应式设计,手机上也要玩得舒服

看到了吗,就是这么简单,需求说清楚,AI就懂了。不到一分钟,AI就把代码生成出来了!还是老样子,直接双击打开就能运行,一点问题都没有。


微调过程


第一次生成的2048也很棒,就是有一点我觉得可以改进:方块间距有点小,我手指粗,手机上玩容易点错。我就告诉AI:

帮我把方块间距调大一点,整体格子也稍微放大一点,方便手机触摸操作;然后把数字字体也调大一些,看着更清楚。

分分钟就改好了,完美!真的,这种迭代体验太爽了,你不用懂代码,就告诉AI你想要改什么,分分钟给你搞定。


最终成品代码


   

   

    经典2048

   

        * {

            margin: 0;

            padding: 0;

            box-sizing: border-box;

            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

        }

        body {

            background-color: #0a192f;

            display: flex;

            flex-direction: column;

            align-items: center;

            padding: 20px;

            min-height: 100vh;

        }

        h1 {

            color: #64ffda;

            margin-bottom: 10px;

            text-shadow: 0 0 10px rgba(100, 255, 218, 0.5);

        }

        .game-description {

            color: #8892b0;

            margin-bottom: 20px;

            text-align: center;

        }

        .header {

            display: flex;

            justify-content: space-between;

            align-items: center;

            margin-bottom: 20px;

            width: 100%;

        }

        .score-container {

            display: flex;

            gap: 10px;

        }

        .score-box {

            background-color: #112240;

            padding: 10px 15px;

            border-radius: 8px;

            border: 1px solid #64ffda;

            text-align: center;

            min-width: 80px;

        }

        .score-box .label {

            color: #8892b0;

            font-size: 12px;

        }

        .score-box .value {

            color: #64ffda;

            font-size: 20px;

            font-weight: bold;

        }

        #game-board {

            background-color: #112240;

            border-radius: 10px;

            padding: 15px;

            display: grid;

            grid-template-columns: repeat(4, 1fr);

            gap: 15px;

            border: 2px solid #64ffda;

            width: 400px;

            height: 400px;

        }

        .tile {

            background-color: #0a192f;

            border-radius: 6px;

            display: flex;

            align-items: center;

            justify-content: center;

            font-size: 28px;

            font-weight: bold;

            transition: all 0.2s ease;

        }

        .tile-2 { background-color: #eee4da; color: #776e65; }

        .tile-4 { background-color: #ede0c8; color: #776e65; }

        .tile-8 { background-color: #f2b179; color: #f9f6f2; }

        .tile-16 { background-color: #f59563; color: #f9f6f2; }

        .tile-32 { background-color: #f67c5f; color: #f9f6f2; }

        .tile-64 { background-color: #f65e3b; color: #f9f6f2; }

        .tile-128 { background-color: #edcf72; color: #f9f6f2; }

        .tile-256 { background-color: #edcc61; color: #f9f6f2; }

        .tile-512 { background-color: #edc850; color: #f9f6f2; }

        .tile-1024 { background-color: #edc53f; color: #f9f6f2; font-size: 22px; }

        .tile-2048 { background-color: #edc22e; color: #f9f6f2; font-size: 22px; }

        .tile-4096 { background-color: #3c3a32; color: #f9f6f2; font-size: 22px; }

        .tile-8192 { background-color: #3c3a32; color: #f9f6f2; font-size: 22px; }

        .controls {

            display: flex;

            gap: 15px;

            margin-top: 20px;

        }

        button {

            background-color: #64ffda;

            color: #0a192f;

            border: none;

            padding: 12px 30px;

            font-size: 16px;

            font-weight: bold;

            border-radius: 6px;

            cursor: pointer;

            transition: all 0.3s ease;

        }

        button:hover {

            background-color: #52d8b8;

            transform: translateY(-2px);

            box-shadow: 0 4px 12px rgba(100, 255, 218, 0.4);

        }

        .instructions {

            margin-top: 20px;

            color: #8892b0;

            text-align: center;

            max-width: 400px;

            line-height: 1.6;

        }

        .instructions h3 {

            color: #64ffda;

            margin-bottom: 10px;

        }

        .game-overlay {

            position: fixed;

            top: 0;

            left: 0;

            right: 0;

            bottom: 0;

            background-color: rgba(10, 25, 47, 0.8);

            display: none;

            align-items: center;

            justify-content: center;

            z-index: 100;

        }

        .message-box {

            background-color: #112240;

            padding: 40px;

            border-radius: 10px;

            border: 2px solid #64ffda;

            text-align: center;

        }

        .message-box h2 {

            color: #64ffda;

            margin-bottom: 15px;

        }

        .message-box p {

            color: #8892b0;

            margin-bottom: 20px;

        }

        @media (max-width: 500px) {

            #game-board {

                width: 320px;

                height: 320px;

                gap: 10px;

                padding: 10px;

            }

            .tile {

                font-size: 22px;

            }

            .tile-1024, .tile-2048, .tile-4096, .tile-8192 {

                font-size: 18px;

            }

        }

   

   

🎮 经典2048

   

合并方块,得到2048!

 

   

       

           

               

分数

               

0

           

           

               

最高分

               

0

           

       

   

   

   

        重新开始

   

   

       

操作说明

       

⬅️ ➡️ ⬆️ ⬇️ 方向键滑动移动

       

手机端: 手指滑动控制方向

       

相同数字的方块会合并,目标是拼出2048!

   

   

       

           

恭喜你!

           

你已经得到了2048!

            继续游戏

            重新开始

       

   

   

        // 游戏配置

        const GRID_SIZE = 4;

        let grid = [];

        let score = 0;

        let bestScore = localStorage.getItem('2048BestScore') || 0;

        let gameOver = false;

        let gameWon = false;

        // DOM元素

        const gameBoard = document.getElementById('game-board');

        const scoreElement = document.getElementById('score');

        const bestScoreElement = document.getElementById('best-score');

        const gameOverlay = document.getElementById('game-overlay');

        const gameTitle = document.getElementById('game-title');

        const gameMessage = document.getElementById('game-message');

        const newGameBtn = document.getElementById('new-game-btn');

        const continueBtn = document.getElementById('continue-btn');

        const restartBtn = document.getElementById('restart-btn');

        // 初始化最高分

        bestScoreElement.textContent = bestScore;

        // 初始化游戏面板

        function initBoard() {

            gameBoard.innerHTML = '';

            grid = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(0));

            for (let y = 0; y < GRID_SIZE; y++) {

                for (let x = 0; x < GRID_SIZE; x++) {

                    const tile = document.createElement('div');

                    tile.className = 'tile';

                    tile.id = tile-${y}-${x};

                    gameBoard.appendChild(tile);

                }

            }

        }

        // 随机添加一个新方块

        function addRandomTile() {

            const emptyCells = [];

            for (let y = 0; y < GRID_SIZE; y++) {

                for (let x = 0; x < GRID_SIZE; x++) {

                    if (grid[y][x] === 0) {

                        emptyCells.push({x, y});

                    }

                }

            }

            if (emptyCells.length === 0) return false;

 

            const {x, y} = emptyCells[Math.floor(Math.random() * emptyCells.length)];

            grid[y][x] = Math.random() < 0.9 ? 2 : 4;

            updateBoard();

            return true;

        }

        // 更新面板显示

        function updateBoard() {

            for (let y = 0; y < GRID_SIZE; y++) {

                for (let x = 0; x < GRID_SIZE; x++) {

                    const tile = document.getElementById(tile-${y}-${x});

                    const value = grid[y][x];

                    tile.className = tile tile-${value};

                    tile.textContent = value === 0 ? '' : value;

                }

            }

            scoreElement.textContent = score;

            if (score > bestScore) {

                bestScore = score;

                bestScoreElement.textContent = bestScore;

                localStorage.setItem('2048BestScore', bestScore);

            }

        }

        // 移动一行

        function moveRow(row) {

            // 移除零

            let newRow = row.filter(num => num !== 0);

            let merged = false;

            for (let i = 0; i < newRow.length - 1; i++) {

                if (newRow[i] === newRow[i + 1] && !merged) {

                    newRow[i] *= 2;

                    score += newRow[i];

                    newRow.splice(i + 1, 1);

                    merged = true;

                    // 检查是否得到2048

                    if (newRow[i] === 2048 && !gameWon) {

                        gameWon = true;

                        showWinMessage();

                    }

                } else {

                    merged = false;

                }

            }

            // 补零

            while (newRow.length < GRID_SIZE) {

                newRow.push(0);

            }

            return newRow;

        }

        // 向左移动

        function moveLeft() {

            let moved = false;

            for (let y = 0; y < GRID_SIZE; y++) {

                const originalRow = [...grid[y]];

                grid[y] = moveRow(grid[y]);

                if (JSON.stringify(originalRow) !== JSON.stringify(grid[y])) {

                    moved = true;

                }

            }

            return moved;

        }

        // 向右移动

        function moveRight() {

            let moved = false;

            for (let y = 0; y < GRID_SIZE; y++) {

                const originalRow = [...grid[y]];

                grid[y] = moveRow([...grid[y]].reverse()).reverse();

                if (JSON.stringify(originalRow) !== JSON.stringify(grid[y])) {

                    moved = true;

                }

            }

            return moved;

        }

        // 向上移动

        function moveUp() {

            let moved = false;

            for (let x = 0; x < GRID_SIZE; x++) {

                let column = [];

                for (let y = 0; y < GRID_SIZE; y++) {

                    column.push(grid[y][x]);

                }

                const originalColumn = [...column];

                column = moveRow(column);

                if (JSON.stringify(originalColumn) !== JSON.stringify(column)) {

                    moved = true;

                }

                for (let y = 0; y < GRID_SIZE; y++) {

                    grid[y][x] = column[y];

                }

            }

            return moved;

        }

        // 向下移动

        function moveDown() {

            let moved = false;

            for (let x = 0; x < GRID_SIZE; x++) {

                let column = [];

                for (let y = 0; y < GRID_SIZE; y++) {

                    column.push(grid[y][x]);

                }

                const originalColumn = [...column];

                column = moveRow(column.reverse()).reverse();

                if (JSON.stringify(originalColumn) !== JSON.stringify(column)) {

                    moved = true;

                }

                for (let y = 0; y < GRID_SIZE; y++) {

                    grid[y][x] = column[y];

                }

            }

            return moved;

        }

        // 检查游戏是否结束

        function checkGameOver() {

            // 还有空格

            for (let y = 0; y < GRID_SIZE; y++) {

                for (let x = 0; x < GRID_SIZE; x++) {

                    if (grid[y][x] === 0) return false;

                }

            }

            // 还有可以合并的相邻格子

            for (let y = 0; y < GRID_SIZE; y++) {

                for (let x = 0; x < GRID_SIZE; x++) {

                    const current = grid[y][x];

                    if (x < GRID_SIZE - 1 && grid[y][x + 1] === current) return false;

                    if (y < GRID_SIZE - 1 && grid[y + 1][x] === current) return false;

                }

            }

            return true;

        }

        // 显示获胜消息

        function showWinMessage() {

            gameTitle.textContent = '🎉 恭喜你!';

            gameMessage.textContent = '成功拼出了2048!是否继续游戏?';

            gameOverlay.style.display = 'flex';

        }

        // 显示游戏结束消息

        function showGameOverMessage() {

            gameTitle.textContent = '游戏结束';

            gameMessage.textContent = 你的最终分数是: ${score};

            gameOverlay.style.display = 'flex';

            gameOver = true;

        }

        // 继续游戏

        function continueGame() {

            gameOverlay.style.display = 'none';

        }

        // 重新开始

        function newGame() {

            grid = [];

            score = 0;

            gameOver = false;

            gameWon = false;

            gameOverlay.style.display = 'none';

            initBoard();

            addRandomTile();

            addRandomTile();

            updateBoard();

        }

        // 处理移动

        function handleMove(direction) {

            if (gameOver) return;

 

            let moved = false;

            switch(direction) {

                case 'left':

                    moved = moveLeft();

                    break;

                case 'right':

                    moved = moveRight();

                    break;

                case 'up':

                    moved = moveUp();

                    break;

                case 'down':

                    moved = moveDown();

                    break;

            }

            if (moved) {

                addRandomTile();

                updateBoard();

                if (checkGameOver()) {

                    showGameOverMessage();

                }

            }

        }

        // 键盘控制

        document.addEventListener('keydown', (e) => {

            switch(e.key) {

                case 'ArrowLeft':

                    e.preventDefault();

                    handleMove('left');

                    break;

                case 'ArrowRight':

                    e.preventDefault();

                    handleMove('right');

                    break;

                case 'ArrowUp':

                    e.preventDefault();

                    handleMove('up');

                    break;

                case 'ArrowDown':

                    e.preventDefault();

                    handleMove('down');

                    break;

            }

        });

        // 触摸控制

        let touchStartX = 0;

        let touchStartY = 0;

        document.addEventListener('touchstart', (e) => {

            touchStartX = e.touches[0].clientX;

            touchStartY = e.touches[0].clientY;

        });

        document.addEventListener('touchend', (e) => {

            if (gameOver) return;

            const touchEndX = e.changedTouches[0].clientX;

            const touchEndY = e.changedTouches[0].clientY;

            const diffX = touchEndX - touchStartX;

            const diffY = touchEndY - touchStartY;

            if (Math.abs(diffX) > Math.abs(diffY)) {

                // 水平滑动

                if (Math.abs(diffX) > 20) {

                    handleMove(diffX > 0 ? 'right' : 'left');

                }

            } else {

                // 垂直滑动

                if (Math.abs(diffY) > 20) {

                    handleMove(diffY > 0 ? 'down' : 'up');

                }

            }

        });

        // 绑定事件

        newGameBtn.addEventListener('click', newGame);

        continueBtn.addEventListener('click', continueGame);

        restartBtn.addEventListener('click', newGame);

        // 开始游戏

        initBoard();

        newGame();

   

拿到这个文件我直接就玩了好几局,停不下来。配色和俄罗斯方块保持了统一,操作流畅,该有的功能一个不少,最高分还存在本地,刷新页面都不会丢,太赞了。


使用体验

讲完了两个游戏的制作过程,我给大家聊聊作为一个完全不懂编程的文科生,这半个小时体验下来,我的真实感受是什么。

首先,颠覆认知。我以前一直觉得编程是聪明人、理科生才能干的活,像我这种看到代码就头疼的人,这辈子都沾不上边。但这次体验下来,我发现AI真的把编程的门槛拉到了地板上。你不需要懂什么是变量,什么是循环,什么是函数,你只需要会说中文,能讲清楚你想要什么,就行了。AI都帮你搞定了。

其次,AiPy真的对小白太友好了。我也用过别的AI编程产品,有的生成出来代码一堆错,运行不起来,还得你自己装依赖,改bug,我哪会这个啊。AiPy就不一样了,它生成的代码我第一次打开就能运行,就算我有不满意的地方,直接用大白话告诉它改哪里,它分分钟就改好了,全程我一行代码都不用碰。这种体验对于零基础小白来说太重要了——你刚入门,信心比什么都重要,要是第一次就遇到一堆bug,估计你直接就放弃了。就算担心token不够用也没关系,就邀请码填c8W3,会有两百万的token。

第三,效率真的太高了。我做这两个完整可玩的游戏,加上微调,总共才花了半个小时。放在以前,你就算是专业程序员,从零开始做两个这样的游戏,没有大半天也搞不定吧?我一个零基础小白,半个小时就搞定了,这就是AI的力量啊。

第四,原来创造这么简单。这种把你脑子里想法变成实实在在东西的感觉,真的太爽了。我原来就是刷手机,看别人做这个做那个,现在我发现,哦,原来我也可以啊!只要我有想法,AI就能帮我实现。这种成就感真的很难形容,你得自己体验一次才知道。


给同样零基础想尝试的朋友一些建议

看了我的经历,你是不是也心动了?我给和我一样零基础的朋友几点建议:

  1. 别怕,大胆去试。你不用懂代码,真的,就像我,纯文科生都能做出来,你怕什么?想到什么就直接说,AI现在理解能力很强的。

  2. prompt写清楚你的需求。不用太复杂,就用大白话,把你想要的功能、风格、要求一条一条列出来,AI更容易理解,生成出来的东西也更符合你的预期。

  3. 不满意就改。不用第一次就要求完美,做出来之后,哪里不满意直接告诉AI,让它改,多改两次就是你想要的了。AI不会嫌你麻烦的。

  4. 从简单的小项目开始。就像我,先做两个经典小游戏,难度不大,容易成功,能快速建立信心。信心有了,你再去尝试更复杂的东西。

  5. 选对工具很重要。我试用了这么多,真心推荐零基础小白从AiPy开始,中文环境,对技术要求低,不容易踩坑,能让你快速体验到成功的乐趣。


总结:AI时代,每个人都可以是创造者

我原来一直觉得,"编程"、"创造"这些词都是属于技术人员的,和我这种文科生没关系。但这次半个小时做两个游戏的经历,真的改变了我的想法。

在AI时代,你不需要掌握每一项技能,你只需要有想法,知道怎么用AI工具帮你实现就行了。AI就是你的左膀右臂,它帮你处理那些技术细节,你只需要负责创意和想法。

vibe coding真的没有你想象的那么难,就像我,编程零基础,半个小时都能做出两个可玩的小游戏,你为什么不试一试呢?说不定你脑子里那个放了很久的想法,现在就能用AI实现出来了。

最后,把我用到的prompt都放在文章里了,你直接拿去用就行,改一改就能做出你自己风格的游戏。快去试一试吧,期待你也能体验到创造的乐趣!


PS:文章里的两个HTML文件都可以直接复制保存,双击就能玩,拿走不谢~如果你也做出来有意思的东西,欢迎在评论区分享呀!