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

用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亿,但当前还没有详细的模型描述

image.png

通过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 .

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

image.png

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

image.png

让trae自动开发游戏

使用自定义大模型

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

image.png

提示词

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

image.pngimage.png

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

image.png

生成的代码

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

image.png

<!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>
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;
}
// 游戏常量
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();

验证游戏

直接用浏览器打开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技术文档!

梦幻智能logo-01(无水印).png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值