<!DOCTYPE html>

<html lang="en">

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>Tetris Game</title>

        <style>

            canvas {

                border: 1px solid #000;

            }

        </style>

    </head>

    <body>

        <canvas id="canvas" width="200" height="400"></canvas>

        <script>

            const canvas = document.getElementById("canvas");

            const context = canvas.getContext("2d");

            const blockSize = 20;

            const numRows = 20;

            const numCols = 10;

            const screen = new Array(numRows).fill(0).map(() => new Array(numCols).fill(0));

            let gameStarted = false; // New variable to track game start

            let paused = false; // Variable to track whether the game is paused

            const tetrominoes = [

                { shape: [[1, 1, 1, 1]], color: "red" },

                { shape: [[1, 1, 1], [1]], color: "orange" },

                { shape: [[1, 1, 1], [0, 0, 1]], color: "yellow" },

                { shape: [[1, 1, 1], [0, 1]], color: "green" },

                { shape: [[1, 1], [1, 1]], color: "blue" },

                { shape: [[1, 1, 0], [0, 1, 1]], color: "indigo" },

                { shape: [[0, 1, 1], [1, 1]], color: "purple" },

            ];


            let tetromino = getRandomTetromino();


            function drawBlock(x, y, color) {

                context.fillStyle = color;

                context.fillRect(x * blockSize, y * blockSize, blockSize, blockSize);

                context.strokeStyle = "black";

                context.strokeRect(x * blockSize, y * blockSize, blockSize, blockSize);

            }


            function draw() {

                context.clearRect(0, 0, canvas.width, canvas.height);


                // Draw filled blocks on the screen

                for (let y = 0; y < numRows; y++) {

                    for (let x = 0; x < numCols; x++) {

                        if (screen[y][x] !== 0) {

                            drawBlock(x, y, "gray");

                        }

                    }

                }


                if (!gameStarted) {

                    // Draw initial screen message

                    context.fillStyle = "black";

                    context.font = "14px Arial"; // Adjusted font size

                    const message = paused ? "Game Paused - Press Space to Resume" : "Press Enter to start the game";

                    const textWidth = context.measureText(message).width;

                    context.fillText(message, (canvas.width - textWidth) / 2, canvas.height / 2);

                } else {

                    // Draw Tetromino

                    tetromino.shape.forEach((row, y) => {

                        row.forEach((value, x) => {

                            if (value !== 0) {

                                drawBlock(tetromino.x + x, tetromino.y + y, tetromino.color);

                            }

                        });

                    });

                }


                // Draw pause/resume message

                if (paused && gameStarted) {

                    context.fillStyle = "black";

                    context.font = "10px Arial"; // Adjusted font size

                    const pauseMessage = "Game Paused - Press Space to Resume";

                    const pauseTextWidth = context.measureText(pauseMessage).width;

                    context.fillText(pauseMessage, (canvas.width - pauseTextWidth) / 2, canvas.height - 10);

                }

            }


            function moveDown() {

                tetromino.y++;

                if (checkCollision()) {

                    tetromino.y--;

                    placeTetromino();

                    clearLines();

                    if (isGameOver()) {

                        endGame();

                    } else {

                        spawnTetromino();

                    }

                }

            }


            function moveLeft() {

                tetromino.x--;

                if (checkCollision()) {

                    tetromino.x++;

                }

            }


            function moveRight() {

                tetromino.x++;

                if (checkCollision()) {

                    tetromino.x--;

                }

            }


            function rotate() {

                const originalShape = tetromino.shape;

                tetromino.shape = rotateMatrix(tetromino.shape);

                if (checkCollision()) {

                    tetromino.shape = originalShape;

                }

            }


            function getRandomTetromino() {

                const randomIndex = Math.floor(Math.random() * tetrominoes.length);

                return {

                    shape: tetrominoes[randomIndex].shape,

                    color: tetrominoes[randomIndex].color,

                    x: Math.floor((numCols - tetrominoes[randomIndex].shape[0].length) / 2),

                    y: 0,

                };

            }


            function rotateMatrix(matrix) {

                const rows = matrix.length;

                const cols = matrix[0].length;

                const result = new Array(cols).fill(0).map(() => new Array(rows).fill(0));


                for (let i = 0; i < rows; i++) {

                    for (let j = 0; j < cols; j++) {

                        result[j][rows - 1 - i] = matrix[i][j];

                    }

                }


                return result;

            }


            function checkCollision() {

                for (let y = 0; y < tetromino.shape.length; y++) {

                    for (let x = 0; x < tetromino.shape[y].length; x++) {

                        if (

                            tetromino.shape[y][x] !== 0 &&

                            (screen[tetromino.y + y] && screen[tetromino.y + y][tetromino.x + x]) !== 0

                        ) {

                            return true;

                        }

                    }

                }

                return false;

            }


            function placeTetromino() {

                tetromino.shape.forEach((row, y) => {

                    row.forEach((value, x) => {

                        if (value !== 0) {

                            screen[tetromino.y + y][tetromino.x + x] = 1;

                        }

                    });

                });

            }


            function clearLines() {

                for (let y = numRows - 1; y >= 0; y--) {

                    if (screen[y].every((value) => value !== 0)) {

                        // Clear the line

                        screen.splice(y, 1);

                        screen.unshift(new Array(numCols).fill(0));

                    }

                }

            }


            function spawnTetromino() {

                tetromino = getRandomTetromino();

            }


            function isGameOver() {

                // Check if the top row has any filled blocks

                return screen[0].some((value) => value !== 0);

            }


            function endGame() {

                // Perform actions when the game is over

                gameStarted = false;

                paused = false;

                alert("Game Over! Press Enter to restart.");

                resetGame();

            }


            function resetGame() {

                // Reset the game state

                screen.forEach((row) => row.fill(0));

            }


            function togglePause() {

                paused = !paused;

            }


            function update() {

                if (gameStarted && !paused) {

                    moveDown();

                }

                draw();

            }


            // Handle keyboard input

            document.addEventListener("keydown", (event) => {

                if (!gameStarted && event.code === "Enter") {

                    // Start or resume the game on pressing Enter

                    gameStarted = true;

                    paused = false; // Ensure the game is not paused when starting

                } else if (gameStarted) {

                    // Continue handling other keys during the game

                    switch (event.code) {

                        case "ArrowLeft":

                            moveLeft();

                            break;

                        case "ArrowRight":

                            moveRight();

                            break;

                        case "ArrowDown":

                            moveDown();

                            break;

                        case "ArrowUp":

                            rotate();

                            break;

                        case "Space":

                            togglePause(); // Pause or resume the game on pressing Space

                            break;

                    }

                }

            });

            // Game loop

            setInterval(update, 500);

        </script>

    </body>

</html>
html로 테트리스 개발해보면서 공부하려는데, 테트리스 블록 중에서 T자 블록이랑 L자 블록이 회전하면서 모양이 뭉게지는 현상이 발생함.
아마 rotate()함수나 
rotateMatrix()함수에 문제가 있는 것 같은데 계속 수정해봤는데도 문제가 있음. 해결책 알려주면 감사하겠습니다...