Игра «Тетрис»

Классический вариант игры «Тетрис»

Файл 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);

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *