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

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

上学的时候最头疼的就是计算机课,看见满屏幕的英文字母和符号就头大,工作之后更是和编程八竿子打不着关系。但是最近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就是最好的工具,就算你不做程序员工作,多会用一个工具,说不定哪天就能帮到你。而且,看着自己脑子里的想法从一句话,变成一个能实实在在玩的游戏。

事前准备:哪个AI?

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

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

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

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

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

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

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

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

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

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

第一个游戏:俄罗斯方块

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

prompt

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

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

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

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

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

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

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

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

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

生成过程和微调

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

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

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

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

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

帮我修改一下:

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

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

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

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


最终成品代码

<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>经典俄罗斯方块</title>

<style>

* {

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);

}

}

</style>

</head>

<body>

<h1>🎮 经典俄罗斯方块</h1>

<div class="game-container">

<div class="game-info">

<div class="info-box">分数: <span id="score">0</span></div>

<div class="info-box">最高分: <span id="high-score">0</span></div>

<div class="info-box">行数: <span id="lines">0</span></div>

</div>

<div id="game-board"></div>

<div class="next-container">

<h3>下一个方块</h3>

<div id="next-board"></div>

</div>

<div class="controls">

<button id="start-btn">开始游戏</button>

<button id="pause-btn">暂停</button>

</div>

<div class="instructions">

<h3>操作说明</h3>

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

<p>手机端: 滑动控制移动,点击旋转</p>

</div>

</div>

<script>

// 游戏配置

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();

</script>

</body>

</html>

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


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

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

我的prompt分享

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

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

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

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

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

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

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

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

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

看到了吗,就是这么简单,需求说清楚,AI就懂了。


微调过程

告诉AI:

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

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


最终成品代码

<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>经典2048</title>

<style>

* {

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;

}

}

</style>

</head>

<body>

<h1>🎮 经典2048</h1>

<p class="game-description">合并方块,得到2048!</p>

<div class="header">

<div class="score-container">

<div class="score-box">

<div class="label">分数</div>

<div class="value" id="score">0</div>

</div>

<div class="score-box">

<div class="label">最高分</div>

<div class="value" id="best-score">0</div>

</div>

</div>

</div>

<div id="game-board"></div>

<div class="controls">

<button id="new-game-btn">重新开始</button>

</div>

<div class="instructions">

<h3>操作说明</h3>

<p>⬅️ ➡️ ⬆️ ⬇️ 方向键滑动移动</p>

<p>手机端: 手指滑动控制方向</p>

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

</div>

<div class="game-overlay" id="game-overlay">

<div class="message-box">

<h2 id="game-title">恭喜你!</h2>

<p id="game-message">你已经得到了2048!</p>

<button id="continue-btn">继续游戏</button>

<button id="restart-btn">重新开始</button>

</div>

</div>

<script>

// 游戏配置

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();

</script>

</body>

</html>

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


作为零基础小白,我的真实使用体验

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

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

其次,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文件都可以直接复制保存,双击就能玩,拿走不谢~如果你也做出来有意思的东西,欢迎在评论区分享呀!

相关推荐
MediaTea1 小时前
DL:卷积神经网络的基本原理与 PyTorch 实现
人工智能·pytorch·深度学习·神经网络·cnn
csdn小瓯1 小时前
前端工程化:React + TypeScript + Tailwind CSS 的组件化实践
开发语言·人工智能·python
蓦然回首却已人去楼空1 小时前
深度学习进阶:自然语言处理|3.4 QA|用 SimpleCBOW 讲清楚 backward 为什么有的 return,有的不 return
人工智能·深度学习·自然语言处理
Zldaisy3d1 小时前
为增材制造“驱动器”中国,注入规模化应用更强动力 | TCT亚洲展专访西门子全球增材制造副总裁
大数据·人工智能·制造
AllData公司负责人1 小时前
亲测丝滑,体验跃迁|AllData通过集成开源项目StreamPark,实时流任务调度更省心!
java·大数据·数据库·人工智能·算法·实时计算·实时开发平台
AskHarries1 小时前
Reddit 找需求完整教程:3小时找到20个真实痛点
人工智能
小柒儿3362 小时前
充电桩行业的秩序重构,CCC证书正在划定新的起跑线
人工智能
思诺学长2 小时前
智能物流机器人的技术演进:AGV / AMR 与具身智能融合路径
人工智能
ZHW_AI课题组2 小时前
基于LSTM的天气预测
人工智能·rnn·lstm