<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
    <channel>
        <title>Маргарита - Блог 5</title>
        <link>http://margo.mozello.shop/blog-5/</link>
        <description>Маргарита - Блог 5</description>
                    <item>
                <title>Перша новина</title>
                <link>http://margo.mozello.shop/blog-5/params/post/5342594/persha-novina</link>
                <pubDate>Tue, 03 Nov 2026 13:20:00 +0000</pubDate>
                <description>1жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж&lt;p&gt;7&lt;/p&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot;&gt;
&lt;title&gt;Мозаїка Майстрів — Версія 1.9 (Планшетна адаптація)&lt;/title&gt;
&lt;h2&gt;Мозаїка Майстрів — Версія 1.9 (Планшетна адаптація)&lt;/h2&gt;
&lt;p&gt;Права кнопка миші — поворот блоку на 90°, Жест двома пальцями —
поворот на кут, Кнопка &quot;Скасувати&quot; — скасування ходу&lt;/p&gt;
&lt;div id=&quot;gameContainer&quot;&gt;
&lt;canvas id=&quot;gameCanvas&quot; width=&quot;250&quot; height=&quot;250&quot;&gt;&lt;/canvas&gt;
&lt;div id=&quot;controlPanel&quot;&gt;&lt;button id=&quot;pauseButton&quot; fdprocessedid=&quot;imgj4r&quot;&gt;Пауза&lt;/button&gt; &lt;button id=&quot;undoButton&quot; disabled=&quot;&quot;&gt;Скасувати&lt;/button&gt;
&lt;div id=&quot;rotateButtons&quot;&gt;&lt;button onclick=&quot;rotateSelectedBlock(90)&quot; fdprocessedid=&quot;q77zl&quot;&gt;90°&lt;/button&gt; &lt;button onclick=&quot;rotateSelectedBlock(180)&quot; fdprocessedid=&quot;2d8u&quot;&gt;180°&lt;/button&gt; &lt;button onclick=&quot;rotateSelectedBlock(270)&quot; fdprocessedid=&quot;1gr28&quot;&gt;270°&lt;/button&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;nextBlocks&quot;&gt;
&lt;canvas id=&quot;block1&quot; class=&quot;blockCanvas&quot; width=&quot;60&quot; height=&quot;60&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
&lt;canvas id=&quot;block2&quot; class=&quot;blockCanvas&quot; width=&quot;60&quot; height=&quot;60&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
&lt;canvas id=&quot;block3&quot; class=&quot;blockCanvas&quot; width=&quot;60&quot; height=&quot;60&quot; draggable=&quot;true&quot;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;div id=&quot;score&quot;&gt;Очки: 0&lt;/div&gt;
&lt;div id=&quot;highScore&quot;&gt;Рекорд: 0&lt;/div&gt;
&lt;div id=&quot;bonusMessage&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;gameOver&quot;&gt;
&lt;h2&gt;Гра закінчена!&lt;/h2&gt;
&lt;p id=&quot;finalScore&quot;&gt;&lt;/p&gt;
&lt;button onclick=&quot;restartGame()&quot; fdprocessedid=&quot;17a4n&quot;&gt;Грати знову&lt;/button&gt;&lt;/div&gt;
&lt;div id=&quot;pauseOverlay&quot;&gt;
&lt;h2&gt;Гра на паузі&lt;/h2&gt;
&lt;button onclick=&quot;togglePause()&quot; fdprocessedid=&quot;jrjse5&quot;&gt;Відновити&lt;/button&gt;&lt;/div&gt;
&lt;div class=&quot;accordion&quot;&gt;
&lt;div class=&quot;accordion-item&quot;&gt;
&lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;
Таблиця блоків&lt;/div&gt;
&lt;div class=&quot;accordion-content&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Назва&lt;/th&gt;
&lt;th&gt;Зображення&lt;/th&gt;
&lt;th&gt;Структура&lt;/th&gt;
&lt;th&gt;Використання&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Одинарний&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeSingle&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для заповнення окремих клітинок&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L-форма&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeL&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 1],
                  &lt;br&gt;[1, 0]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для кутів або вузьких просторів&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T-форма&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeT&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 1, 1],
                  &lt;br&gt;[0, 1, 0]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для горизонтальних ліній з виступом&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I-форма (4)&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeI4&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для заповнення рядків/стовпців&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Квадрат&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeSquare&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 1],
                  &lt;br&gt;[1, 1]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для компактних квадратних просторів&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Z-форма&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeZ&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 1, 0],
                  &lt;br&gt;[0, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для зміщених &quot;змійок&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I-форма (5)&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeI5&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 1, 1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для довгих рядків/стовпців&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I-форма (3)&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeI3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 1, 1]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для середніх рядків/стовпців&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I-форма (2)&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeI2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 1]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для коротких рядків/стовпців&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Діагональ 2x2&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeDiagonal2&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 0],
                  &lt;br&gt;[0, 1]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для заповнення діагональних просторів&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Діагональ 3x3&lt;/td&gt;
&lt;td&gt;
&lt;canvas id=&quot;shapeDiagonal3&quot; width=&quot;60&quot; height=&quot;60&quot;&gt;&lt;/canvas&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;[[1, 0, 0],
                  &lt;br&gt;[0, 1, 0],
                  &lt;br&gt;[0, 0, 1]]&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;Для довгих діагональних ліній&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;accordion-item&quot;&gt;
&lt;div class=&quot;accordion-header&quot; onclick=&quot;toggleAccordion(this)&quot;&gt;
Інструкція&lt;/div&gt;
&lt;div class=&quot;accordion-content&quot;&gt;
&lt;h3&gt;Мета гри&lt;/h3&gt;
&lt;p&gt;&quot;Мозаїка Майстрів&quot; — це головоломка, де гравець розміщує блоки
на сітці 10x10, щоб очищати цілі рядки або стовпці. Мета — набрати
якомога більше очок і встановити рекорд. Гра закінчується, коли
жоден блок не можна розмістити.&lt;/p&gt;
&lt;h3&gt;Правила гри&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ігрове поле&lt;/b&gt;: Сітка 10x10, де клітинки можуть бути
порожніми або заповненими.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Черга блоків&lt;/b&gt;: До трьох блоків відображаються знизу для
розміщення.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Розміщення&lt;/b&gt;: Перетягуйте блоки на сітку. Розміщення
можливе лише у вільних місцях.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Очищення ліній&lt;/b&gt;:
&lt;ul&gt;
&lt;li&gt;Повний рядок або стовпець очищається.&lt;/li&gt;
&lt;li&gt;1 лінія: 100 очок.&lt;/li&gt;
&lt;li&gt;2+ ліній: 100 + 50 за кожну додаткову (наприклад, 2 лінії = 150
очок).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Бонус за очищення поля&lt;/b&gt;: 25% від суми очок, якщо поле
порожнє.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Рекорд&lt;/b&gt;: Зберігається у браузері, відображається під час
гри та після завершення.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Кінець гри&lt;/b&gt;: Гра закінчується, якщо блоки неможливо
розмістити.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Дії гравця&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Перетягування&lt;/b&gt;:
&lt;ul&gt;
&lt;li&gt;Сенсорні пристрої: Торкніться та перетягніть.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Поворот&lt;/b&gt;: Кнопки 90°/180°/270° або жест двома
пальцями.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Скасування ходу&lt;/b&gt;: Кнопка &quot;Скасувати&quot; для останнього
ходу.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Пауза&lt;/b&gt;: Кнопка &quot;Пауза&quot;/&quot;Відновити&quot;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Перезапуск&lt;/b&gt;: Кнопка &quot;Грати знову&quot; на екрані &quot;Гра
закінчена&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Поради&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Плануйте ходи, щоб створювати повні лінії.&lt;/li&gt;
&lt;li&gt;Використовуйте одинарний блок для прогалин.&lt;/li&gt;
&lt;li&gt;Скасовуйте невдалі ходи.&lt;/li&gt;
&lt;li&gt;Намагайтеся очищати кілька ліній для бонусів.&lt;/li&gt;
&lt;li&gt;Експериментуйте з діагональними блоками для унікальних
комбінацій.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
    // Акордеон-меню
        function toggleAccordion(header) {
            const content = header.nextElementSibling;
            const isActive = content.classList.contains(&#039;active&#039;);
            document.querySelectorAll(&#039;.accordion-content&#039;).forEach(item =&gt; {
                item.classList.remove(&#039;active&#039;);
                item.previousElementSibling.classList.remove(&#039;active&#039;);
            });
            if (!isActive) {
                content.classList.add(&#039;active&#039;);
                header.classList.add(&#039;active&#039;);
            }
        }

        // Ігрова логіка
        const gameCanvas = document.getElementById(&#039;gameCanvas&#039;);
        const ctx = gameCanvas.getContext(&#039;2d&#039;);
        const gridSize = 10;
        const cellSize = gameCanvas.width / gridSize; // 25px або 30px на планшеті
        const scoreElement = document.getElementById(&#039;score&#039;);
        const highScoreElement = document.getElementById(&#039;highScore&#039;);
        const bonusMessageElement = document.getElementById(&#039;bonusMessage&#039;);
        const gameOverElement = document.getElementById(&#039;gameOver&#039;);
        const finalScoreElement = document.getElementById(&#039;finalScore&#039;);
        const pauseButton = document.getElementById(&#039;pauseButton&#039;);
        const undoButton = document.getElementById(&#039;undoButton&#039;);
        const pauseOverlay = document.getElementById(&#039;pauseOverlay&#039;);

        let grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
        let score = 0;
        let highScore = parseInt(localStorage.getItem(&#039;blockLegendHighScore&#039;)) || 0;
        let currentBlocks = [];
        let selectedBlock = null;
        let selectedBlockIndex = -1;
        let gameActive = true;
        let gamePaused = false;
        let lastMove = null;

        highScoreElement.textContent = `Рекорд: ${highScore}`;
        console.log(&#039;Завантажено рекорд:&#039;, highScore);

        const blockShapes = [
            [[1]], // Одинарний
            [[1, 1], [1, 0]], // L-форма
            [[1, 1, 1], [0, 1, 0]], // T-форма
            [[1, 1, 1, 1]], // I-форма (4)
            [[1, 1], [1, 1]], // Квадрат
            [[1, 1, 0], [0, 1, 1]], // Z-форма
            [[1, 1, 1, 1, 1]], // I-форма (5)
            [[1, 1, 1]], // I-форма (3)
            [[1, 1]], // I-форма (2)
            [[1, 0], [0, 1]], // Діагональ 2x2
            [[1, 0, 0], [0, 1, 0], [0, 0, 1]] // Діагональ 3x3
        ];

        const colors = [&#039;#FF0000&#039;, &#039;#00FF00&#039;, &#039;#0000FF&#039;, &#039;#FFFF00&#039;, &#039;#FF00FF&#039;, &#039;#FFA500&#039;, &#039;#800080&#039;, &#039;#00FFFF&#039;, &#039;#FF4500&#039;, &#039;#2E8B57&#039;, &#039;#DAA520&#039;, &#039;#8A2BE2&#039;];

        // Малювання блоків у таблиці
        function drawTableBlock(canvasId, shape, color) {
            const canvas = document.getElementById(canvasId);
            const ctx = canvas.getContext(&#039;2d&#039;);
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const maxSize = Math.max(shape.length, shape[0].length);
            const blockCellSize = canvas.width / maxSize;
            shape.forEach((row, y) =&gt; {
                row.forEach((cell, x) =&gt; {
                    if (cell) {
                        ctx.fillStyle = color;
                        ctx.fillRect(x * blockCellSize + 2, y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                        ctx.strokeStyle = &#039;#000&#039;;
                        ctx.strokeRect(x * blockCellSize + 2, y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                    }
                });
            });
        }

        // Ініціалізація малюнків у таблиці
        drawTableBlock(&#039;shapeSingle&#039;, blockShapes[0], colors[0]);
        drawTableBlock(&#039;shapeL&#039;, blockShapes[1], colors[1]);
        drawTableBlock(&#039;shapeT&#039;, blockShapes[2], colors[2]);
        drawTableBlock(&#039;shapeI4&#039;, blockShapes[3], colors[3]);
        drawTableBlock(&#039;shapeSquare&#039;, blockShapes[4], colors[4]);
        drawTableBlock(&#039;shapeZ&#039;, blockShapes[5], colors[0]);
        drawTableBlock(&#039;shapeI5&#039;, blockShapes[6], colors[5]);
        drawTableBlock(&#039;shapeI3&#039;, blockShapes[7], colors[6]);
        drawTableBlock(&#039;shapeI2&#039;, blockShapes[8], colors[1]);
        drawTableBlock(&#039;shapeDiagonal2&#039;, blockShapes[9], colors[10]);
        drawTableBlock(&#039;shapeDiagonal3&#039;, blockShapes[10], colors[11]);

        function showBonusMessage(message) {
            bonusMessageElement.textContent = message;
            bonusMessageElement.style.display = &#039;block&#039;;
            setTimeout(() =&gt; bonusMessageElement.style.display = &#039;none&#039;, 2000);
        }

        function drawGrid() {
            ctx.clearRect(0, 0, gameCanvas.width, gameCanvas.height);
            for (let y = 0; y &lt; gridSize; y++) {
                for (let x = 0; x &lt; gridSize; x++) {
                    ctx.strokeStyle = &#039;#000&#039;;
                    ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize);
                    if (grid[y][x]) {
                        ctx.fillStyle = grid[y][x];
                        ctx.fillRect(x * cellSize + 2, y * cellSize + 2, cellSize - 4, cellSize - 4);
                    }
                }
            }
        }

        function drawPreview(shape, x, y, valid) {
            drawGrid();
            if (shape &amp;&amp; x &gt;= 0 &amp;&amp; y &gt;= 0) {
                ctx.globalAlpha = 0.5;
                for (let sy = 0; sy &lt; shape.length; sy++) {
                    for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                        if (shape[sy][sx]) {
                            ctx.fillStyle = valid ? selectedBlock.color : &#039;#FF0000&#039;;
                            ctx.fillRect((x + sx) * cellSize + 2, (y + sy) * cellSize + 2, cellSize - 4, cellSize - 4);
                            ctx.strokeStyle = &#039;#000&#039;;
                            ctx.strokeRect((x + sx) * cellSize + 2, (y + sy) * cellSize + 2, cellSize - 4, cellSize - 4);
                        }
                    }
                }
                ctx.globalAlpha = 1.0;
            }
        }

        function canPlaceBlock(shape, x, y) {
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        const gridX = x + sx;
                        const gridY = y + sy;
                        if (gridX &lt; 0 || gridX &gt;= gridSize || gridY &lt; 0 || gridY &gt;= gridSize || grid[gridY][gridX]) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        function placeBlock(shape, color, x, y, blockIndex) {
            console.log(`Розміщення блоку на позиції (${x}, ${y}), індекс: ${blockIndex}, форма:`, JSON.stringify(shape));
            lastMove = {
                grid: grid.map(row =&gt; [...row]),
                score,
                block: { shape, color },
                blockIndex
            };
            undoButton.disabled = false;
            for (let sy = 0; sy &lt; shape.length; sy++) {
                for (let sx = 0; sx &lt; shape[sy].length; sx++) {
                    if (shape[sy][sx]) {
                        grid[y + sy][x + sx] = color;
                    }
                }
            }
            console.log(&#039;Блок розміщено, викликаємо checkLines&#039;);
            checkLines();
            console.log(&#039;checkLines завершено, викликаємо checkGameOver&#039;);
            checkGameOver();
            drawGrid();
            console.log(&#039;Розміщення завершено, поточна черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
        }

        function checkLines() {
            let linesCleared = 0;
            for (let y = gridSize - 1; y &gt;= 0; y--) {
                if (grid[y].every(cell =&gt; cell)) {
                    grid.splice(y, 1);
                    grid.unshift(Array(gridSize).fill(null));
                    linesCleared++;
                    y++;
                }
            }
            for (let x = gridSize - 1; x &gt;= 0; x--) {
                let isFull = true;
                for (let y = 0; y &lt; gridSize; y++) {
                    if (!grid[y][x]) {
                        isFull = false;
                        break;
                    }
                }
                if (isFull) {
                    for (let y = 0; y &lt; gridSize; y++) {
                        grid[y].splice(x, 1);
                        grid[y].push(null);
                    }
                    linesCleared++;
                    x++;
                }
            }
            if (linesCleared &gt; 0) {
                let lineBonus = linesCleared === 1 ? 100 : 100 + (linesCleared - 1) * 50;
                score += lineBonus;
                if (linesCleared &gt; 1) {
                    showBonusMessage(`Бонус за ${linesCleared} лінії: +${lineBonus} очок`);
                    console.log(`Бонус за очищення ${linesCleared} ліній: +${lineBonus} очок`);
                }
                const isGridEmpty = grid.every(row =&gt; row.every(cell =&gt; !cell));
                if (isGridEmpty &amp;&amp; score &gt; 0) {
                    const clearBonus = Math.floor(score * 0.25);
                    score += clearBonus;
                    showBonusMessage(`Бонус за повне очищення поля: +${clearBonus} очок`);
                    console.log(`Бонус за повне очищення поля: +${clearBonus} очок`);
                }
                scoreElement.textContent = `Очки: ${score}`;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    highScoreElement.textContent = `Рекорд: ${highScore}`;
                    console.log(&#039;Новий рекорд:&#039;, highScore);
                }
            }
            console.log(&#039;Очищено ліній:&#039;, linesCleared, &#039;Очки:&#039;, score, &#039;Рекорд:&#039;, highScore);
        }

        function checkGameOver() {
            console.log(&#039;Перевірка стану гри. Кількість блоків:&#039;, currentBlocks.length, &#039;Блоки:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
            if (currentBlocks.length === 0) {
                console.log(&#039;Черга порожня, генеруємо нові блоки&#039;);
                setTimeout(() =&gt; {
                    generateBlocks();
                    console.log(&#039;Нові блоки згенеровано, нова черга:&#039;, JSON.stringify(currentBlocks.map(b =&gt; ({ shape: b.shape, color: b.color }))));
                }, 0);
                return;
            }
            let canPlaceAny = false;
            for (let block of currentBlocks) {
                for (let y = 0; y &lt; gridSize; y++) {
                    for (let x = 0; x &lt; gridSize; x++) {
                        if (canPlaceBlock(block.shape, x, y)) {
                            canPlaceAny = true;
                            break;
                        }
                    }
                    if (canPlaceAny) break;
                }
                if (canPlaceAny) break;
            }
            console.log(&#039;Чи можна розмістити блок:&#039;, canPlaceAny);
            if (!canPlaceAny) {
                gameActive = false;
                if (score &gt; highScore) {
                    highScore = score;
                    localStorage.setItem(&#039;blockLegendHighScore&#039;, highScore);
                    console.log(&#039;Новий рекорд на кінці гри:&#039;, highScore);
                }
                finalScoreElement.textContent = `Ваш рахунок: ${score}\nРекорд: ${highScore}`;
                gameOverElement.style.display = &#039;block&#039;;
                console.log(&#039;Гра закінчена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
            }
        }

        function restartGame() {
            grid = Array(gridSize).fill().map(() =&gt; Array(gridSize).fill(null));
            score = 0;
            scoreElement.textContent = `Очки: ${score}`;
            highScoreElement.textContent = `Рекорд: ${highScore}`;
            gameOverElement.style.display = &#039;none&#039;;
            gamePaused = false;
            pauseButton.textContent = &#039;Пауза&#039;;
            pauseOverlay.style.display = &#039;none&#039;;
            undoButton.disabled = true;
            lastMove = null;
            gameActive = true;
            currentBlocks = [];
            generateBlocks();
            drawGrid();
            console.log(&#039;Гра перезапущена. Рахунок:&#039;, score, &#039;Рекорд:&#039;, highScore);
        }

        function togglePause() {
            if (!gameActive) return;
            gamePaused = !gamePaused;
            pauseButton.textContent = gamePaused ? &#039;Відновити&#039; : &#039;Пауза&#039;;
            pauseOverlay.style.display = gamePaused ? &#039;block&#039; : &#039;none&#039;;
            console.log(&#039;Гра на паузі:&#039;, gamePaused);
        }

        pauseButton.addEventListener(&#039;click&#039;, togglePause);
        undoButton.addEventListener(&#039;click&#039;, undoMove);

        const blockCanvases = document.querySelectorAll(&#039;.blockCanvas&#039;);
        let touchStart = { x1: 0, y1: 0, x2: 0, y2: 0, time: 0 };

        blockCanvases.forEach(canvas =&gt; {
            canvas.addEventListener(&#039;dragstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                selectedBlock = currentBlocks[index];
                selectedBlockIndex = index;
                canvas.classList.add(&#039;dragging&#039;);
                e.dataTransfer.setData(&#039;text/plain&#039;, index);
                console.log(&#039;Початок перетягування блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
            });

            canvas.addEventListener(&#039;dragend&#039;, (e) =&gt; {
                canvas.classList.remove(&#039;dragging&#039;);
                selectedBlock = null;
                selectedBlockIndex = -1;
                drawGrid();
                console.log(&#039;Кінець перетягування&#039;);
            });

            canvas.addEventListener(&#039;contextmenu&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                rotateSelectedBlock(90, index);
                drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                console.log(&#039;Блок повернуто на 90°:&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
            });

            canvas.addEventListener(&#039;touchstart&#039;, (e) =&gt; {
                if (!gameActive || gamePaused || e.touches.length &lt; 1) return;
                const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                selectedBlock = currentBlocks[index];
                selectedBlockIndex = index;
                canvas.classList.add(&#039;dragging&#039;);
                if (e.touches.length === 1) {
                    touchStart = { x1: e.touches[0].clientX, y1: e.touches[0].clientY, time: Date.now() };
                } else if (e.touches.length === 2) {
                    touchStart = { x1: e.touches[0].clientX, y1: e.touches[0].clientY, x2: e.touches[1].clientX, y2: e.touches[1].clientY, time: Date.now() };
                }
                console.log(&#039;Початок сенсорного перетягування/ротації блоку:&#039;, index, &#039;Блок:&#039;, JSON.stringify(selectedBlock));
            });

            canvas.addEventListener(&#039;touchmove&#039;, (e) =&gt; {
                e.preventDefault();
                if (!gameActive || gamePaused || e.touches.length !== 2 || selectedBlockIndex === -1) return;
                const touch1 = e.touches[0];
                const touch2 = e.touches[1];
                const dx = touch2.clientX - touch1.clientX;
                const dy = touch2.clientY - touch1.clientY;
                const startDx = touchStart.x2 - touchStart.x1;
                const startDy = touchStart.y2 - touchStart.y1;
                let angle = Math.atan2(dy, dx) - Math.atan2(startDy, startDy);
                angle = Math.round(degrees(angle) / 90) * 90; // Округлення до найближчих 90°
                rotateSelectedBlock(angle, selectedBlockIndex);
                drawBlock(selectedBlockIndex, currentBlocks[selectedBlockIndex].shape, currentBlocks[selectedBlockIndex].color);
                touchStart = { x1: touch1.clientX, y1: touch1.clientY, x2: touch2.clientX, y2: touch2.clientY, time: Date.now() };
            });

            canvas.addEventListener(&#039;touchend&#039;, (e) =&gt; {
                if (!gameActive || !selectedBlock || gamePaused) return;
                const touch = e.changedTouches[0];
                const rect = gameCanvas.getBoundingClientRect();
                const x = Math.floor((touch.clientX - rect.left) / cellSize);
                const y = Math.floor((touch.clientY - rect.top) / cellSize);
                console.log(`Сенсорне розміщення: координати (${x}, ${y}), індекс: ${selectedBlockIndex}, блок:`, JSON.stringify(selectedBlock));
                if (selectedBlockIndex &gt;= 0 &amp;&amp; selectedBlockIndex &lt; currentBlocks.length) {
                    if (canPlaceBlock(selectedBlock.shape, x, y)) {
                        placeBlock(selectedBlock.shape, selectedBlock.color, x, y, selectedBlockIndex);
                        currentBlocks.splice(selectedBlockIndex, 1);
                        console.log(&#039;Блок видалено з черги. Залишилося:&#039;, currentBlocks.length);
                        for (let i = 0; i &lt; 3; i++) {
                            const blockCanvas = document.getElementById(`block${i + 1}`);
                            blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                            if (i &lt; currentBlocks.length) {
                                drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                            }
                        }
                        checkGameOver();
                        selectedBlock = null;
                        selectedBlockIndex = -1;
                    } else {
                        console.log(&#039;Неможливо розмістити блок на позиції:&#039;, x, y);
                    }
                }
                canvas.classList.remove(&#039;dragging&#039;);
                drawGrid();
                console.log(&#039;Сенсорне розміщення завершено&#039;);
                touchStart = null;
            });

            canvas.addEventListener(&#039;mousedown&#039;, (e) =&gt; {
                if (e.button === 1) {
                    e.preventDefault();
                    if (!gameActive || gamePaused) return;
                    const index = parseInt(canvas.id.replace(&#039;block&#039;, &#039;&#039;)) - 1;
                    currentBlocks[index].shape = flipShape(currentBlocks[index].shape);
                    drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
                    console.log(&#039;Блок перевернуто (середня кнопка):&#039;, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
                }
            });
        });

        gameCanvas.addEventListener(&#039;dragover&#039;, (e) =&gt; {
            e.preventDefault();
            if (!gameActive || !selectedBlock || gamePaused) return;
            const rect = gameCanvas.getBoundingClientRect();
            const x = Math.floor((e.clientX - rect.left) / cellSize);
            const y = Math.floor((e.clientY - rect.top) / cellSize);
            const valid = canPlaceBlock(selectedBlock.shape, x, y);
            drawPreview(selectedBlock.shape, x, y, valid);
        });

        gameCanvas.addEventListener(&#039;drop&#039;, (e) =&gt; {
            e.preventDefault();
            if (!gameActive || !selectedBlock || gamePaused) return;
            const rect = gameCanvas.getBoundingClientRect();
            const x = Math.floor((e.clientX - rect.left) / cellSize);
            const y = Math.floor((e.clientY - rect.top) / cellSize);
            const index = parseInt(e.dataTransfer.getData(&#039;text/plain&#039;));
            console.log(`Розміщення через drag: координати (${x}, ${y}), індекс: ${index}, блок:`, JSON.stringify(selectedBlock));
            if (index &gt;= 0 &amp;&amp; index &lt; currentBlocks.length) {
                if (canPlaceBlock(selectedBlock.shape, x, y)) {
                    placeBlock(selectedBlock.shape, selectedBlock.color, x, y, index);
                    currentBlocks.splice(index, 1);
                    console.log(&#039;Блок видалено з черги. Залишилося:&#039;, currentBlocks.length);
                    for (let i = 0; i &lt; 3; i++) {
                        const blockCanvas = document.getElementById(`block${i + 1}`);
                        blockCanvas.getContext(&#039;2d&#039;).clearRect(0, 0, blockCanvas.width, blockCanvas.height);
                        if (i &lt; currentBlocks.length) {
                            drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
                        }
                    }
                    checkGameOver();
                    selectedBlock = null;
                    selectedBlockIndex = -1;
                } else {
                    console.log(&#039;Неможливо розмістити блок на позиції:&#039;, x, y);
                }
            } else {
                console.error(&#039;Помилка: невалідний індекс блоку на drop&#039;, index);
            }
        });

        function generateBlocks() {
            currentBlocks = [];
            for (let i = 0; i &lt; 3; i++) {
                const shapeIndex = Math.floor(Math.random() * blockShapes.length);
                const colorIndex = Math.floor(Math.random() * colors.length);
                currentBlocks.push({ shape: blockShapes[shapeIndex], color: colors[colorIndex] });
                drawBlock(i, currentBlocks[i].shape, currentBlocks[i].color);
            }
        }

        function drawBlock(index, shape, color) {
            const canvas = document.getElementById(`block${index + 1}`);
            const blockCtx = canvas.getContext(&#039;2d&#039;);
            blockCtx.clearRect(0, 0, canvas.width, canvas.height);
            const maxSize = Math.max(shape.length, shape[0].length);
            const blockCellSize = canvas.width / maxSize;
            const offsetX = (canvas.width - maxSize * blockCellSize) / 2;
            const offsetY = (canvas.height - maxSize * blockCellSize) / 2;
            for (let y = 0; y &lt; shape.length; y++) {
                for (let x = 0; x &lt; shape[y].length; x++) {
                    if (shape[y][x]) {
                        blockCtx.fillStyle = color;
                        blockCtx.fillRect(offsetX + x * blockCellSize + 2, offsetY + y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                        blockCtx.strokeStyle = &#039;#000&#039;;
                        blockCtx.strokeRect(offsetX + x * blockCellSize + 2, offsetY + y * blockCellSize + 2, blockCellSize - 4, blockCellSize - 4);
                    }
                }
            }
        }

        function rotateSelectedBlock(angle, index) {
            if (index === undefined || index &lt; 0 || index &gt;= currentBlocks.length) {
                console.error(&#039;Невірний індекс блоку для ротації:&#039;, index);
                return;
            }
            let shape = currentBlocks[index].shape;
            let newShape = Array(shape[0].length).fill().map(() =&gt; Array(shape.length).fill(0));
            for (let y = 0; y &lt; shape.length; y++) {
                for (let x = 0; x &lt; shape[y].length; x++) {
                    let newX, newY;
                    if (angle === 90) {
                        newX = shape.length - 1 - y;
                        newY = x;
                    } else if (angle === 180) {
                        newX = shape[y].length - 1 - x;
                        newY = shape.length - 1 - y;
                    } else if (angle === 270) {
                        newX = y;
                        newY = shape[0].length - 1 - x;
                    } else {
                        return; // Нічого не робимо для інших кутів
                    }
                    newShape[newY][newX] = shape[y][x];
                }
            }
            currentBlocks[index].shape = newShape;
            drawBlock(index, currentBlocks[index].shape, currentBlocks[index].color);
            console.log(`Блок повернуто на ${angle}°:`, index, &#039;Нова форма:&#039;, JSON.stringify(currentBlocks[index].shape));
        }

        function flipShape(shape) {
            return shape[0].map((_, col) =&gt; shape.map(row =&gt; row[col]).reverse());
        }

        function undoMove() {
            if (lastMove) {
                grid = lastMove.grid;
                score = lastMove.score;
                currentBlocks[lastMove.blockIndex] = lastMove.block;
                scoreElement.textContent = `Очки: ${score}`;
                drawGrid();
                drawBlock(lastMove.blockIndex, currentBlocks[lastMove.blockIndex].shape, currentBlocks[lastMove.blockIndex].color);
                lastMove = null;
                undoButton.disabled = true;
                console.log(&#039;Хід скасовано&#039;);
            }
        }

        generateBlocks();
        drawGrid();
        console.log(&#039;Гра ініціалізована — Мозаїка Майстрів Версія 1.9&#039;);
  &lt;/script&gt;</description>
            </item>
            </channel>
</rss>