当前位置: 首页 > news >正文

cursor+deepseek实现完整的俄罗斯方块小游戏

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>俄罗斯方块</title>
    <style>
        body {
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background: #333;
            color: white;
            font-family: Arial, sans-serif;
        }
        .game-container {
            display: flex;
            gap: 20px;
        }
        canvas {
            border: 2px solid #fff;
        }
        .info-panel {
            width: 150px;
        }
        .controls {
            margin-top: 20px;
        }
        .controls button {
            padding: 10px 20px;
            margin: 5px;
            font-size: 16px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="game-container">
        <canvas id="tetris" width="300" height="600"></canvas>
        <div class="info-panel">
            <h2>俄罗斯方块</h2>
            <p>分数: <span id="score">0</span></p>
            <p>等级: <span id="level">1</span></p>
            <p>下一个:</p>
            <canvas id="nextPiece" width="120" height="120"></canvas>
            <div class="controls">
                <button id="startBtn">开始游戏</button>
                <button id="pauseBtn" disabled>暂停</button>
                <button id="restartBtn" disabled>重新开始</button>
            </div>
        </div>
    </div>
    <script>
        const canvas = document.getElementById('tetris');
        const ctx = canvas.getContext('2d');
        const nextCanvas = document.getElementById('nextPiece');
        const nextCtx = nextCanvas.getContext('2d');
        const scoreElement = document.getElementById('score');
        const levelElement = document.getElementById('level');
        
        const ROW = 20;
        const COL = 10;
        const SQ = 30;
        const VACANT = 'black';
        const SPEED = 500;
        const LINES_PER_LEVEL = 10;

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

        const PIECES = [
            [Z, 'red'],
            [S, 'green'],
            [T, 'yellow'],
            [O, 'blue'],
            [L, 'purple'],
            [I, 'cyan'],
            [J, 'orange']
        ];

        let board = [];
        let score = 0;
        let level = 1;
        let lines = 0;
        let dropStart = Date.now();
        let piece;
        let nextPiece;
        let isPaused = false;
        let isRunning = false;
        let rAF;

        // 初始化游戏板
        function initBoard() {
            for(let r = 0; r < ROW; r++) {
                board[r] = [];
                for(let c = 0; c < COL; c++) {
                    board[r][c] = VACANT;
                }
            }
        }

        // 绘制方块
        function drawSquare(x, y, color) {
            ctx.fillStyle = color;
            ctx.fillRect(x*SQ, y*SQ, SQ, SQ);
            ctx.strokeStyle = '#333';
            ctx.strokeRect(x*SQ, y*SQ, SQ, SQ);
        }

        // 绘制游戏板
        function drawBoard() {
            for(let r = 0; r < ROW; r++) {
                for(let c = 0; c < COL; c++) {
                    drawSquare(c, r, board[r][c]);
                }
            }
        }

        // 方块类
        class Piece {
            constructor(tetromino, color) {
                this.tetromino = tetromino;
                this.color = color;
                this.tetrominoN = 0;
                this.activeTetromino = this.tetromino[this.tetrominoN];
                this.x = 3;
                this.y = -2;
            }

            draw() {
                for(let r = 0; r < this.activeTetromino.length; r++) {
                    for(let c = 0; c < this.activeTetromino.length; c++) {
                        if(this.activeTetromino[r][c]) {
                            drawSquare(this.x + c, this.y + r, this.color);
                        }
                    }
                }
            }

            unDraw() {
                for(let r = 0; r < this.activeTetromino.length; r++) {
                    for(let c = 0; c < this.activeTetromino.length; c++) {
                        if(this.activeTetromino[r][c]) {
                            drawSquare(this.x + c, this.y + r, VACANT);
                        }
                    }
                }
            }

            moveDown() {
                if(!this.collision(0, 1, this.activeTetromino)) {
                    this.unDraw();
                    this.y++;
                    this.draw();
                } else {
                    if(this.y < 0) {
                        gameOver();
                        return;
                    }
                    this.lock();
                    piece = nextPiece;
                    nextPiece = randomPiece();
                    drawNextPiece();
                }
            }

            moveLeft() {
                if(!this.collision(-1, 0, this.activeTetromino)) {
                    this.unDraw();
                    this.x--;
                    this.draw();
                }
            }

            moveRight() {
                if(!this.collision(1, 0, this.activeTetromino)) {
                    this.unDraw();
                    this.x++;
                    this.draw();
                }
            }

            rotate() {
                if(this.y < 0) {
                    return;
                }

                let nextPattern = this.tetromino[(this.tetrominoN + 1) % this.tetromino.length];
                let kick = 0;
                
                if(this.collision(0, 0, nextPattern)) {
                    if(this.x > COL/2) {
                        kick = -1;
                    } else {
                        kick = 1;
                    }
                    
                    if(!this.collision(kick, 0, nextPattern)) {
                        this.x += kick;
                    } else {
                        return;
                    }
                }
                
                this.unDraw();
                this.tetrominoN = (this.tetrominoN + 1) % this.tetromino.length;
                this.activeTetromino = this.tetromino[this.tetrominoN];
                this.draw();
            }

            collision(x, y, piece) {
                for(let r = 0; r < piece.length; r++) {
                    for(let c = 0; c < piece.length; c++) {
                        if(!piece[r][c]) continue;
                        
                        let newX = this.x + c + x;
                        let newY = this.y + r + y;
                        
                        if(newX < 0 || newX >= COL || newY >= ROW) {
                            return true;
                        }
                        
                        if(newY >= 0 && board[newY][newX] !== VACANT) {
                            return true;
                        }
                    }
                }
                return false;
            }

            lock() {
                for(let r = 0; r < this.activeTetromino.length; r++) {
                    for(let c = 0; c < this.activeTetromino.length; c++) {
                        if(!this.activeTetromino[r][c]) continue;
                        if(this.y + r < 0) {
                            gameOver();
                            return;
                        }
                        board[this.y + r][this.x + c] = this.color;
                    }
                }
                clearLines();
            }
        }

        // 随机生成方块
        function randomPiece() {
            let r = Math.floor(Math.random() * PIECES.length);
            return new Piece(PIECES[r][0], PIECES[r][1]);
        }

        // 消除满行
        function clearLines() {
            let linesCleared = 0;
            for(let r = ROW - 1; r >= 0; r--) {
                if(board[r].every(cell => cell !== VACANT)) {
                    board.splice(r, 1);
                    board.unshift(new Array(COL).fill(VACANT));
                    linesCleared++;
                    r++;
                }
            }
            if(linesCleared > 0) {
                updateScore(linesCleared);
            }
        }

        // 更新分数
        function updateScore(linesCleared) {
            const points = [0, 40, 100, 300, 1200][linesCleared] * level;
            score += points;
            lines += linesCleared;
            if(lines >= LINES_PER_LEVEL) {
                level++;
                lines -= LINES_PER_LEVEL;
            }
            scoreElement.textContent = score;
            levelElement.textContent = level;
        }

        // 绘制下一个方块
        function drawNextPiece() {
            nextCtx.clearRect(0, 0, nextCanvas.width, nextCanvas.height);
            for(let r = 0; r < nextPiece.tetromino[0].length; r++) {
                for(let c = 0; c < nextPiece.tetromino[0].length; c++) {
                    if(nextPiece.tetromino[0][r][c]) {
                        nextCtx.fillStyle = nextPiece.color;
                        nextCtx.fillRect(c*30, r*30, 30, 30);
                        nextCtx.strokeStyle = '#333';
                        nextCtx.strokeRect(c*30, r*30, 30, 30);
                    }
                }
            }
        }

        // 游戏结束
        function gameOver() {
            cancelAnimationFrame(rAF);
            isRunning = false;
            document.getElementById('startBtn').disabled = false;
            document.getElementById('pauseBtn').disabled = true;
            document.getElementById('restartBtn').disabled = false;
            ctx.fillStyle = 'rgba(0,0,0,0.75)';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = 'white';
            ctx.font = '40px Arial';
            ctx.fillText('游戏结束!', 30, canvas.height/2 - 20);
            ctx.font = '20px Arial';
            ctx.fillText('按R键重新开始', 50, canvas.height/2 + 20);
        }

        // 初始化游戏
        function init() {
            initBoard();
            score = 0;
            level = 1;
            lines = 0;
            scoreElement.textContent = score;
            levelElement.textContent = level;
            piece = randomPiece();
            nextPiece = randomPiece();
            drawNextPiece();
            drawBoard();
            piece.draw();
        }

        // 游戏主循环
        function gameLoop() {
            if(isPaused || !isRunning) return;
            
            let now = Date.now();
            let delta = now - dropStart;
            
            if(delta > SPEED / level) {
                piece.moveDown();
                dropStart = Date.now();
            }
            
            drawBoard();
            piece.draw();
            rAF = requestAnimationFrame(gameLoop);
        }

        // 添加控制按钮事件
        document.getElementById('startBtn').addEventListener('click', () => {
            if(!isRunning) {
                init();
                isRunning = true;
                isPaused = false;
                document.getElementById('startBtn').disabled = true;
                document.getElementById('pauseBtn').disabled = false;
                document.getElementById('restartBtn').disabled = false;
                dropStart = Date.now();
                gameLoop();
            }
        });

        document.getElementById('pauseBtn').addEventListener('click', () => {
            if(isRunning) {
                isPaused = !isPaused;
                document.getElementById('pauseBtn').textContent = isPaused ? '继续' : '暂停';
                if(!isPaused) {
                    dropStart = Date.now();
                    gameLoop();
                }
            }
        });

        document.getElementById('restartBtn').addEventListener('click', () => {
            cancelAnimationFrame(rAF);
            init();
            isRunning = true;
            isPaused = false;
            document.getElementById('pauseBtn').textContent = '暂停';
            dropStart = Date.now();
            gameLoop();
        });

        // 键盘控制
        document.addEventListener('keydown', (event) => {
            if(!isRunning || isPaused) return;
            
            if(event.keyCode === 37) { // 左
                piece.moveLeft();
                dropStart = Date.now();
            } else if(event.keyCode === 38) { // 上
                if(piece.y >= 0) {
                    piece.rotate();
                    dropStart = Date.now();
                }
            } else if(event.keyCode === 39) { // 右
                piece.moveRight();
                dropStart = Date.now();
            } else if(event.keyCode === 40) { // 下
                piece.moveDown();
            } else if(event.keyCode === 80) { // P键暂停
                document.getElementById('pauseBtn').click();
            }
        });
    </script>
</body>
</html>

相关文章:

  • ES 聚合查询
  • 数据安全的守护者:备份文件的重要性及自动化备份策略
  • 自学嵌入式第28天-----select,
  • BambuStudio学习笔记:MarchingSquares类
  • mysql中如何保证没有幻读发生
  • 道可云人工智能每日资讯|亚马逊云业务部门成立智能体人工智能团队
  • 解析调控网络之竞争结合
  • 只要四行代码就能解决mac上运行exe文件的问题
  • 05-2基于vs2022的c语言笔记——表达式
  • Mysql-经典故障案例(1)-主从同步由于主键问题引发的故障
  • 深度学习Save Best、Early Stop
  • Quadrotor-NMPC-Control 开源项目复现与问题记录
  • 03.06 QT
  • ComfyUI进阶教程核心要点与详解
  • 多模态模型在做选择题时,如何设置Prompt,如何精准定位我们需要的选项
  • 【Kubernetes 指南】基础入门——Kubernetes 基本概念(四)
  • Python在DevOps中的应用:自动化CI/CD管道的实现
  • 【电控笔记z29】扰动估测器DOB估测惯量J-摩擦系数B
  • 私有云基础架构与运维(一)
  • Mybatis中的设计模式
  • 互联网专线做网站怎么做数据/百度搜索网页版
  • java做网站用的是什么/软文范例大全
  • 做淘宝客网站一定要备案吗/软文范例100例
  • 怎样给网站做新闻稿子/账号权重查询入口站长工具
  • 涿州市网站建设/湖南网站建设加盟代理
  • 做网站的模仿还要去量宽高吗/必应搜索引擎入口