<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2048 Game with Super AI</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            background-color: #faf8ef;
            color: #776e65;
        }
        .container {
            width: 500px;
            margin: 0 auto;
        }
        #game-board {
            display: grid;
            grid-template-columns: repeat(4, 100px);
            grid-template-rows: repeat(4, 100px);
            gap: 10px;
            background-color: #bbada0;
            border-radius: 5px;
            padding: 10px;
            margin: 20px auto;
        }
        .tile {
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #cdc1b4;
            border-radius: 3px;
            font-size: 36px;
            font-weight: bold;
        }
        .tile-2 { background-color: #eee4da; }
        .tile-4 { background-color: #ede0c8; }
        .tile-8 { background-color: #f2b179; color: #f9f6f2; }
        .tile-16 { background-color: #f59563; color: #f9f6f2; }
        .tile-32 { background-color: #f67c5f; color: #f9f6f2; }
        .tile-64 { background-color: #f65e3b; color: #f9f6f2; }
        .tile-128 { background-color: #edcf72; color: #f9f6f2; font-size: 32px; }
        .tile-256 { background-color: #edcc61; color: #f9f6f2; font-size: 32px; }
        .tile-512 { background-color: #edc850; color: #f9f6f2; font-size: 32px; }
        .tile-1024 { background-color: #edc53f; color: #f9f6f2; font-size: 28px; }
        .tile-2048 { background-color: #edc22e; color: #f9f6f2; font-size: 28px; }
        .tile-4096 { background-color: #b885ac; color: #f9f6f2; font-size: 28px; }
        .tile-8192 { background-color: #af6da9; color: #f9f6f2; font-size: 28px; }
        
        .controls {
            margin: 20px 0;
        }
        button {
            padding: 10px 20px;
            margin: 0 5px;
            background-color: #8f7a66;
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
            font-weight: bold;
        }
        button:disabled {
            background-color: #cdc1b4;
            cursor: not-allowed;
        }
        #score-container {
            font-size: 24px;
            margin: 10px 0;
        }
        #ai-stats {
            margin: 10px 0;
            font-size: 14px;
            color: #776e65;
        }
        .ai-settings {
            display: flex;
            justify-content: center;
            margin: 10px 0;
            gap: 15px;
        }
        .setting-group {
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            padding: 10px;
            background-color: #eee4da;
            border-radius: 5px;
        }
        #ai-thinking {
            font-style: italic;
            margin-top: 10px;
            color: #8f7a66;
        }
        #iterations-display {
            font-size: 12px;
            color: #776e65;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>2048 с супер ИИ</h1>
        <div id="score-container">Счет: <span id="score">0</span></div>
        <div class="controls">
            <button id="new-game">Новая игра</button>
            <button id="ai-move">ИИ ход</button>
            <button id="ai-auto">ИИ авто-игра</button>
            <button id="ai-stop" disabled>Остановить ИИ</button>
        </div>
        <div class="ai-settings">
            <div class="setting-group">
                <label for="ai-algorithm">Алгоритм:</label>
                <select id="ai-algorithm">
                    <option value="expectimax">Expectimax (быстрый)</option>
                    <option value="mcts" selected>Monte Carlo (точный)</option>
                    <option value="combined">Комбинированный (лучший)</option>
                </select>
            </div>
            <div class="setting-group">
                <label for="search-depth">Глубина поиска:</label>
                <select id="search-depth">
                    <option value="4">4 (быстро)</option>
                    <option value="6" selected>6 (сбалансированно)</option>
                    <option value="8">8 (глубоко)</option>
                </select>
            </div>
            <div class="setting-group">
                <label for="iterations">Количество симуляций:</label>
                <select id="iterations">
                    <option value="500">500 (быстро)</option>
                    <option value="1000" selected>1000 (сбалансированно)</option>
                    <option value="2000">2000 (точно)</option>
                </select>
            </div>
        </div>
        <div id="ai-stats">
            <p>Наибольшая плитка: <span id="max-tile">0</span></p>
            <p>Количество ходов: <span id="move-count">0</span></p>
            <p id="iterations-display"></p>
        </div>
        <div id="ai-thinking"></div>
        <div id="game-board"></div>
    </div>

    <script>
        class Game2048 {
            constructor() {
                this.board = Array(4).fill().map(() => Array(4).fill(0));
                this.score = 0;
                this.gameOver = false;
                this.won = false;
                this.acknowledgedWin = false;
                this.aiPlaying = false;
                this.aiInterval = null;
                this.moveCount = 0;
                this.maxTile = 0;
                this.aiThinking = false;
                this.workerActive = false;
                this.worker = null;
                
                this.initializeBoard();
                this.setupEventListeners();
                this.startGame();
                this.setupWorker();
            }
            
            setupWorker() {
                // Create a blob URL for the worker script
                const workerCode = `
                    function cloneBoard(board) {
                        return JSON.parse(JSON.stringify(board));
                    }
                    
                    function getEmptyCells(board) {
                        const emptyCells = [];
                        for (let i = 0; i < 4; i++) {
                            for (let j = 0; j < 4; j++) {
                                if (board[i][j] === 0) {
                                    emptyCells.push({row: i, col: j});
                                }
                            }
                        }
                        return emptyCells;
                    }
                    
                    function addRandomTile(board) {
                        const emptyCells = getEmptyCells(board);
                        if (emptyCells.length > 0) {
                            const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
                            board[randomCell.row][randomCell.col] = Math.random() < 0.9 ? 2 : 4;
                        }
                        return board;
                    }
                    
                    // Helper functions for board manipulation
                    function transpose(board) {
                        const n = board.length;
                        const result = Array(n).fill().map(() => Array(n).fill(0));
                        for (let i = 0; i < n; i++) {
                            for (let j = 0; j < n; j++) {
                                result[i][j] = board[j][i];
                            }
                        }
                        return result;
                    }
                    
                    function reverse(board) {
                        return board.map(row => [...row].reverse());
                    }
                    
                    function moveLine(line) {
                        const newLine = [...line];
                        let score = 0;
                        
                        // Move all non-zero elements to the front
                        for (let i = 0; i < 4; i++) {
                            if (newLine[i] === 0) {
                                // Find the next non-zero element
                                for (let j = i + 1; j < 4; j++) {
                                    if (newLine[j] !== 0) {
                                        newLine[i] = newLine[j];
                                        newLine[j] = 0;
                                        break;
                                    }
                                }
                            }
                        }
                        
                        // Merge adjacent identical tiles
                        for (let i = 0; i < 3; i++) {
                            if (newLine[i] !== 0 && newLine[i] === newLine[i + 1]) {
                                newLine[i] *= 2;
                                score += newLine[i];
                                
                                // Shift the rest
                                for (let j = i + 1; j < 3; j++) {
                                    newLine[j] = newLine[j + 1];
                                }
                                newLine[3] = 0;
                            }
                        }
                        
                        return { line: newLine, score };
                    }
                    
                    function move(board, direction) {
                        let boardCopy = cloneBoard(board);
                        let moved = false;
                        let score = 0;
                        
                        // Transpose for up/down
                        if (direction === 'up' || direction === 'down') {
                            boardCopy = transpose(boardCopy);
                        }
                        
                        // Reverse for right/down
                        if (direction === 'right' || direction === 'down') {
                            boardCopy = reverse(boardCopy);
                        }
                        
                        // Process each row
                        for (let i = 0; i < 4; i++) {
                            const originalRow = [...boardCopy[i]];
                            const result = moveLine(originalRow);
                            boardCopy[i] = result.line;
                            score += result.score;
                            
                            // Check if moved
                            if (!moved && !originalRow.every((val, idx) => val === result.line[idx])) {
                                moved = true;
                            }
                        }
                        
                        // Reverse back
                        if (direction === 'right' || direction === 'down') {
                            boardCopy = reverse(boardCopy);
                        }
                        
                        // Transpose back
                        if (direction === 'up' || direction === 'down') {
                            boardCopy = transpose(boardCopy);
                        }
                        
                        return { board: boardCopy, moved, score };
                    }
                    
                    function isGameOver(board) {
                        // Check for empty cells
                        for (let i = 0; i < 4; i++) {
                            for (let j = 0; j < 4; j++) {
                                if (board[i][j] === 0) {
                                    return false;
                                }
                            }
                        }
                        
                        // Check for possible merges
                        for (let i = 0; i < 4; i++) {
                            for (let j = 0; j < 3; j++) {
                                if (board[i][j] === board[i][j + 1]) {
                                    return false;
                                }
                            }
                        }
                        
                        for (let j = 0; j < 4; j++) {
                            for (let i = 0; i < 3; i++) {
                                if (board[i][j] === board[i + 1][j]) {
                                    return false;
                                }
                            }
                        }
                        
                        return true;
                    }
                    
                    // Evaluation functions
                    function evaluateBoard(board) {
                        let score = 0;
                        
                        // 1. Weight matrix - prefers tiles in corners and edges with decreasing priority
                        const weightMatrix = [
                            [6.0, 5.0, 4.0, 3.0],
                            [5.0, 4.0, 3.0, 2.0],
                            [4.0, 3.0, 2.0, 1.0],
                            [3.0, 2.0, 1.0, 0.5]
                        ];
                        
                        // 2. Empty cell count (weighted heavily)
                        const emptyCells = getEmptyCells(board).length;
                        score += emptyCells * 30;
                        
                        // 3. Snake pattern evaluation (highest values in zigzag)
                        const snakePatterns = [
                            // Top-left based snake
                            [
                                [0, 0], [0, 1], [0, 2], [0, 3],
                                [1, 3], [1, 2], [1, 1], [1, 0],
                                [2, 0], [2, 1], [2, 2], [2, 3],
                                [3, 3], [3, 2], [3, 1], [3, 0]
                            ],
                            // Bottom-left based snake
                            [
                                [3, 0], [3, 1], [3, 2], [3, 3],
                                [2, 3], [2, 2], [2, 1], [2, 0],
                                [1, 0], [1, 1], [1, 2], [1, 3],
                                [0, 3], [0, 2], [0, 1], [0, 0]
                            ]
                        ];
                        
                        let bestSnakeScore = -Infinity;
                        for (const pattern of snakePatterns) {
                            let snakeScore = 0;
                            let prevValue = 0;
                            
                            for (const [row, col] of pattern) {
                                const cellValue = board[row][col];
                                if (cellValue > 0) {
                                    // Reward decreasing values along snake
                                    if (prevValue === 0 || cellValue <= prevValue) {
                                        snakeScore += cellValue * weightMatrix[row][col];
                                    } else {
                                        // Penalty for non-monotonic sequence
                                        snakeScore -= (cellValue - prevValue) * 1.5;
                                    }
                                    prevValue = cellValue;
                                }
                            }
                            
                            bestSnakeScore = Math.max(bestSnakeScore, snakeScore);
                        }
                        
                        score += bestSnakeScore * 2;
                        
                        // 4. Smoothness (adjacent tile similarity)
                        let smoothness = 0;
                        for (let i = 0; i < 4; i++) {
                            for (let j = 0; j < 4; j++) {
                                if (board[i][j] !== 0) {
                                    // Look right
                                    if (j < 3 && board[i][j+1] !== 0) {
                                        const diff = Math.abs(Math.log2(board[i][j]) - Math.log2(board[i][j+1]));
                                        smoothness -= diff * 2;
                                    }
                                    // Look down
                                    if (i < 3 && board[i+1][j] !== 0) {
                                        const diff = Math.abs(Math.log2(board[i][j]) - Math.log2(board[i+1][j]));
                                        smoothness -= diff * 2;
                                    }
                                }
                            }
                        }
                        score += smoothness;
                        
                        // 5. Mergeability (adjacent same values)
                        let mergeScore = 0;
                        for (let i = 0; i < 4; i++) {
                            for (let j = 0; j < 3; j++) {
                                if (board[i][j] !== 0 && board[i][j] === board[i][j+1]) {
                                    mergeScore += board[i][j];
                                }
                            }
                        }
                        for (let j = 0; j < 4; j++) {
                            for (let i = 0; i < 3; i++) {
                                if (board[i][j] !== 0 && board[i][j] === board[i+1][j]) {
                                    mergeScore += board[i][j];
                                }
                            }
                        }
                        score += mergeScore * 10;
                        
                        // 6. Value of highest cell in corner
                        const cornerMax = Math.max(
                            board[0][0], board[0][3], 
                            board[3][0], board[3][3]
                        );
                        score += cornerMax * 2.5;
                        
                        return score;
                    }
                    
                    // Expectimax algorithm
                    function expectimax(board, depth, isMaximizing) {
                        if (depth === 0 || isGameOver(board)) {
                            return { score: evaluateBoard(board), move: null };
                        }
                        
                        if (isMaximizing) {
                            let bestScore = -Infinity;
                            let bestMove = null;
                            
                            for (const direction of ['up', 'right', 'down', 'left']) {
                                const moveResult = move(board, direction);
                                
                                if (moveResult.moved) {
                                    const expectedScore = expectimax(moveResult.board, depth - 1, false).score;
                                    
                                    if (expectedScore > bestScore) {
                                        bestScore = expectedScore;
                                        bestMove = direction;
                                    }
                                }
                            }
                            
                            return { score: bestScore, move: bestMove };
                        } else {
                            const emptyCells = getEmptyCells(board);
                            
                            if (emptyCells.length === 0) {
                                return { score: evaluateBoard(board), move: null };
                            }
                            
                            let totalScore = 0;
                            
                            // Only sample a subset of cells for deeper depths
                            const sampleSize = depth > 3 ? Math.min(5, emptyCells.length) : emptyCells.length;
                            const sampledCells = emptyCells.slice(0, sampleSize);
                            
                            for (const cell of sampledCells) {
                                // Try adding a 2 (with 90% probability)
                                const boardWith2 = cloneBoard(board);
                                boardWith2[cell.row][cell.col] = 2;
                                const scoreWith2 = expectimax(boardWith2, depth - 1, true).score;
                                
                                // Try adding a 4 (with 10% probability)
                                const boardWith4 = cloneBoard(board);
                                boardWith4[cell.row][cell.col] = 4;
                                const scoreWith4 = expectimax(boardWith4, depth - 1, true).score;
                                
                                totalScore += (scoreWith2 * 0.9 + scoreWith4 * 0.1) / sampleSize;
                            }
                            
                            return { score: totalScore, move: null };
                        }
                    }
                    
                    // Monte Carlo Tree Search (MCTS)
                    class MCTSNode {
                        constructor(board, parent = null, move = null) {
                            this.board = board;
                            this.parent = parent;
                            this.move = move;  // Move that led to this board
                            this.children = [];
                            this.visits = 0;
                            this.score = 0;
                            this.untriedMoves = ['up', 'right', 'down', 'left'];
                        }
                        
                        select() {
                            // Select child with highest UCB score
                            let bestChild = null;
                            let bestUCB = -Infinity;
                            
                            for (const child of this.children) {
                                // UCB1 formula: average score + exploration term
                                const exploitation = child.score / (child.visits + Number.EPSILON);
                                const exploration = Math.sqrt(2 * Math.log(this.visits + 1) / (child.visits + Number.EPSILON));
                                const ucb = exploitation + exploration;
                                
                                if (ucb > bestUCB) {
                                    bestUCB = ucb;
                                    bestChild = child;
                                }
                            }
                            
                            return bestChild;
                        }
                        
                        expand() {
                            // Remove a random untried move
                            const index = Math.floor(Math.random() * this.untriedMoves.length);
                            const move = this.untriedMoves.splice(index, 1)[0];
                            
                            // Try the move
                            const moveResult = ::move(this.board, move);
                            
                            if (moveResult.moved) {
                                // Create new child node
                                const childBoard = addRandomTile(moveResult.board);
                                const childNode = new MCTSNode(childBoard, this, move);
                                this.children.push(childNode);
                                return childNode;
                            }
                                                        // If move didn't change the board, return null
                            if (this.untriedMoves.length === 0) {
                                return null;  // No valid moves left
                            }
                            return this.expand();  // Try another move
                        }
                        
                        simulate() {
                            // Perform a simulation from this node
                            let currentBoard = cloneBoard(this.board);
                            let depth = 0;
                            let gameScore = evaluateBoard(currentBoard);
                            let isGameTerminal = isGameOver(currentBoard);
                            
                            // Run simulation until game over or depth limit
                            while (!isGameTerminal && depth < 100) {
                                // Try random direction
                                const directions = ['up', 'right', 'down', 'left'];
                                let moved = false;
                                let attempts = 0;
                                
                                // Try random directions until a valid move is found
                                while (!moved && attempts < 4) {
                                    const direction = directions[Math.floor(Math.random() * directions.length)];
                                    const moveResult = move(currentBoard, direction);
                                    
                                    if (moveResult.moved) {
                                        currentBoard = moveResult.board;
                                        currentBoard = addRandomTile(currentBoard);
                                        moved = true;
                                    }
                                    
                                    attempts++;
                                }
                                
                                if (!moved) {
                                    isGameTerminal = true;
                                }
                                
                                depth++;
                            }
                            
                            // Return final evaluation score
                            return evaluateBoard(currentBoard);
                        }
                        
                        backpropagate(score) {
                            // Update stats
                            this.visits++;
                            this.score += score;
                            
                            // Propagate to parent if exists
                            if (this.parent) {
                                this.parent.backpropagate(score);
                            }
                        }
                        
                        getBestMove() {
                            // Find child with most visits
                            let bestChild = null;
                            let mostVisits = -1;
                            
                            for (const child of this.children) {
                                if (child.visits > mostVisits) {
                                    mostVisits = child.visits;
                                    bestChild = child;
                                }
                            }
                            
                            return bestChild ? bestChild.move : null;
                        }
                    }
                    
                    function mcts(board, iterations) {
                        const rootNode = new MCTSNode(board);
                        
                        for (let i = 0; i < iterations; i++) {
                            // 1. Selection: Find the most promising leaf node
                            let node = rootNode;
                            while (node.untriedMoves.length === 0 && node.children.length > 0) {
                                node = node.select();
                            }
                            
                            // 2. Expansion: Add a new child node
                            if (node.untriedMoves.length > 0) {
                                const expandedNode = node.expand();
                                if (expandedNode) {
                                    node = expandedNode;
                                }
                            }
                            
                            // 3. Simulation: Perform random playout
                            const score = node.simulate();
                            
                            // 4. Backpropagation: Update statistics
                            node.backpropagate(score);
                        }
                        
                        // Return the best move
                        return rootNode.getBestMove();
                    }
                    
                    // Combined approach using both algorithms
                    function findBestMove(board, algorithm, depth, iterations) {
                        let bestMove = null;
                        
                        // Progress tracking
                        let progress = 0;
                        const totalIterations = algorithm === 'combined' ? iterations + 10 : 
                                            algorithm === 'mcts' ? iterations : 1;
                        
                        function updateProgress(current) {
                            progress = Math.floor((current / totalIterations) * 100);
                            if (progress % 10 === 0) {
                                self.postMessage({type: 'progress', progress});
                            }
                        }
                        
                        if (algorithm === 'expectimax' || algorithm === 'combined') {
                            // First, use expectimax for initial assessment
                            updateProgress(0);
                            bestMove = expectimax(board, depth, true).move;
                            updateProgress(10);
                        }
                        
                        if (algorithm === 'mcts' || algorithm === 'combined') {
                            // Then, refine with MCTS if needed
                            updateProgress(algorithm === 'combined' ? 10 : 0);
                            const mctsMove = mcts(board, iterations);
                            
                            if (algorithm === 'mcts' || mctsMove !== null) {
                                bestMove = mctsMove;
                            }
                            
                            updateProgress(totalIterations);
                        }
                        
                        return bestMove;
                    }
                    
                    // Web Worker message handler
                    self.onmessage = function(e) {
                        const { board, algorithm, depth, iterations } = e.data;
                        
                        try {
                            const startTime = Date.now();
                            const bestMove = findBestMove(board, algorithm, depth, iterations);
                            const elapsedTime = Date.now() - startTime;
                            
                            self.postMessage({
                                type: 'result',
                                move: bestMove,
                                time: elapsedTime
                            });
                        } catch (error) {
                            self.postMessage({
                                type: 'error',
                                message: error.toString()
                            });
                        }
                    };
                `;
                
                const blob = new Blob([workerCode], { type: 'application/javascript' });
                const workerUrl = URL.createObjectURL(blob);
                this.worker = new Worker(workerUrl);
                
                this.worker.onmessage = (e) => {
                    const data = e.data;
                    
                    if (data.type === 'result') {
                        // AI found a move
                        if (this.aiThinking) {
                            this.aiThinking = false;
                            document.getElementById('ai-thinking').textContent = 
                                `ИИ выбрал ход: ${this.translateDirection(data.move)} (за ${data.time} мс)`;
                            
                            if (data.move) {
                                const moved = this.move(data.move);
                                if (moved) {
                                    this.moveCount++;
                                    this.addRandomTile();
                                    this.updateView();
                                    this.checkGameStatus();
                                    
                                    if (this.aiPlaying && !this.gameOver) {
                                        setTimeout(() => this.makeAIMove(), 150);
                                    }
                                }
                            }
                        }
                    } else if (data.type === 'progress') {
                        // Update progress
                        document.getElementById('ai-thinking').textContent = 
                            `ИИ думает... ${data.progress}% завершено`;
                    } else if (data.type === 'error') {
                        console.error('Worker error:', data.message);
                        document.getElementById('ai-thinking').textContent = 
                            `Ошибка ИИ: ${data.message}`;
                        this.aiThinking = false;
                    }
                };
                
                // Clean up the URL object
                URL.revokeObjectURL(workerUrl);
            }
            
            translateDirection(direction) {
                const translations = {
                    'up': 'Вверх',
                    'down': 'Вниз',
                    'left': 'Влево',
                    'right': 'Вправо'
                };
                return translations[direction] || direction;
            }
            
            initializeBoard() {
                const gameBoard = document.getElementById('game-board');
                gameBoard.innerHTML = '';
                
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        const tile = document.createElement('div');
                        tile.classList.add('tile');
                        tile.dataset.row = i;
                        tile.dataset.col = j;
                        gameBoard.appendChild(tile);
                    }
                }
            }
            
            setupEventListeners() {
                document.addEventListener('keydown', this.handleKeyPress.bind(this));
                document.getElementById('new-game').addEventListener('click', () => this.startGame());
                document.getElementById('ai-move').addEventListener('click', () => this.makeAIMove());
                document.getElementById('ai-auto').addEventListener('click', () => this.startAI());
                document.getElementById('ai-stop').addEventListener('click', () => this.stopAI());
            }
            
            startGame() {
                this.board = Array(4).fill().map(() => Array(4).fill(0));
                this.score = 0;
                this.gameOver = false;
                this.won = false;
                this.acknowledgedWin = false;
                this.moveCount = 0;
                this.maxTile = 0;
                this.stopAI();
                
                // Add two initial tiles
                this.addRandomTile();
                this.addRandomTile();
                
                this.updateView();
                document.getElementById('ai-thinking').textContent = '';
            }
            
            addRandomTile() {
                const emptyCells = [];
                
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (this.board[i][j] === 0) {
                            emptyCells.push({row: i, col: j});
                        }
                    }
                }
                
                if (emptyCells.length > 0) {
                    const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
                    this.board[randomCell.row][randomCell.col] = Math.random() < 0.9 ? 2 : 4;
                    
                    // Update max tile
                    this.updateMaxTile();
                }
            }
            
            updateMaxTile() {
                let max = 0;
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        max = Math.max(max, this.board[i][j]);
                    }
                }
                this.maxTile = max;
                document.getElementById('max-tile').textContent = this.maxTile;
            }
            
            updateView() {
                const tiles = document.querySelectorAll('.tile');
                const scoreElement = document.getElementById('score');
                const moveCountElement = document.getElementById('move-count');
                
                scoreElement.textContent = this.score;
                moveCountElement.textContent = this.moveCount;
                
                tiles.forEach(tile => {
                    const row = parseInt(tile.dataset.row);
                    const col = parseInt(tile.dataset.col);
                    const value = this.board[row][col];
                    
                    tile.textContent = value !== 0 ? value : '';
                    
                    // Reset classes
                    tile.className = 'tile';
                    if (value !== 0) {
                        tile.classList.add(`tile-${value}`);
                    }
                });
                
                if (this.gameOver) {
                    alert('Игра окончена! Ваш счет: ' + this.score + '. Наибольшая плитка: ' + this.maxTile);
                } else if (this.won && !this.acknowledgedWin) {
                    this.acknowledgedWin = true;
                    alert('Поздравляем! Вы достигли плитки 2048! Игра продолжается...');
                }
            }
            
            handleKeyPress(event) {
                if (this.gameOver || this.aiPlaying || this.aiThinking) return;
                
                let moved = false;
                
                switch(event.key) {
                    case 'ArrowUp':
                        moved = this.move('up');
                        break;
                    case 'ArrowDown':
                        moved = this.move('down');
                        break;
                    case 'ArrowLeft':
                        moved = this.move('left');
                        break;
                    case 'ArrowRight':
                        moved = this.move('right');
                        break;
                }
                
                if (moved) {
                    this.moveCount++;
                    this.addRandomTile();
                    this.updateView();
                    this.checkGameStatus();
                }
            }
            
            move(direction) {
                const oldBoard = JSON.parse(JSON.stringify(this.board));
                
                // Transpose the board for up/down moves
                if (direction === 'up' || direction === 'down') {
                    this.transpose();
                }
                
                // Reverse the rows for right/down moves
                if (direction === 'right' || direction === 'down') {
                    this.reverse();
                }
                
                let moved = false;
                
                // Move and merge tiles
                for (let i = 0; i < 4; i++) {
                    const result = this.moveLine(this.board[i]);
                    this.board[i] = result.line;
                    this.score += result.score;
                    if (result.moved) {
                        moved = true;
                    }
                }
                
                // Reverse back
                if (direction === 'right' || direction === 'down') {
                    this.reverse();
                }
                
                // Transpose back
                if (direction === 'up' || direction === 'down') {
                    this.transpose();
                }
                
                // Check if the board actually changed
                return moved;
            }
            
            moveLine(line) {
                const originalLine = [...line];
                const newLine = Array(4).fill(0);
                let score = 0;
                let index = 0;
                let moved = false;
                
                // Move all non-zero elements to the front
                for (let i = 0; i < 4; i++) {
                    if (line[i] !== 0) {
                        newLine[index++] = line[i];
                    }
                }
                
                // Merge adjacent identical tiles
                for (let i = 0; i < 3; i++) {
                    if (newLine[i] !== 0 && newLine[i] === newLine[i + 1]) {
                        newLine[i] *= 2;
                        score += newLine[i];
                        
                        if (newLine[i] === 2048 && !this.won) {
                            this.won = true;
                        }
                        
                        // Shift the rest of the line
                        for (let j = i + 1; j < 3; j++) {
                            newLine[j] = newLine[j + 1];
                        }
                        newLine[3] = 0;
                    }
                }
                
                // Check if the line actually moved
                moved = !originalLine.every((val, i) => val === newLine[i]);
                
                return { line: newLine, score, moved };
            }
            
            transpose() {
                const n = this.board.length;
                for (let i = 0; i < n; i++) {
                    for (let j = i; j < n; j++) {
                        const temp = this.board[i][j];
                        this.board[i][j] = this.board[j][i];
                        this.board[j][i] = temp;
                    }
                }
            }
            
            reverse() {
                for (let i = 0; i < 4; i++) {
                    this.board[i].reverse();
                }
            }
            
            checkGameStatus() {
                // Update max tile
                this.updateMaxTile();
                
                // Check for 2048 tile for win condition
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (this.board[i][j] === 2048 && !this.won) {
                            this.won = true;
                        }
                    }
                }
                
                // Check if there are any empty cells
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (this.board[i][j] === 0) {
                            return; // Game not over
                        }
                    }
                }
                
                // Check if any moves are possible
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 3; j++) {
                        if (this.board[i][j] === this.board[i][j + 1]) {
                            return; // Horizontal move possible
                        }
                    }
                }
                
                for (let j = 0; j < 4; j++) {
                    for (let i = 0; i < 3; i++) {
                        if (this.board[i][j] === this.board[i + 1][j]) {
                            return; // Vertical move possible
                        }
                    }
                }
                
                // No moves possible
                this.gameOver = true;
            }
            
            // Advanced AI methods
            makeAIMove() {
                if (this.gameOver || this.aiThinking) return;
                
                this.aiThinking = true;
                document.getElementById('ai-thinking').textContent = "ИИ думает...";
                document.getElementById('ai-move').disabled = true;
                
                // Get AI settings
                const algorithm = document.getElementById('ai-algorithm').value;
                const depth = parseInt(document.getElementById('search-depth').value);
                const iterations = parseInt(document.getElementById('iterations').value);
                
                // Display iterations info
                document.getElementById('iterations-display').textContent = 
                    `Используется: ${algorithm === 'expectimax' ? 'Expectimax с глубиной ' + depth : 
                              algorithm === 'mcts' ? 'Monte Carlo с ' + iterations + ' симуляциями' :
                              'Комбинированный подход (Expectimax + Monte Carlo)'}`;
                
                // Use web worker for AI to keep UI responsive
                this.worker.postMessage({
                    board: this.board,
                    algorithm,
                    depth,
                    iterations
                });
            }
            
            startAI() {
                if (this.aiInterval) {
                    this.stopAI();
                }
                
                this.aiPlaying = true;
                document.getElementById('ai-move').disabled = true;
                document.getElementById('ai-auto').disabled = true;
                document.getElementById('ai-stop').disabled = false;
                
                // Start with first move
                this.makeAIMove();
            }
            
            stopAI() {
                this.aiPlaying = false;
                document.getElementById('ai-move').disabled = false;
                document.getElementById('ai-auto').disabled = false;
                document.getElementById('ai-stop').disabled = true;
                document.getElementById('ai-thinking').textContent = "";
            }
        }
        
        // Initialize the game
        const game = new Game2048();
    </script>
</body>
</html>

                            
Найди и исправь ошибки в коде, чтобы игра была полностью рабочей