班释元作业

所属课程: 人工智能大变革(16星期,32课时)

*释元

11岁半

发布于:06-18
浏览数:16

 

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>俄罗斯方块</title>
    <style>
        body {
            background: #202028;
            color: #fff;
            font-family: sans-serif;
            display: flex;
            justify-content: center;
        }
        #game {
            position: relative;
        }
        #board {
            border: 2px solid #fff;
        }
        #score {
            position: absolute;
            top: -40px;
            left: 0;
        }
        #next-block {
            position: absolute;
            top: 0;
            right: -150px;
            border: 2px solid #fff;
        }
        .control-panel {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            text-align: center;
        }
        button {
            padding: 10px 20px;
            font-size: 18px;
            background: #4CAF50;
            border: none;
            color: white;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div id="game">
        <canvas id="board" width="300" height="600"></canvas>
        <canvas id="next-block" width="120" height="120"></canvas>
        <div id="score">得分: 0</div>
        <div class="control-panel" id="controls">
            <button onclick="startGame()">开始</button>
        </div>
    </div>

<script>
const BLOCKS = [
    [[1,1,1,1]], // I
    [[1,1,1],[0,1,0]], // T
    [[1,1,1],[1,0,0]], // L
    [[1,1,1],[0,0,1]], // J
    [[1,1],[1,1]], // O
    [[1,1,0],[0,1,1]], // S
    [[0,1,1],[1,1,0]]  // Z
];
const COLORS = ['#FF0D72', '#0DC2FF', '#0DFF72', '#F538FF', '#FF8E0D', '#FFE138', '#3877FF'];
const COLS = 10, ROWS = 20, BLOCK_SIZE = 30;
let ctx, nextCtx, board = [], score = 0;
let currentBlock, nextBlock, gameLoop, dropSpeed = 1000;

function initBoard() {
    ctx = document.getElementById('board').getContext('2d');
    nextCtx = document.getElementById('next-block').getContext('2d');
    
    // 绘制网格
    ctx.strokeStyle = '#303030';
    for(let y = 0; y < ROWS; y++) {
        for(let x = 0; x < COLS; x++) {
            ctx.strokeRect(x*BLOCK_SIZE, y*BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
        }
    }
}

function createBlock() {
    const index = Math.floor(Math.random() * BLOCKS.length);
    return {
        shape: BLOCKS[index],
        color: COLORS[index],
        x: Math.floor(COLS/2) - 1,
        y: 0
    };
}

function drawBlock(block, context, offsetX=0, offsetY=0) {
    context.fillStyle = block.color;
    block.shape.forEach((row, y) => {
        row.forEach((value, x) => {
            if(value) {
                context.fillRect(
                    (block.x + x + offsetX) * BLOCK_SIZE,
                    (block.y + y + offsetY) * BLOCK_SIZE,
                    BLOCK_SIZE-1, BLOCK_SIZE-1
                );
            }
        });
    });
}

function isValidMove(block, moveX=0, moveY=0, newShape) {
    const shape = newShape || block.shape;
    return shape.every((row, y) => 
        row.every((value, x) => {
            if(!value) return true;
            const newX = block.x + x + moveX;
            const newY = block.y + y + moveY;
            return newX >= 0 && newX < COLS && 
                   newY < ROWS && 
                   !board[newY]?.[newX];
        })
    );
}

function rotateBlock() {
    const newShape = currentBlock.shape[0].map((_, i) =>
        currentBlock.shape.map(row => row[i]).reverse()
    );
    if(isValidMove(currentBlock, 0, 0, newShape)) {
        currentBlock.shape = newShape;
    }
}

function mergeBlock() {
    currentBlock.shape.forEach((row, y) => {
        row.forEach((value, x) => {
            if(value) {
                board[currentBlock.y + y][currentBlock.x + x] = currentBlock.color;
            }
        });
    });
}

function clearLines() {
    let linesCleared = 0;
    for(let y = ROWS - 1; y >= 0; y--) {
        if(board[y].every(cell => cell)) {
            board.splice(y, 1);
            board.unshift(Array(COLS).fill(null));
            linesCleared++;
        }
    }
    if(linesCleared) {
        score += linesCleared * 100;
        document.getElementById('score').textContent = `得分: ${score}`;
    }
}

function drawBoard() {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    board.forEach((row, y) => {
        row.forEach((color, x) => {
            if(color) {
                ctx.fillStyle = color;
                ctx.fillRect(x*BLOCK_SIZE, y*BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1);
            }
            ctx.strokeRect(x*BLOCK_SIZE, y*BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
        });
    });
    drawBlock(currentBlock, ctx);
}

function gameOver() {
    clearInterval(gameLoop);
    document.getElementById('controls').innerHTML = `
        <div>游戏结束!得分: ${score}</div>
        <button onclick="startGame()">重新开始</button>
    `;
    document.getElementById('controls').style.display = 'block';
}

function drop() {
    currentBlock.y++;
    if(!isValidMove(currentBlock)) {
        currentBlock.y--;
        mergeBlock();
        clearLines();
        currentBlock = nextBlock;
        nextBlock = createBlock();
        if(!isValidMove(currentBlock)) {
            gameOver();
            return;
        }
        drawNextBlock();
    }
    drawBoard();
}

function drawNextBlock() {
    nextCtx.clearRect(0, 0, 120, 120);
    nextCtx.strokeStyle = '#303030';
    for(let y = 0; y < 4; y++) {
        for(let x = 0; x < 4; x++) {
            nextCtx.strokeRect(x*BLOCK_SIZE, y*BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
        }
    }
    drawBlock({...nextBlock, x:1, y:1}, nextCtx);
}

function startGame() {
    document.getElementById('controls').style.display = 'none';
    board = Array(ROWS).fill().map(() => Array(COLS).fill(null));
    score = 0;
    document.getElementById('score').textContent = `得分: 0`;
    currentBlock = createBlock();
    nextBlock = createBlock();
    drawNextBlock();
    drawBoard();
    
    if(gameLoop) clearInterval(gameLoop);
    gameLoop = setInterval(drop, dropSpeed);
}

document.addEventListener('keydown', e => {
    e.preventDefault();
    switch(e.key) {
        case 'ArrowLeft':
            if(isValidMove(currentBlock, -1)) currentBlock.x--; break;
        case 'ArrowRight':
            if(isValidMove(currentBlock, 1)) currentBlock.x++; break;
        case 'ArrowUp':
            rotateBlock(); break;
        case 'ArrowDown':
            drop(); break;
    }
    drawBoard();
});

initBoard();
</script>
</body>
</html>

 

 

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!