Классический вариант игры «Тетрис»
Файл index.html
<!DOCTYPE html>
<html>
<head>
<title>Tetris</title>
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="240" height="400"></canvas>
<script src="tetris.js"></script>
</body>
</html>
Файл tetris.js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const ROWS = 20;
const COLS = 10;
const BLOCK_SIZE = 20;
const colors = [
"#000000",
"#FF0000",
"#00FF00",
"#0000FF",
"#FFFF00",
"#00FFFF",
"#FF00FF",
"#C0C0C0",
];
const shapes = [
[
[1, 1],
[1, 1],
],
[
[0, 2, 0],
[2, 2, 2],
],
[
[0, 3, 3],
[3, 3, 0],
],
[
[4, 4, 0],
[0, 4, 4],
],
[
[5, 5, 5, 5],
],
[
[0, 6, 0, 0],
[0, 6, 0, 0],
[0, 6, 0, 0],
[0, 6, 0, 0],
],
[
[0, 0, 7],
[7, 7, 7],
[0, 0, 0],
],
];
let board = [];
let currentShape = null;
let currentX = 0;
let currentY = 0;
let score = 0;
function newShape() {
const shapeIndex = Math.floor(Math.random() * shapes.length);
const shape = shapes[shapeIndex];
currentShape = [];
for (let i = 0; i < shape.length; i++) {
currentShape[i] = [];
for (let j = 0; j < shape[i].length; j++) {
currentShape[i][j] = shape[i][j];
}
}
currentX = Math.floor((COLS - currentShape[0].length) / 2);
currentY = 0;
}
function init() {
for (let i = 0; i < ROWS; i++) {
board[i] = [];
for (let j = 0; j < COLS; j++) {
board[i][j] = 0;
}
}
newShape();
draw();
}
function drawBlock(x, y, color) {
ctx.fillStyle = colors[color];
ctx.fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
ctx.strokeStyle = "#000000";
ctx.strokeRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < ROWS; i++) {
for (let j = 0; j < COLS; j++) {
if (board[i][j]) {
drawBlock(j, i, board[i][j]);
}
}
}
for (let i = 0; i < currentShape.length; i++) {
for (let j = 0; j < currentShape[i].length; j++) {
if (currentShape[i][j]) {
drawBlock(currentX + j, currentY + i, currentShape[i][j]);
}
}
}
ctx.fillStyle = "#000000";
ctx.font = "20px Arial";
ctx.fillText(`Score: ${score}`, 10, 30);
}
function moveDown() {
if (canMove(0, 1)) {
currentY++;
} else {
freeze();
clearLines();
newShape();
}
draw();
}
function canMove(dx, dy) {
for (let i = 0; i < currentShape.length; i++) {
for (let j = 0; j < currentShape[i].length; j++) {
if (currentShape[i][j]) {
const newX = currentX + j + dx;
const newY = currentY + i + dy;
if (newX < 0 || newX >= COLS || newY >= ROWS) {
return false;
}
if (newY < 0) {
continue;
}
if (board[newY][newX]) {
return false;
}
}
}
}
return true;
}
function freeze() {
for (let i = 0; i < currentShape.length; i++) {
for (let j = 0; j < currentShape[i].length; j++) {
if (currentShape[i][j]) {
board[currentY + i][currentX + j] = currentShape[i][j];
}
}
}
}
function clearLines() {
let linesCleared = 0;
for (let i = ROWS - 1; i >= 0; i--) {
let rowFilled = true;
for (let j = 0; j < COLS; j++) {
if (board[i][j] === 0) {
rowFilled = false;
break;
}
}
if (rowFilled) {
for (let k = i; k > 0; k--) {
for (let j = 0; j < COLS; j++) {
board[k][j] = board[k - 1][j];
}
}
linesCleared++;
i++;
}
}
if (linesCleared > 0) {
score += linesCleared * 10;
}
}
document.addEventListener("keydown", (event) => {
switch (event.keyCode) {
case 37:
if (canMove(-1, 0)) {
currentX--;
draw();
}
break;
case 38:
rotate();
draw();
break;
case 39:
if (canMove(1, 0)) {
currentX++;
draw();
}
break;
case 40:
moveDown();
break;
}
});
function rotate() {
const newShape = [];
for (let i = 0; i < currentShape[0].length; i++) {
newShape[i] = [];
for (let j = 0; j < currentShape.length; j++) {
newShape[i][j] = currentShape[currentShape.length - 1 - j][i];
}
}
currentShape = newShape;
if (!canMove(0, 0)) {
currentShape = oldShape;
}
}
init();
setInterval(moveDown, 500);
7 Comments
Douglas had been drawn to Lengthy Seashore’s rising municipal airport with its Military and Navy amenities.
Greetings! Very useful advice within this article! It is the little changes that produce the biggest changes. Many thanks for sharing!
I quite like reading a post that will make men and women think. Also, thank you for allowing me to comment.
Aw, this was an extremely nice post. Spending some time and actual effort to make a really good article… but what can I say… I put things off a lot and don’t manage to get anything done.
wonderful issues altogether, you just won a new reader. What could you suggest about your publish that you made a few days in the past? Any certain?
I don’t even know how I ended up here, but I thought this post was great. I don’t know who you are but definitely you are going to a famous blogger if you aren’t already 😉 Cheers!
Loved the insight in this post. It’s highly comprehensive and full of useful details. Excellent job!