Qwen3.6-27B-FP8 的俄罗斯方块edit icon

Fork(复制)
下载
嵌入
BUG反馈
index.html
md
README.md
现在支持上传本地图片了!
index.html
            
            <!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML5 俄罗斯方块</title>
    <style>
        body {
            background: #202028;
            color: #fff;
            font-family: sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            margin: 0;
            overflow: hidden;
        }

        h1 {
            margin-top: 0;
            font-size: 2em;
        }

        .game-container {
            position: relative;
            border: 2px solid #fff;
            box-shadow: 0 0 20px rgba(0,0,0,0.5);
        }

        canvas {
            display: block;
            background-color: #000;
        }

        .score-board {
            margin-top: 10px;
            font-size: 1.5em;
        }

        .controls-hint {
            margin-top: 15px;
            font-size: 0.9em;
            color: #aaa;
            text-align: center;
        }
        
        /* 游戏结束时的遮罩层 */
        #game-over {
            display: none;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.85);
            padding: 20px;
            text-align: center;
            border: 1px solid #fff;
            width: 200px;
        }
        
        button {
            background: #fff;
            color: #000;
            border: none;
            padding: 10px 20px;
            font-size: 1em;
            cursor: pointer;
            margin-top: 10px;
        }
        
        button:hover {
            background: #ccc;
        }
    </style>
</head>
<body>

    <h1>俄罗斯方块</h1>

    <div class="game-container">
        <canvas id="tetris" width="240" height="400"></canvas>
        
        <div id="game-over">
            <h2>游戏结束</h2>
            <p>得分: <span id="final-score">0</span></p>
            <button onclick="resetGame()">重新开始</button>
        </div>
    </div>

    <div class="score-board">
        得分: <span id="score">0</span>
    </div>

    <div class="controls-hint">
        ← → : 移动 | ↑ : 旋转 | ↓ : 加速下落
    </div>

    <script>
        const canvas = document.getElementById('tetris');
        const context = canvas.getContext('2d');
        const scoreElement = document.getElementById('score');
        const finalScoreElement = document.getElementById('final-score');
        const gameOverDiv = document.getElementById('game-over');

        // 放大倍数,让每个像素块更大 (20x12 的网格,每个块放大20倍)
        context.scale(20, 20);

        // 消除满行的逻辑
        function arenaSweep() {
            let rowCount = 1;
            outer: for (let y = arena.length - 1; y > 0; --y) {
                for (let x = 0; x < arena[y].length; ++x) {
                    if (arena[y][x] === 0) {
                        continue outer;
                    }
                }
                // 移除满行并填充新行
                const row = arena.splice(y, 1)[0].fill(0);
                arena.unshift(row);
                ++y;

                player.score += rowCount * 10;
                rowCount *= 2;
            }
        }

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

        // 创建矩阵(游戏区域或方块)
        function createMatrix(w, h) {
            const matrix = [];
            while (h--) {
                matrix.push(new Array(w).fill(0));
            }
            return matrix;
        }

        // 定义所有方块形状
        function createPiece(type) {
            if (type === 'I') {
                return [
                    [0, 1, 0, 0],
                    [0, 1, 0, 0],
                    [0, 1, 0, 0],
                    [0, 1, 0, 0],
                ];
            } else if (type === 'L') {
                return [
                    [0, 2, 0],
                    [0, 2, 0],
                    [0, 2, 2],
                ];
            } else if (type === 'J') {
                return [
                    [0, 3, 0],
                    [0, 3, 0],
                    [3, 3, 0],
                ];
            } else if (type === 'O') {
                return [
                    [4, 4],
                    [4, 4],
                ];
            } else if (type === 'Z') {
                return [
                    [5, 5, 0],
                    [0, 5, 5],
                    [0, 0, 0],
                ];
            } else if (type === 'S') {
                return [
                    [0, 6, 6],
                    [6, 6, 0],
                    [0, 0, 0],
                ];
            } else if (type === 'T') {
                return [
                    [0, 7, 0],
                    [7, 7, 7],
                    [0, 0, 0],
                ];
            }
        }

        // 绘制函数
        function draw() {
            // 清空画布
            context.fillStyle = '#000';
            context.fillRect(0, 0, canvas.width, canvas.height);

            drawMatrix(arena, {x: 0, y: 0});
            drawMatrix(player.matrix, player.pos);
        }

        // 绘制矩阵(方块或场地)
        function drawMatrix(matrix, offset) {
            matrix.forEach((row, y) => {
                row.forEach((value, x) => {
                    if (value !== 0) {
                        // 定义颜色
                        const colors = [
                            null,
                            '#FF0D72', // I - 红粉
                            '#0DC2FF', // L - 蓝
                            '#0DFF72', // J - 绿
                            '#F538FF', // O - 紫
                            '#FF8E0D', // Z - 橙
                            '#FFE138', // S - 黄
                            '#3877FF', // T - 深蓝
                        ];
                        context.fillStyle = colors[value];
                        context.fillRect(x + offset.x, y + offset.y, 1, 1);
                        
                        // 给方块加一点立体边框效果
                        context.lineWidth = 0.05;
                        context.strokeStyle = 'white';
                        context.strokeRect(x + offset.x, y + offset.y, 1, 1);
                    }
                });
            });
        }

        // 合并方块到场地中
        function merge(arena, player) {
            player.matrix.forEach((row, y) => {
                row.forEach((value, x) => {
                    if (value !== 0) {
                        arena[y + player.pos.y][x + player.pos.x] = value;
                    }
                });
            });
        }

        // 旋转矩阵
        function rotate(matrix, dir) {
            for (let y = 0; y < matrix.length; ++y) {
                for (let x = 0; x < y; ++x) {
                    [
                        matrix[x][y],
                        matrix[y][x],
                    ] = [
                        matrix[y][x],
                        matrix[x][y],
                    ];
                }
            }
            if (dir > 0) {
                matrix.forEach(row => row.reverse());
            } else {
                matrix.reverse();
            }
        }

        // 玩家下落逻辑
        function playerDrop() {
            player.pos.y++;
            if (collide(arena, player)) {
                player.pos.y--;
                merge(arena, player);
                playerReset();
                arenaSweep();
                updateScore();
            }
            dropCounter = 0;
        }

        // 玩家移动逻辑
        function playerMove(offset) {
            player.pos.x += offset;
            if (collide(arena, player)) {
                player.pos.x -= offset;
            }
        }

        // 玩家重置(生成新方块或游戏结束)
        function playerReset() {
            const pieces = 'ILJOTSZ';
            player.matrix = createPiece(pieces[pieces.length * Math.random() | 0]);
            player.pos.y = 0;
            player.pos.x = (arena[0].length / 2 | 0) -
                           (player.matrix[0].length / 2 | 0);
            
            // 如果生成新方块时就碰撞,则游戏结束
            if (collide(arena, player)) {
                gameOver();
            }
        }

        // 玩家旋转逻辑
        function playerRotate(dir) {
            const pos = player.pos.x;
            let offset = 1;
            rotate(player.matrix, dir);
            // 墙踢(Wall kick)简单实现:防止旋转出墙外
            while (collide(arena, player)) {
                player.pos.x += offset;
                offset = -(offset + (offset > 0 ? 1 : -1));
                if (offset > player.matrix[0].length) {
                    rotate(player.matrix, -dir);
                    player.pos.x = pos;
                    return;
                }
            }
        }

        // 游戏结束处理
        function gameOver() {
            isGameOver = true;
            finalScoreElement.innerText = player.score;
            gameOverDiv.style.display = 'block';
        }

        // 重置游戏
        function resetGame() {
            arena.forEach(row => row.fill(0));
            player.score = 0;
            updateScore();
            gameOverDiv.style.display = 'none';
            isGameOver = false;
            playerReset();
            update();
        }

        // 更新分数显示
        function updateScore() {
            scoreElement.innerText = player.score;
        }

        // 游戏主循环变量
        let dropCounter = 0;
        let dropInterval = 1000; // 下落间隔(毫秒)
        let lastTime = 0;
        let isGameOver = false;

        // 游戏主循环
        function update(time = 0) {
            if (isGameOver) return;

            const deltaTime = time - lastTime;
            lastTime = time;

            dropCounter += deltaTime;
            if (dropCounter > dropInterval) {
                playerDrop();
            }

            draw();
            requestAnimationFrame(update);
        }

        // 游戏区域 (12宽 x 20高)
        const arena = createMatrix(12, 20);

        // 玩家状态
        const player = {
            pos: {x: 0, y: 0},
            matrix: null,
            score: 0,
        };

        // 键盘监听
        document.addEventListener('keydown', event => {
            if (isGameOver) return;

            if (event.keyCode === 37) { // Left
                playerMove(-1);
            } else if (event.keyCode === 39) { // Right
                playerMove(1);
            } else if (event.keyCode === 40) { // Down
                playerDrop();
            } else if (event.keyCode === 38) { // Up (Rotate)
                playerRotate(1);
            }
        });

        // 启动游戏
        playerReset();
        updateScore();
        update();

    </script>
</body>
</html>
        
编辑器加载中
预览
控制台