我来为你创建一个完整的俄罗斯方块游戏,使用HTML、CSS和JavaScript实现。我为你创建了一个完整的俄罗斯方块游戏!这个游戏包含了所有经典功能:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>俄罗斯方块</title>
<style>
body {
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
font-family: 'Arial', sans-serif;
color: white;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.game-container {
display: flex;
gap: 30px;
align-items: flex-start;
}
.game-board {
border: 3px solid #fff;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
background: #000;
}
.info-panel {
background: rgba(255,255,255,0.1);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 20px;
min-width: 200px;
box-shadow: 0 8px 25px rgba(0,0,0,0.2);
}
.score {
font-size: 18px;
margin-bottom: 10px;
font-weight: bold;
}
.next-piece {
margin-top: 20px;
}
.next-canvas {
border: 2px solid rgba(255,255,255,0.3);
border-radius: 8px;
background: rgba(0,0,0,0.3);
}
.controls {
margin-top: 20px;
font-size: 14px;
line-height: 1.6;
}
.game-over {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.9);
color: white;
padding: 30px;
border-radius: 15px;
text-align: center;
display: none;
box-shadow: 0 15px 40px rgba(0,0,0,0.5);
}
.restart-btn {
background: linear-gradient(45deg, #ff6b6b, #ee5a52);
color: white;
border: none;
padding: 12px 25px;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
margin-top: 15px;
transition: transform 0.2s;
}
.restart-btn:hover {
transform: scale(1.05);
}
h1 {
text-align: center;
margin-bottom: 20px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
</style>
</head>
<body>
<div>
<h1>🎮 俄罗斯方块</h1>
<div class="game-container">
<canvas id="gameCanvas" class="game-board" width="300" height="600"></canvas>
<div class="info-panel">
<div class="score">得分: <span id="score">0</span></div>
<div class="score">等级: <span id="level">1</span></div>
<div class="score">行数: <span id="lines">0</span></div>
<div class="next-piece">
<div>下一个:</div>
<canvas id="nextCanvas" class="next-canvas" width="80" height="80"></canvas>
</div>
<div class="controls">
<strong>控制:</strong><br>
← → 移动<br>
↓ 快速下降<br>
↑ 旋转<br>
空格键 暂停
</div>
</div>
</div>
<div id="gameOver" class="game-over">
<h2>游戏结束</h2>
<p>最终得分: <span id="finalScore">0</span></p>
<button class="restart-btn" onclick="restartGame()">重新开始</button>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const nextCanvas = document.getElementById('nextCanvas');
const nextCtx = nextCanvas.getContext('2d');
const BOARD_WIDTH = 10;
const BOARD_HEIGHT = 20;
const BLOCK_SIZE = 30;
let board = Array(BOARD_HEIGHT).fill().map(() => Array(BOARD_WIDTH).fill(0));
let score = 0;
let level = 1;
let lines = 0;
let dropTime = 0;
let dropInterval = 1000;
let lastTime = 0;
let gameRunning = true;
let paused = false;
// 方块形状定义
const pieces = [
{ // I
shape: [
[1, 1, 1, 1]
],
color: '#00f5ff'
},
{ // O
shape: [
[1, 1],
[1, 1]
],
color: '#ffff00'
},
{ // T
shape: [
[0, 1, 0],
[1, 1, 1]
],
color: '#800080'
},
{ // S
shape: [
[0, 1, 1],
[1, 1, 0]
],
color: '#00ff00'
},
{ // Z
shape: [
[1, 1, 0],
[0, 1, 1]
],
color: '#ff0000'
},
{ // J
shape: [
[1, 0, 0],
[1, 1, 1]
],
color: '#0000ff'
},
{ // L
shape: [
[0, 0, 1],
[1, 1, 1]
],
color: '#ffa500'
}
];
let currentPiece = null;
let nextPiece = null;
function createPiece() {
const piece = pieces[Math.floor(Math.random() * pieces.length)];
return {
shape: piece.shape,
color: piece.color,
x: Math.floor(BOARD_WIDTH / 2) - Math.floor(piece.shape[0].length / 2),
y: 0
};
}
function drawBlock(ctx, x, y, color) {
ctx.fillStyle = color;
ctx.fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
ctx.strokeStyle = '#fff';
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);
// 绘制已放置的方块
for (let y = 0; y < BOARD_HEIGHT; y++) {
for (let x = 0; x < BOARD_WIDTH; x++) {
if (board[y][x]) {
drawBlock(ctx, x, y, board[y][x]);
}
}
}
// 绘制当前方块
if (currentPiece) {
drawPiece(ctx, currentPiece);
}
}
function drawPiece(context, piece) {
piece.shape.forEach((row, dy) => {
row.forEach((value, dx) => {
if (value) {
const x = piece.x + dx;
const y = piece.y + dy;
if (context === nextCtx) {
context.fillStyle = piece.color;
context.fillRect(dx * 20, dy * 20, 20, 20);
context.strokeStyle = '#fff';
context.strokeRect(dx * 20, dy * 20, 20, 20);
} else {
drawBlock(context, x, y, piece.color);
}
}
});
});
}
function isValidMove(piece, dx, dy) {
for (let y = 0; y < piece.shape.length; y++) {
for (let x = 0; x < piece.shape[y].length; x++) {
if (piece.shape[y][x]) {
const newX = piece.x + x + dx;
const newY = piece.y + y + dy;
if (newX < 0 || newX >= BOARD_WIDTH ||
newY >= BOARD_HEIGHT ||
(newY >= 0 && board[newY][newX])) {
return false;
}
}
}
}
return true;
}
function placePiece() {
currentPiece.shape.forEach((row, dy) => {
row.forEach((value, dx) => {
if (value) {
const x = currentPiece.x + dx;
const y = currentPiece.y + dy;
if (y >= 0) {
board[y][x] = currentPiece.color;
}
}
});
});
clearLines();
currentPiece = nextPiece;
nextPiece = createPiece();
if (!isValidMove(currentPiece, 0, 0)) {
gameOver();
}
}
function clearLines() {
let linesCleared = 0;
for (let y = BOARD_HEIGHT - 1; y >= 0; y--) {
if (board[y].every(cell => cell !== 0)) {
board.splice(y, 1);
board.unshift(Array(BOARD_WIDTH).fill(0));
linesCleared++;
y++; // 检查同一行
}
}
if (linesCleared > 0) {
lines += linesCleared;
score += linesCleared * 100 * level;
level = Math.floor(lines / 10) + 1;
dropInterval = Math.max(50, 1000 - (level - 1) * 100);
updateDisplay();
}
}
function rotatePiece() {
const rotated = currentPiece.shape[0].map((_, i) =>
currentPiece.shape.map(row => row[i]).reverse()
);
const originalShape = currentPiece.shape;
currentPiece.shape = rotated;
if (!isValidMove(currentPiece, 0, 0)) {
currentPiece.shape = originalShape;
}
}
function updateDisplay() {
document.getElementById('score').textContent = score;
document.getElementById('level').textContent = level;
document.getElementById('lines').textContent = lines;
nextCtx.clearRect(0, 0, nextCanvas.width, nextCanvas.height);
if (nextPiece) {
drawPiece(nextCtx, nextPiece);
}
}
function gameOver() {
gameRunning = false;
document.getElementById('finalScore').textContent = score;
document.getElementById('gameOver').style.display = 'block';
}
function restartGame() {
board = Array(BOARD_HEIGHT).fill().map(() => Array(BOARD_WIDTH).fill(0));
score = 0;
level = 1;
lines = 0;
dropInterval = 1000;
gameRunning = true;
paused = false;
currentPiece = createPiece();
nextPiece = createPiece();
document.getElementById('gameOver').style.display = 'none';
updateDisplay();
gameLoop();
}
function gameLoop(time = 0) {
if (!gameRunning || paused) return;
const deltaTime = time - lastTime;
lastTime = time;
dropTime += deltaTime;
if (dropTime > dropInterval) {
if (isValidMove(currentPiece, 0, 1)) {
currentPiece.y++;
} else {
placePiece();
}
dropTime = 0;
}
drawBoard();
requestAnimationFrame(gameLoop);
}
// 键盘控制
document.addEventListener('keydown', (e) => {
if (!gameRunning || paused) return;
switch(e.key) {
case 'ArrowLeft':
if (isValidMove(currentPiece, -1, 0)) {
currentPiece.x--;
}
break;
case 'ArrowRight':
if (isValidMove(currentPiece, 1, 0)) {
currentPiece.x++;
}
break;
case 'ArrowDown':
if (isValidMove(currentPiece, 0, 1)) {
currentPiece.y++;
score += 1;
updateDisplay();
}
break;
case 'ArrowUp':
rotatePiece();
break;
case ' ':
paused = !paused;
if (!paused) gameLoop();
break;
}
e.preventDefault();
});
// 初始化游戏
currentPiece = createPiece();
nextPiece = createPiece();
updateDisplay();
gameLoop();
</script>
</body>
</html>
游戏特色:
- 7种经典方块形状(I、O、T、S、Z、J、L)
- 完整的游戏逻辑:旋转、移动、消行
- 得分系统和等级提升
- 下一个方块预览
- 暂停功能
- 游戏结束和重新开始
操作说明:
- ← → 键:左右移动方块
- ↓ 键:加速下降
- ↑ 键:旋转方块
- 空格键:暂停/继续游戏
游戏机制:
- 消除一行得100分×当前等级
- 每消除10行升一级
- 等级越高,方块下降速度越快
- 方块堆到顶部游戏结束
界面采用了现代化的设计,包括渐变背景、毛玻璃效果和平滑动画。游戏完全可玩,你可以立即开始享受经典的俄罗斯方块游戏体验!