源码在效果图后面 五个按钮控制
效果图
源代码
<!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 {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: 'Arial', sans-serif;
background-color: #f0f0f0;
}
canvas {
border: 2px solid #333;
border-radius: 10px;
box-shadow: 2px 2px 12px rgba(0, 0, 0, 0.5);
background-color: #fff;
}
#controls {
margin-left: 20px;
display: flex;
flex-direction: column;
gap: 10px;
}
button {
padding: 10px 15px;
border: none;
border-radius: 5px;
background-color: #007bff;
color: #fff;
cursor: pointer;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<canvas id="board" width="300" height="600"></canvas>
<div id="controls">
<button id="left">左</button>
<button id="right">右</button>
<button id="down">下</button>
<button id="rotate">旋转</button>
<button id="start">开始</button>
</div>
<script>
const canvas = document.getElementById('board');
const ctx = canvas.getContext('2d');
const cols = 10;
const rows = 20;
const blockSize = 30;
const colors = [
null,
'cyan',
'blue',
'orange',
'yellow',
'green',
'purple',
'red',
];
const pieces = [
[[1, 1, 1, 1]], // I
[[1, 1, 1], [0, 1, 0]], // T
[[1, 1, 0], [0, 1, 1]], // Z
[[0, 1, 1], [1, 1, 0]], // S
[[1, 1], [1, 1]], // O
[[1, 1, 1], [1, 0, 0]], // L
[[1, 1, 1], [0, 0, 1]], // J
];
let board = Array.from({ length: rows }, () => Array(cols).fill(0));
let currentPiece;
let currentPosition;
let dropInterval;
let gameOver = false;
function drawBoard() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (board[r][c]) {
ctx.fillStyle = colors[board[r][c]];
ctx.fillRect(c * blockSize, r * blockSize, blockSize, blockSize);
ctx.strokeStyle = '#333';
ctx.strokeRect(c * blockSize, r * blockSize, blockSize, blockSize);
}
}
}
drawPiece();
}
function drawPiece() {
ctx.fillStyle = colors[currentPiece.color];
currentPiece.shape.forEach((row, r) => {
row.forEach((value, c) => {
if (value) {
ctx.fillRect((currentPosition.x + c) * blockSize, (currentPosition.y + r) * blockSize, blockSize, blockSize);
ctx.strokeRect((currentPosition.x + c) * blockSize, (currentPosition.y + r) * blockSize, blockSize, blockSize);
}
});
});
}
function rotate(piece) {
return piece[0].map((_, index) => piece.map(row => row[index])).reverse();
}
function collision(offsetX = 0, offsetY = 0, piece = currentPiece) {
return piece.shape.some((row, r) => {
return row.some((value, c) => {
if (value) {
const newX = currentPosition.x + c + offsetX;
const newY = currentPosition.y + r + offsetY;
return (
newX < 0 ||
newX >= cols ||
newY >= rows ||
(newY >= 0 && board[newY][newX] !== 0)
);
}
return false;
});
});
}
function merge() {
currentPiece.shape.forEach((row, r) => {
row.forEach((value, c) => {
if (value) {
board[currentPosition.y + r][currentPosition.x + c] = currentPiece.color;
}
});
});
clearRows();
}
function clearRows() {
for (let r = rows - 1; r >= 0; r--) {
if (board[r].every(cell => cell !== 0)) {
board.splice(r, 1);
board.unshift(Array(cols).fill(0));
}
}
}
function spawnPiece() {
const index = Math.floor(Math.random() * pieces.length);
currentPiece = {
shape: pieces[index],
color: index + 1,
};
currentPosition = { x: Math.floor(cols / 2) - 1, y: 0 };
if (collision(0, 0)) {
gameOver = true;
}
}
function drop() {
if (!gameOver) {
if (!collision(0, 1)) {
currentPosition.y++;
} else {
merge();
spawnPiece();
}
drawBoard();
} else {
clearInterval(dropInterval);
alert('游戏结束!');
}
}
function startGame() {
board = Array.from({ length: rows }, () => Array(cols).fill(0));
currentPiece = null;
currentPosition = null;
gameOver = false;
spawnPiece();
drawBoard();
dropInterval = setInterval(drop, 1000);
}
document.getElementById('left').addEventListener('click', () => {
if (!collision(-1, 0)) currentPosition.x--;
drawBoard();
});
document.getElementById('right').addEventListener('click', () => {
if (!collision(1, 0)) currentPosition.x++;
drawBoard();
});
document.getElementById('down').addEventListener('click', () => {
drop();
});
document.getElementById('rotate').addEventListener('click', () => {
const rotated = rotate(currentPiece.shape);
if (!collision(0, 0, { shape: rotated, color: currentPiece.color })) {
currentPiece.shape = rotated;
}
drawBoard();
});
document.getElementById('start').addEventListener('click', startGame);
drawBoard();
</script>
</body>
</html>