用trae完全自动化开发一款网页版的俄罗斯方块游戏

阅读原文

建议阅读原文,始终查看最新文档版本,获得最佳阅读体验: 《用trae完全自动化开发一款网页版的俄罗斯方块游戏》

deepseek-R1-0528已经上传到Huggingface

参考资料: deepseek-ai/DeepSeek-R1-0528 · Hugging Face

2025年5月28日deepseek对deepseek R1模型进行了小幅度更新,据说编程性能大幅提升,甚至能媲美claude 4,我马上就想要测试一下。想着利用deepseek-R1-0528开发一个俄罗斯方块游戏。

可以看到,模型参数是6850亿,但当前还没有详细的模型描述

用trae完全自动化开发一款网页版的俄罗斯方块游戏_俄罗斯方块

通过api询问当前聊天模型是否是最新的deepseek R1-0528版本的

curl --request POST \
  -H "Content-Type: application/json" \
  --header 'Authorization: Bearer <此处替换为你的deepseek API KEY>' \
  --url https://api.deepseek.com/chat/completions \
  --data '{"messages":[{"role":"user","content":"请问你是deepseek最新发布的DeepSeek R1-0528大模型吗?2025年5月28日发布的"}],"model":"deepseek-reasoner"}' | jq .
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

输出表明,通过api调用,仍然还是旧版本的deepseek R1(2025年5月29日14点测试的)

用trae完全自动化开发一款网页版的俄罗斯方块游戏_AI编程_02

如果直接在网页端询问,给出的回答是最新版本的R1

用trae完全自动化开发一款网页版的俄罗斯方块游戏_俄罗斯方块_03

让trae自动开发游戏

使用自定义大模型

我使用的是自定义的大模型,因为我本来以为通过api调用是可以用上最新版本的deepseek R1的。

用trae完全自动化开发一款网页版的俄罗斯方块游戏_AI编程_04

提示词

提示词非常简单,就一句话“开发一款网页版的俄罗斯方块游戏”

用trae完全自动化开发一款网页版的俄罗斯方块游戏_俄罗斯方块_05

用trae完全自动化开发一款网页版的俄罗斯方块游戏_俄罗斯方块_06

一开始生成的代码只能利用方向键移动方块,我希望除了这种方式,还能利用WASD键操作方块,更加符合人类的习惯。

用trae完全自动化开发一款网页版的俄罗斯方块游戏_trae_07

生成的代码

代码也不多,只有三个文件

用trae完全自动化开发一款网页版的俄罗斯方块游戏_俄罗斯方块_08

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>网页版俄罗斯方块</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="game-container">
        <h1>俄罗斯方块</h1>
        <div class="game-info">
            <div>分数: <span id="score">0</span></div>
            <div>等级: <span id="level">1</span></div>
            <div>下一块:</div>
            <canvas id="next-piece" width="100" height="100"></canvas>
        </div>
        <canvas id="game-board" width="300" height="600"></canvas>
        <div class="controls">
            <button id="start-btn">开始游戏</button>
            <button id="pause-btn">暂停</button>
        </div>
    </div>
    <script src="game.js"></script>
</body>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
    font-family: 'Microsoft YaHei', sans-serif;
}

.game-container {
    display: flex;
    flex-direction: column;
    align-items: center;
}

h1 {
    color: #333;
    margin-bottom: 20px;
}

#game-board {
    border: 2px solid #333;
    background-color: #111;
}

.game-info {
    margin-bottom: 15px;
    text-align: center;
    font-size: 18px;
}

.controls {
    margin-top: 15px;
}

button {
    padding: 10px 20px;
    margin: 0 5px;
    font-size: 16px;
    cursor: pointer;
    background-color: #4CAF50;
    color: white;
    border: none;
    border-radius: 4px;
}

button:hover {
    background-color: #45a049;
}

#next-piece {
    display: block;
    margin: 10px auto;
    background-color: #222;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
// 游戏常量
const COLS = 10;
const ROWS = 20;
const BLOCK_SIZE = 30;
const COLORS = [
    null,
    '#FF0D72', // I
    '#0DC2FF', // J
    '#0DFF72', // L
    '#F538FF', // O
    '#FF8E0D', // S
    '#FFE138', // T
    '#3877FF'  // Z
];

// 方块形状定义
const SHAPES = [
    [],
    [[0,0,0,0], [1,1,1,1], [0,0,0,0], [0,0,0,0]], // I
    [[0,0,0], [1,0,0], [1,1,1], [0,0,0]],         // J
    [[0,0,0], [0,0,1], [1,1,1], [0,0,0]],         // L
    [[0,0,0,0], [0,1,1,0], [0,1,1,0], [0,0,0,0]], // O
    [[0,0,0], [0,1,1], [1,1,0], [0,0,0]],         // S
    [[0,0,0], [0,1,0], [1,1,1], [0,0,0]],         // T
    [[0,0,0], [1,1,0], [0,1,1], [0,0,0]]          // Z
];

// 游戏状态
let board = createBoard();
let score = 0;
let level = 1;
let gameOver = false;
let dropInterval = 1000; // 初始下落速度(毫秒)
let dropStart = Date.now();
let requestId = null;

// DOM元素
const canvas = document.getElementById('game-board');
const nextCanvas = document.getElementById('next-piece');
const ctx = canvas.getContext('2d');
const nextCtx = nextCanvas.getContext('2d');
const scoreElement = document.getElementById('score');
const levelElement = document.getElementById('level');
const startBtn = document.getElementById('start-btn');
const pauseBtn = document.getElementById('pause-btn');

// 初始化游戏板
function createBoard() {
    return Array.from(Array(ROWS), () => Array(COLS).fill(0));
}

// 当前方块
let piece = {
    pos: {x: 0, y: 0},
    matrix: null,
    type: null
};

// 下一个方块
let nextPiece = {
    matrix: null,
    type: null
};

// 绘制单个方块
function drawBlock(ctx, x, y, type) {
    ctx.fillStyle = COLORS[type];
    ctx.fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
    
    ctx.strokeStyle = '#000';
    ctx.lineWidth = 1;
    ctx.strokeRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
}

// 绘制游戏板
function drawBoard() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    
    // 绘制已落下的方块
    board.forEach((row, y) => {
        row.forEach((value, x) => {
            if (value !== 0) {
                drawBlock(ctx, x, y, value);
            }
        });
    });
    
    // 绘制当前方块
    if (piece.matrix) {
        piece.matrix.forEach((row, y) => {
            row.forEach((value, x) => {
                if (value !== 0) {
                    drawBlock(ctx, x + piece.pos.x, y + piece.pos.y, piece.type);
                }
            });
        });
    }
}

// 绘制下一个方块预览
function drawNextPiece() {
    nextCtx.clearRect(0, 0, nextCanvas.width, nextCanvas.height);
    
    if (nextPiece.matrix) {
        nextPiece.matrix.forEach((row, y) => {
            row.forEach((value, x) => {
                if (value !== 0) {
                    nextCtx.fillStyle = COLORS[nextPiece.type];
                    nextCtx.fillRect(x * 20, y * 20, 20, 20);
                    
                    nextCtx.strokeStyle = '#000';
                    nextCtx.lineWidth = 1;
                    nextCtx.strokeRect(x * 20, y * 20, 20, 20);
                }
            });
        });
    }
}

// 碰撞检测
function collide(board, piece) {
    const [m, o] = [piece.matrix, piece.pos];
    for (let y = 0; y < m.length; y++) {
        for (let x = 0; x < m[y].length; x++) {
            if (m[y][x] !== 0 &&
                (board[y + o.y] &&
                board[y + o.y][x + o.x]) !== 0) {
                return true;
            }
        }
    }
    return false;
}

// 旋转方块 - 修复非方阵旋转问题
function rotate(matrix) {
    const rows = matrix.length;
    const cols = matrix[0].length;
    const rotated = Array(cols).fill().map(() => Array(rows).fill(0));
    
    for (let y = 0; y < rows; y++) {
        for (let x = 0; x < cols; x++) {
            rotated[x][rows - 1 - y] = matrix[y][x];
        }
    }
    return rotated;
}

// 合并方块到游戏板
function merge(board, piece) {
    piece.matrix.forEach((row, y) => {
        row.forEach((value, x) => {
            if (value !== 0) {
                board[y + piece.pos.y][x + piece.pos.x] = piece.type;
            }
        });
    });
}

// 消除满行
function sweep() {
    let linesCleared = 0;
    
    outer: for (let y = ROWS - 1; y > 0; y--) {
        for (let x = 0; x < COLS; x++) {
            if (board[y][x] === 0) {
                continue outer;
            }
        }
        
        const row = board.splice(y, 1)[0].fill(0);
        board.unshift(row);
        linesCleared++;
        y++; // 重新检查当前行
    }
    
    if (linesCleared > 0) {
        // 更新分数
        score += [40, 100, 300, 1200][linesCleared - 1] * level;
        scoreElement.textContent = score;
        
        // 更新等级
        level = Math.floor(score / 1000) + 1;
        levelElement.textContent = level;
        
        // 加快下落速度
        dropInterval = Math.max(100, 1000 - (level - 1) * 100);
    }
}

// 创建新方块
function createPiece() {
    const type = Math.floor(Math.random() * 7) + 1;
    return {
        matrix: SHAPES[type],
        type: type
    };
}

// 重置当前方块
function resetPiece() {
    piece.matrix = nextPiece.matrix;
    piece.type = nextPiece.type;
    piece.pos.y = 0;
    piece.pos.x = Math.floor(COLS / 2) - Math.floor(piece.matrix[0].length / 2);
    
    nextPiece = createPiece();
    drawNextPiece();
    
    // 检查游戏结束
    if (collide(board, piece)) {
        gameOver = true;
        cancelAnimationFrame(requestId);
        alert(`游戏结束!最终得分: ${score}`);
    }
}

// 方块下落
function drop() {
    piece.pos.y++;
    if (collide(board, piece)) {
        piece.pos.y--;
        merge(board, piece);
        resetPiece();
        sweep();
    }
    dropStart = Date.now();
}

// 游戏主循环
function gameLoop() {
    if (gameOver) return;
    
    const now = Date.now();
    const delta = now - dropStart;
    
    if (delta > dropInterval) {
        drop();
    }
    
    drawBoard();
    requestId = requestAnimationFrame(gameLoop);
}

// 初始化游戏
function init() {
    board = createBoard();
    score = 0;
    level = 1;
    gameOver = false;
    dropInterval = 1000;
    
    scoreElement.textContent = score;
    levelElement.textContent = level;
    
    nextPiece = createPiece();
    resetPiece();
    drawBoard();
    drawNextPiece();
}

// 控制事件监听
document.addEventListener('keydown', event => {
    if (gameOver || !requestId) {  // 添加暂停状态检查
        return;
    }
    
    switch (event.keyCode) {
        case 37: // 左箭头
        case 65: // A键 (新增)
            piece.pos.x--;
            if (collide(board, piece)) piece.pos.x++;
            break;
        case 39: // 右箭头
        case 68: // D键 (新增)
            piece.pos.x++;
            if (collide(board, piece)) piece.pos.x--;
            break;
        case 40: // 下箭头
        case 83: // S键 (新增)
            drop();
            break;
        case 38: // 上箭头 (旋转)
        case 87: // W键 (新增)
            const rotated = rotate(piece.matrix);
            const original = piece.matrix;
            piece.matrix = rotated;
            if (collide(board, piece)) piece.matrix = original;
            break;
        case 32: // 空格键 (硬降落)
            event.preventDefault();  // 阻止空格键触发按钮点击
            while (!collide(board, piece)) {
                piece.pos.y++;
            }
            piece.pos.y--;
            merge(board, piece);
            resetPiece();
            sweep();
            break;
    }
});

// 按钮事件
startBtn.addEventListener('click', () => {
    if (gameOver) init();
    if (requestId) cancelAnimationFrame(requestId);
    gameOver = false;
    gameLoop();
});

pauseBtn.addEventListener('click', () => {
    if (gameOver) return;
    
    if (requestId) {
        cancelAnimationFrame(requestId);
        requestId = null;
        pauseBtn.textContent = '继续';
    } else {
        gameLoop();
        pauseBtn.textContent = '暂停';
    }
});

// 初始化游戏
init();
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.
  • 272.
  • 273.
  • 274.
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
  • 280.
  • 281.
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
  • 287.
  • 288.
  • 289.
  • 290.
  • 291.
  • 292.
  • 293.
  • 294.
  • 295.
  • 296.
  • 297.
  • 298.
  • 299.
  • 300.
  • 301.
  • 302.
  • 303.
  • 304.
  • 305.
  • 306.
  • 307.
  • 308.
  • 309.
  • 310.
  • 311.
  • 312.
  • 313.
  • 314.
  • 315.
  • 316.
  • 317.
  • 318.
  • 319.
  • 320.
  • 321.
  • 322.
  • 323.
  • 324.
  • 325.

验证游戏

直接用浏览器打开index.html文件即可开始游戏

其实验证过程中,我发现了一个问题,就是如果单击了“继续”按钮后,再按空格,虽然方块确实会直接落地,但是游戏也暂停了。下面这个视频演示了这个问题

 请至钉钉文档查看附件《网页版俄罗斯方块 和另外 12 个页面 - 个人 - Microsoft Edge 2025-05-29 14-55-56.mp4》

后来我让trae再调整代码,问题解决了。

 请至钉钉文档查看附件《网页版俄罗斯方块 和另外 12 个页面 - 个人 - Microsoft Edge 2025-05-29 15-19-41.mp4》

关注微信公众号“AI发烧友”,获取更多IT开发运维实用工具与技巧,还有很多AI技术文档!

用trae完全自动化开发一款网页版的俄罗斯方块游戏_俄罗斯方块_09