726 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			726 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html>
 | 
						|
<html lang="de">
 | 
						|
<head>
 | 
						|
    <meta charset="UTF-8">
 | 
						|
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
						|
    <title>Minesweeper | PonyWave Tools</title>
 | 
						|
    <meta property="og:title" content="Minesweeper | PonyWave Tools">
 | 
						|
    <meta property="og:description" content="Klassisches Minesweeper-Spiel mit verschiedenen Schwierigkeitsgraden">
 | 
						|
    <meta property="og:type" content="website">
 | 
						|
    <meta property="og:url" content="https://tools.ponywave.de/minesweeper">
 | 
						|
    <meta property="og:image" content="https://tools.ponywave.de/minesweeper/icon.png">
 | 
						|
    
 | 
						|
    <!-- Favicons -->
 | 
						|
    <link rel="icon" type="image/png" href="https://tools.ponywave.de/minesweeper/icon.png">
 | 
						|
    <link rel="shortcut icon" href="https://tools.ponywave.de/minesweeper/icon.png">
 | 
						|
    <link rel="apple-touch-icon" href="https://tools.ponywave.de/minesweeper/icon.png">
 | 
						|
    <link rel="icon" sizes="192x192" href="https://tools.ponywave.de/minesweeper/icon.png">
 | 
						|
 | 
						|
    <!-- Umami Tracking -->
 | 
						|
    <script defer src="https://stats.ponywave.de/script" data-website-id="9ef713d2-adb9-4906-9df5-708d8a8b9131" data-tag="minesweeper"></script>
 | 
						|
    
 | 
						|
    <style>
 | 
						|
        :root {
 | 
						|
            --primary-color: #7F006E;
 | 
						|
            --secondary-color: #FF7FED;
 | 
						|
            --bg-gradient: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
 | 
						|
            --text-color: #2c3e50;
 | 
						|
            --cell-size: 30px;
 | 
						|
            --board-bg: #c0c0c0;
 | 
						|
            --cell-bg: #c0c0c0;
 | 
						|
            --cell-border: #808080;
 | 
						|
            --cell-revealed: #d9d9d9;
 | 
						|
            --font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 | 
						|
            --shadow-color: rgba(0, 0, 0, 0.1);
 | 
						|
            --footer-color: rgba(255, 255, 255, 0.8);
 | 
						|
            --button-bg: #f0f0f0;
 | 
						|
            --button-hover: #e0e0e0;
 | 
						|
            --button-active: #d0d0d0;
 | 
						|
        }
 | 
						|
 | 
						|
        .dark-mode {
 | 
						|
            --bg-gradient: linear-gradient(135deg, #4A0040 0%, #CC65B5 100%);
 | 
						|
            --text-color: #ffffff;
 | 
						|
            --board-bg: #444444;
 | 
						|
            --cell-bg: #555555;
 | 
						|
            --cell-border: #666666;
 | 
						|
            --cell-revealed: #333333;
 | 
						|
            --button-bg: #555555;
 | 
						|
            --button-hover: #666666;
 | 
						|
            --button-active: #777777;
 | 
						|
            --shadow-color: rgba(0, 0, 0, 0.3);
 | 
						|
            --footer-color: rgba(0, 0, 0, 0.8);
 | 
						|
        }
 | 
						|
 | 
						|
        body {
 | 
						|
            font-family: var(--font-family);
 | 
						|
            background-color: var(--board-bg);
 | 
						|
            background-image: none;
 | 
						|
            color: var(--text-color);
 | 
						|
            margin: 0;
 | 
						|
            padding: 20px 20px 60px;
 | 
						|
            min-height: 100vh;
 | 
						|
            position: relative;
 | 
						|
            line-height: 1.6;
 | 
						|
            text-align: center;
 | 
						|
        }
 | 
						|
 | 
						|
        .dark-mode body {
 | 
						|
            background-image: none;
 | 
						|
            background-color: #444444;
 | 
						|
        }
 | 
						|
 | 
						|
        .theme-toggle {
 | 
						|
            position: fixed;
 | 
						|
            top: 20px;
 | 
						|
            right: 20px;
 | 
						|
            background: var(--button-bg);
 | 
						|
            border: none;
 | 
						|
            border-radius: 50%;
 | 
						|
            width: 40px;
 | 
						|
            height: 40px;
 | 
						|
            cursor: pointer;
 | 
						|
            box-shadow: 0 2px 4px var(--shadow-color);
 | 
						|
            display: flex;
 | 
						|
            align-items: center;
 | 
						|
            justify-content: center;
 | 
						|
            font-size: 1.2em;
 | 
						|
            transition: all 0.3s ease;
 | 
						|
            z-index: 10;
 | 
						|
        }
 | 
						|
 | 
						|
        .theme-toggle:hover {
 | 
						|
            transform: scale(1.1);
 | 
						|
        }
 | 
						|
 | 
						|
        h1 {
 | 
						|
            margin: 20px 0;
 | 
						|
            color: var(--text-color);
 | 
						|
            text-shadow: 2px 2px 4px var(--shadow-color);
 | 
						|
        }
 | 
						|
 | 
						|
        .game-container {
 | 
						|
            display: flex;
 | 
						|
            flex-direction: column;
 | 
						|
            align-items: center;
 | 
						|
            justify-content: center;
 | 
						|
            margin: 20px auto;
 | 
						|
            max-width: 800px;
 | 
						|
            background: rgba(255, 255, 255, 0.9);
 | 
						|
            padding: 20px;
 | 
						|
            border-radius: 15px;
 | 
						|
            box-shadow: 0 4px 6px var(--shadow-color);
 | 
						|
            backdrop-filter: blur(5px);
 | 
						|
            overflow-x: hidden;
 | 
						|
            width: 90%;
 | 
						|
        }
 | 
						|
 | 
						|
        .dark-mode .game-container {
 | 
						|
            background: rgba(45, 45, 45, 0.9);
 | 
						|
        }
 | 
						|
 | 
						|
        .game-header {
 | 
						|
            display: flex;
 | 
						|
            width: 100%;
 | 
						|
            justify-content: space-between;
 | 
						|
            align-items: center;
 | 
						|
            margin-bottom: 20px;
 | 
						|
        }
 | 
						|
 | 
						|
        .counter {
 | 
						|
            background: #000;
 | 
						|
            color: #f00;
 | 
						|
            font-family: 'Digital', monospace;
 | 
						|
            padding: 5px 10px;
 | 
						|
            border-radius: 3px;
 | 
						|
            font-size: 1.5em;
 | 
						|
            min-width: 80px;
 | 
						|
            text-align: center;
 | 
						|
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
 | 
						|
        }
 | 
						|
 | 
						|
        .smiley {
 | 
						|
            width: 40px;
 | 
						|
            height: 40px;
 | 
						|
            background: var(--button-bg);
 | 
						|
            border: 2px outset var(--cell-border);
 | 
						|
            border-radius: 50%;
 | 
						|
            display: flex;
 | 
						|
            align-items: center;
 | 
						|
            justify-content: center;
 | 
						|
            font-size: 1.5em;
 | 
						|
            cursor: pointer;
 | 
						|
            user-select: none;
 | 
						|
        }
 | 
						|
 | 
						|
        .smiley:active {
 | 
						|
            border-style: inset;
 | 
						|
        }
 | 
						|
 | 
						|
        .difficulty {
 | 
						|
            display: flex;
 | 
						|
            gap: 10px;
 | 
						|
            margin-bottom: 20px;
 | 
						|
        }
 | 
						|
 | 
						|
        .difficulty button {
 | 
						|
            padding: 8px 15px;
 | 
						|
            background: var(--button-bg);
 | 
						|
            border: 1px solid var(--cell-border);
 | 
						|
            border-radius: 5px;
 | 
						|
            cursor: pointer;
 | 
						|
            transition: all 0.2s;
 | 
						|
            font-family: var(--font-family);
 | 
						|
        }
 | 
						|
 | 
						|
        .difficulty button:hover {
 | 
						|
            background: var(--button-hover);
 | 
						|
        }
 | 
						|
 | 
						|
        .difficulty button.active {
 | 
						|
            background: var(--primary-color);
 | 
						|
            color: white;
 | 
						|
        }
 | 
						|
 | 
						|
        .minesweeper-board {
 | 
						|
            display: grid;
 | 
						|
            background: var(--board-bg);
 | 
						|
            border: 3px solid var(--cell-border);
 | 
						|
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
 | 
						|
            margin: 0 auto;
 | 
						|
            user-select: none;
 | 
						|
            max-width: 100%;
 | 
						|
        }
 | 
						|
 | 
						|
        .cell {
 | 
						|
            width: var(--cell-size);
 | 
						|
            height: var(--cell-size);
 | 
						|
            background: var(--cell-bg);
 | 
						|
            border: 2px outset var(--cell-border);
 | 
						|
            display: flex;
 | 
						|
            align-items: center;
 | 
						|
            justify-content: center;
 | 
						|
            font-weight: bold;
 | 
						|
            font-size: 1.1em;
 | 
						|
            cursor: pointer;
 | 
						|
            transition: background-color 0.1s;
 | 
						|
        }
 | 
						|
 | 
						|
        .cell.revealed {
 | 
						|
            background: var(--cell-revealed);
 | 
						|
            border: 1px solid var(--cell-border);
 | 
						|
        }
 | 
						|
 | 
						|
        .cell.flagged::before {
 | 
						|
            content: "🚩";
 | 
						|
        }
 | 
						|
 | 
						|
        .cell.mine-clicked {
 | 
						|
            background: red;
 | 
						|
        }
 | 
						|
 | 
						|
        .cell.mine::before {
 | 
						|
            content: "💣";
 | 
						|
        }
 | 
						|
 | 
						|
        .cell.number-1 { color: blue; }
 | 
						|
        .cell.number-2 { color: green; }
 | 
						|
        .cell.number-3 { color: red; }
 | 
						|
        .cell.number-4 { color: darkblue; }
 | 
						|
        .cell.number-5 { color: brown; }
 | 
						|
        .cell.number-6 { color: teal; }
 | 
						|
        .cell.number-7 { color: black; }
 | 
						|
        .cell.number-8 { color: gray; }
 | 
						|
 | 
						|
        .instructions {
 | 
						|
            margin: 20px auto;
 | 
						|
            max-width: 600px;
 | 
						|
            text-align: left;
 | 
						|
            padding: 15px;
 | 
						|
            background: rgba(255, 255, 255, 0.8);
 | 
						|
            border-radius: 10px;
 | 
						|
            box-shadow: 0 2px 5px var(--shadow-color);
 | 
						|
        }
 | 
						|
 | 
						|
        .dark-mode .instructions {
 | 
						|
            background: rgba(45, 45, 45, 0.8);
 | 
						|
        }
 | 
						|
 | 
						|
        footer {
 | 
						|
            position: fixed;
 | 
						|
            bottom: 0;
 | 
						|
            left: 0;
 | 
						|
            right: 0;
 | 
						|
            padding: 15px;
 | 
						|
            text-align: center;
 | 
						|
            font-size: 0.9em;
 | 
						|
            background: var(--footer-color);
 | 
						|
            backdrop-filter: blur(5px);
 | 
						|
            z-index: 10;
 | 
						|
        }
 | 
						|
 | 
						|
        footer a {
 | 
						|
            color: var(--primary-color);
 | 
						|
            text-decoration: none;
 | 
						|
            font-weight: 500;
 | 
						|
            transition: opacity 0.3s ease;
 | 
						|
        }
 | 
						|
 | 
						|
        footer a:hover {
 | 
						|
            opacity: 0.8;
 | 
						|
            text-decoration: underline;
 | 
						|
        }
 | 
						|
 | 
						|
        @media (max-width: 600px) {
 | 
						|
            :root {
 | 
						|
                --cell-size: 25px;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .game-container {
 | 
						|
                padding: 10px;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .counter {
 | 
						|
                font-size: 1.2em;
 | 
						|
                min-width: 60px;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .smiley {
 | 
						|
                width: 35px;
 | 
						|
                height: 35px;
 | 
						|
            }
 | 
						|
            
 | 
						|
            .difficulty button {
 | 
						|
                padding: 6px 10px;
 | 
						|
                font-size: 0.9em;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        @media (max-width: 400px) {
 | 
						|
            :root {
 | 
						|
                --cell-size: 20px;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    </style>
 | 
						|
</head>
 | 
						|
<body>
 | 
						|
    <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
 | 
						|
    
 | 
						|
    <h1>Minesweeper</h1>
 | 
						|
    
 | 
						|
    <div class="game-container">
 | 
						|
        <div class="game-header">
 | 
						|
            <div class="counter" id="mines-counter">000</div>
 | 
						|
            <div class="smiley" id="smiley">😊</div>
 | 
						|
            <div class="counter" id="timer">000</div>
 | 
						|
        </div>
 | 
						|
        
 | 
						|
        <div class="difficulty">
 | 
						|
            <button data-level="beginner" class="active">Anfänger (9x9)</button>
 | 
						|
            <button data-level="intermediate">Fortgeschritten (16x16)</button>
 | 
						|
            <button data-level="expert">Experte (30x16)</button>
 | 
						|
        </div>
 | 
						|
        
 | 
						|
        <div class="minesweeper-board" id="board"></div>
 | 
						|
    </div>
 | 
						|
    
 | 
						|
    <div class="instructions">
 | 
						|
        <h3>Anleitung:</h3>
 | 
						|
        <p><strong>Ziel des Spiels:</strong> Finde alle Minen auf dem Spielfeld, ohne eine zu aktivieren.</p>
 | 
						|
        <p><strong>Steuerung:</strong></p>
 | 
						|
        <ul>
 | 
						|
            <li><strong>Linksklick:</strong> Feld aufdecken</li>
 | 
						|
            <li><strong>Rechtsklick:</strong> Flagge setzen/entfernen</li>
 | 
						|
            <li><strong>Doppelklick auf aufgedecktes Feld:</strong> Umgebende Felder aufdecken, wenn entsprechende Anzahl Flaggen gesetzt ist</li>
 | 
						|
        </ul>
 | 
						|
        <p><strong>Zahlen:</strong> Zeigen an, wie viele Minen in den umliegenden 8 Feldern versteckt sind.</p>
 | 
						|
    </div>
 | 
						|
 | 
						|
    <footer>
 | 
						|
        <div>
 | 
						|
             <a href="https://tools.ponywave.de/">Zurück zur Startseite</a> | 
 | 
						|
             © <span id="currentYear"></span> Akamaru | 
 | 
						|
             Made with ❤️ by Claude
 | 
						|
        </div>
 | 
						|
    </footer>
 | 
						|
 | 
						|
    <script>
 | 
						|
        // Spielkonfiguration
 | 
						|
        const levels = {
 | 
						|
            beginner: { rows: 9, cols: 9, mines: 10 },
 | 
						|
            intermediate: { rows: 16, cols: 16, mines: 40 },
 | 
						|
            expert: { rows: 16, cols: 30, mines: 99 }
 | 
						|
        };
 | 
						|
 | 
						|
        let currentLevel = 'beginner';
 | 
						|
        let boardData = [];
 | 
						|
        let gameOver = false;
 | 
						|
        let gameStarted = false;
 | 
						|
        let timeInterval;
 | 
						|
        let startTime;
 | 
						|
        let flagCount = 0;
 | 
						|
 | 
						|
        // DOM-Elemente
 | 
						|
        const board = document.getElementById('board');
 | 
						|
        const smiley = document.getElementById('smiley');
 | 
						|
        const minesCounter = document.getElementById('mines-counter');
 | 
						|
        const timerElement = document.getElementById('timer');
 | 
						|
        const difficultyButtons = document.querySelectorAll('.difficulty button');
 | 
						|
 | 
						|
        // Event-Listener
 | 
						|
        difficultyButtons.forEach(button => {
 | 
						|
            button.addEventListener('click', (e) => {
 | 
						|
                currentLevel = e.target.dataset.level;
 | 
						|
                difficultyButtons.forEach(btn => btn.classList.remove('active'));
 | 
						|
                e.target.classList.add('active');
 | 
						|
                initGame();
 | 
						|
            });
 | 
						|
        });
 | 
						|
 | 
						|
        smiley.addEventListener('click', initGame);
 | 
						|
 | 
						|
        // Initialisieren des Spiels
 | 
						|
        function initGame() {
 | 
						|
            clearInterval(timeInterval);
 | 
						|
            gameOver = false;
 | 
						|
            gameStarted = false;
 | 
						|
            flagCount = 0;
 | 
						|
            smiley.textContent = '😊';
 | 
						|
            timerElement.textContent = '000';
 | 
						|
            
 | 
						|
            const { rows, cols, mines } = levels[currentLevel];
 | 
						|
            
 | 
						|
            // Brett erstellen
 | 
						|
            board.style.gridTemplateColumns = `repeat(${cols}, var(--cell-size))`;
 | 
						|
            board.style.gridTemplateRows = `repeat(${rows}, var(--cell-size))`;
 | 
						|
            board.innerHTML = '';
 | 
						|
            
 | 
						|
            // Zellengröße anpassen im Experten-Modus
 | 
						|
            if (currentLevel === 'expert') {
 | 
						|
                const gameContainer = document.querySelector('.game-container');
 | 
						|
                const containerWidth = gameContainer.clientWidth - 40; // Container-Breite abzüglich Padding
 | 
						|
                const cellSize = Math.max(15, Math.floor(containerWidth / cols)); // Minimalgröße 15px
 | 
						|
                document.documentElement.style.setProperty('--cell-size', `${cellSize}px`);
 | 
						|
            } else {
 | 
						|
                // Zurücksetzen auf Standardwert für andere Modi
 | 
						|
                document.documentElement.style.setProperty('--cell-size', '30px');
 | 
						|
            }
 | 
						|
            
 | 
						|
            // Minen-Counter aktualisieren
 | 
						|
            updateMinesCounter(mines);
 | 
						|
            
 | 
						|
            // Spielbrett-Daten initialisieren
 | 
						|
            boardData = Array(rows).fill().map(() => 
 | 
						|
                Array(cols).fill().map(() => ({
 | 
						|
                    isMine: false,
 | 
						|
                    isRevealed: false,
 | 
						|
                    isFlagged: false,
 | 
						|
                    neighborMines: 0
 | 
						|
                }))
 | 
						|
            );
 | 
						|
            
 | 
						|
            // Zellen erstellen
 | 
						|
            for (let row = 0; row < rows; row++) {
 | 
						|
                for (let col = 0; col < cols; col++) {
 | 
						|
                    const cell = document.createElement('div');
 | 
						|
                    cell.className = 'cell';
 | 
						|
                    cell.dataset.row = row;
 | 
						|
                    cell.dataset.col = col;
 | 
						|
                    
 | 
						|
                    cell.addEventListener('click', handleCellClick);
 | 
						|
                    cell.addEventListener('contextmenu', handleRightClick);
 | 
						|
                    cell.addEventListener('dblclick', handleDoubleClick);
 | 
						|
                    
 | 
						|
                    board.appendChild(cell);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Minen platzieren
 | 
						|
        function placeMines(firstClickRow, firstClickCol) {
 | 
						|
            const { rows, cols, mines } = levels[currentLevel];
 | 
						|
            let minesPlaced = 0;
 | 
						|
            
 | 
						|
            while (minesPlaced < mines) {
 | 
						|
                const row = Math.floor(Math.random() * rows);
 | 
						|
                const col = Math.floor(Math.random() * cols);
 | 
						|
                
 | 
						|
                // Nicht auf die erste Klick-Position oder wo bereits eine Mine ist
 | 
						|
                if ((row !== firstClickRow || col !== firstClickCol) && !boardData[row][col].isMine) {
 | 
						|
                    boardData[row][col].isMine = true;
 | 
						|
                    minesPlaced++;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            // Nachbarn-Minen-Zähler berechnen
 | 
						|
            for (let row = 0; row < rows; row++) {
 | 
						|
                for (let col = 0; col < cols; col++) {
 | 
						|
                    if (!boardData[row][col].isMine) {
 | 
						|
                        boardData[row][col].neighborMines = countNeighborMines(row, col);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Nachbarn-Minen zählen
 | 
						|
        function countNeighborMines(row, col) {
 | 
						|
            const { rows, cols } = levels[currentLevel];
 | 
						|
            let count = 0;
 | 
						|
            
 | 
						|
            for (let r = Math.max(0, row - 1); r <= Math.min(rows - 1, row + 1); r++) {
 | 
						|
                for (let c = Math.max(0, col - 1); c <= Math.min(cols - 1, col + 1); c++) {
 | 
						|
                    if ((r !== row || c !== col) && boardData[r][c].isMine) {
 | 
						|
                        count++;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            return count;
 | 
						|
        }
 | 
						|
 | 
						|
        // Zellen-Klick behandeln
 | 
						|
        function handleCellClick(e) {
 | 
						|
            if (gameOver) return;
 | 
						|
            
 | 
						|
            const row = parseInt(e.target.dataset.row);
 | 
						|
            const col = parseInt(e.target.dataset.col);
 | 
						|
            
 | 
						|
            // Erster Klick initialisiert das Spiel
 | 
						|
            if (!gameStarted) {
 | 
						|
                gameStarted = true;
 | 
						|
                startTimer();
 | 
						|
                placeMines(row, col);
 | 
						|
            }
 | 
						|
            
 | 
						|
            // Nicht auf eine Flagge klicken
 | 
						|
            if (boardData[row][col].isFlagged) return;
 | 
						|
            
 | 
						|
            // Bei Minen-Klick Game Over
 | 
						|
            if (boardData[row][col].isMine) {
 | 
						|
                revealMines();
 | 
						|
                gameOver = true;
 | 
						|
                clearInterval(timeInterval);
 | 
						|
                smiley.textContent = '😵';
 | 
						|
                e.target.classList.add('mine-clicked');
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            
 | 
						|
            // Zelle aufdecken
 | 
						|
            revealCell(row, col);
 | 
						|
            
 | 
						|
            // Prüfen auf Sieg
 | 
						|
            checkWin();
 | 
						|
        }
 | 
						|
 | 
						|
        // Rechtsklick behandeln (Flagge setzen)
 | 
						|
        function handleRightClick(e) {
 | 
						|
            e.preventDefault();
 | 
						|
            if (gameOver || !gameStarted) return;
 | 
						|
            
 | 
						|
            const row = parseInt(e.target.dataset.row);
 | 
						|
            const col = parseInt(e.target.dataset.col);
 | 
						|
            
 | 
						|
            // Nur nicht aufgedeckte Zellen flaggen
 | 
						|
            if (boardData[row][col].isRevealed) return;
 | 
						|
            
 | 
						|
            const cell = e.target;
 | 
						|
            
 | 
						|
            if (boardData[row][col].isFlagged) {
 | 
						|
                // Flagge entfernen
 | 
						|
                boardData[row][col].isFlagged = false;
 | 
						|
                cell.classList.remove('flagged');
 | 
						|
                flagCount--;
 | 
						|
            } else {
 | 
						|
                // Flagge setzen
 | 
						|
                boardData[row][col].isFlagged = true;
 | 
						|
                cell.classList.add('flagged');
 | 
						|
                flagCount++;
 | 
						|
            }
 | 
						|
            
 | 
						|
            // Minen-Counter aktualisieren
 | 
						|
            updateMinesCounter(levels[currentLevel].mines - flagCount);
 | 
						|
        }
 | 
						|
 | 
						|
        // Doppelklick behandeln (Nachbarn aufdecken)
 | 
						|
        function handleDoubleClick(e) {
 | 
						|
            if (gameOver || !gameStarted) return;
 | 
						|
            
 | 
						|
            const row = parseInt(e.target.dataset.row);
 | 
						|
            const col = parseInt(e.target.dataset.col);
 | 
						|
            
 | 
						|
            // Nur für aufgedeckte Zellen mit Zahlen
 | 
						|
            if (!boardData[row][col].isRevealed || boardData[row][col].neighborMines === 0) return;
 | 
						|
            
 | 
						|
            const { rows, cols } = levels[currentLevel];
 | 
						|
            let flagCount = 0;
 | 
						|
            
 | 
						|
            // Zählen der Flaggen in der Umgebung
 | 
						|
            for (let r = Math.max(0, row - 1); r <= Math.min(rows - 1, row + 1); r++) {
 | 
						|
                for (let c = Math.max(0, col - 1); c <= Math.min(cols - 1, col + 1); c++) {
 | 
						|
                    if (boardData[r][c].isFlagged) {
 | 
						|
                        flagCount++;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            // Wenn die Anzahl der Flaggen mit der Zahl übereinstimmt, Nachbarn aufdecken
 | 
						|
            if (flagCount === boardData[row][col].neighborMines) {
 | 
						|
                for (let r = Math.max(0, row - 1); r <= Math.min(rows - 1, row + 1); r++) {
 | 
						|
                    for (let c = Math.max(0, col - 1); c <= Math.min(cols - 1, col + 1); c++) {
 | 
						|
                        if (!boardData[r][c].isRevealed && !boardData[r][c].isFlagged) {
 | 
						|
                            // Simuliere einen Klick auf die Zelle
 | 
						|
                            const cellElement = document.querySelector(`.cell[data-row="${r}"][data-col="${c}"]`);
 | 
						|
                            if (cellElement) {
 | 
						|
                                cellElement.click();
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Zelle aufdecken
 | 
						|
        function revealCell(row, col) {
 | 
						|
            const { rows, cols } = levels[currentLevel];
 | 
						|
            
 | 
						|
            // Bereits aufgedeckt oder geflaggt überspringen
 | 
						|
            if (boardData[row][col].isRevealed || boardData[row][col].isFlagged) return;
 | 
						|
            
 | 
						|
            // Zelle als aufgedeckt markieren
 | 
						|
            boardData[row][col].isRevealed = true;
 | 
						|
            
 | 
						|
            // DOM aktualisieren
 | 
						|
            const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
 | 
						|
            cell.classList.add('revealed');
 | 
						|
            
 | 
						|
            // Nachbarn-Anzahl anzeigen wenn > 0
 | 
						|
            if (boardData[row][col].neighborMines > 0) {
 | 
						|
                cell.textContent = boardData[row][col].neighborMines;
 | 
						|
                cell.classList.add(`number-${boardData[row][col].neighborMines}`);
 | 
						|
            } else {
 | 
						|
                // Bei 0 Nachbarn automatisch alle angrenzenden Zellen aufdecken
 | 
						|
                for (let r = Math.max(0, row - 1); r <= Math.min(rows - 1, row + 1); r++) {
 | 
						|
                    for (let c = Math.max(0, col - 1); c <= Math.min(cols - 1, col + 1); c++) {
 | 
						|
                        if (r !== row || c !== col) {
 | 
						|
                            revealCell(r, c);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Alle Minen aufdecken (bei Game Over)
 | 
						|
        function revealMines() {
 | 
						|
            const { rows, cols } = levels[currentLevel];
 | 
						|
            
 | 
						|
            for (let row = 0; row < rows; row++) {
 | 
						|
                for (let col = 0; col < cols; col++) {
 | 
						|
                    if (boardData[row][col].isMine) {
 | 
						|
                        const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
 | 
						|
                        cell.classList.add('revealed', 'mine');
 | 
						|
                    } else if (boardData[row][col].isFlagged) {
 | 
						|
                        // Falsch platzierte Flaggen markieren
 | 
						|
                        const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
 | 
						|
                        cell.classList.add('revealed');
 | 
						|
                        cell.classList.add('wrong-flag');
 | 
						|
                        cell.textContent = '❌';
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Prüfen, ob das Spiel gewonnen wurde
 | 
						|
        function checkWin() {
 | 
						|
            const { rows, cols, mines } = levels[currentLevel];
 | 
						|
            let revealedCount = 0;
 | 
						|
            
 | 
						|
            for (let row = 0; row < rows; row++) {
 | 
						|
                for (let col = 0; col < cols; col++) {
 | 
						|
                    if (boardData[row][col].isRevealed) {
 | 
						|
                        revealedCount++;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            // Gewonnen, wenn alle Nicht-Minen-Zellen aufgedeckt sind
 | 
						|
            if (revealedCount === (rows * cols - mines)) {
 | 
						|
                gameOver = true;
 | 
						|
                clearInterval(timeInterval);
 | 
						|
                smiley.textContent = '😎';
 | 
						|
                
 | 
						|
                // Alle Minen automatisch flaggen
 | 
						|
                for (let row = 0; row < rows; row++) {
 | 
						|
                    for (let col = 0; col < cols; col++) {
 | 
						|
                        if (boardData[row][col].isMine && !boardData[row][col].isFlagged) {
 | 
						|
                            boardData[row][col].isFlagged = true;
 | 
						|
                            const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
 | 
						|
                            cell.classList.add('flagged');
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                
 | 
						|
                // Minen-Counter auf 0 setzen
 | 
						|
                updateMinesCounter(0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Timer starten
 | 
						|
        function startTimer() {
 | 
						|
            startTime = Date.now();
 | 
						|
            timeInterval = setInterval(() => {
 | 
						|
                const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000);
 | 
						|
                // Maximale Anzeige: 999 Sekunden
 | 
						|
                const displayTime = Math.min(elapsedSeconds, 999);
 | 
						|
                timerElement.textContent = displayTime.toString().padStart(3, '0');
 | 
						|
            }, 1000);
 | 
						|
        }
 | 
						|
 | 
						|
        // Minen-Counter aktualisieren
 | 
						|
        function updateMinesCounter(count) {
 | 
						|
            minesCounter.textContent = count.toString().padStart(3, '0');
 | 
						|
        }
 | 
						|
 | 
						|
        // Dark Mode
 | 
						|
        function toggleTheme() {
 | 
						|
            document.body.classList.toggle('dark-mode');
 | 
						|
            const btn = document.querySelector('.theme-toggle');
 | 
						|
            btn.textContent = document.body.classList.contains('dark-mode') ? '☀️' : '🌙';
 | 
						|
            
 | 
						|
            // Speichern der Präferenz
 | 
						|
            const isDark = document.body.classList.contains('dark-mode');
 | 
						|
            localStorage.setItem('theme', isDark ? 'dark' : 'light');
 | 
						|
        }
 | 
						|
 | 
						|
        // Theme initialisieren
 | 
						|
        function initTheme() {
 | 
						|
            const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
 | 
						|
            const savedTheme = localStorage.getItem('theme');
 | 
						|
            
 | 
						|
            if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
 | 
						|
                document.body.classList.add('dark-mode');
 | 
						|
                document.querySelector('.theme-toggle').textContent = '☀️';
 | 
						|
            }
 | 
						|
            
 | 
						|
            // Jahr aktualisieren
 | 
						|
            document.getElementById('currentYear').textContent = new Date().getFullYear();
 | 
						|
        }
 | 
						|
 | 
						|
        // Kontextmenü für rechte Maustaste verhindern
 | 
						|
        board.addEventListener('contextmenu', e => e.preventDefault());
 | 
						|
 | 
						|
        // Beim Laden ausführen
 | 
						|
        initTheme();
 | 
						|
        initGame();
 | 
						|
 | 
						|
        // Bei Resize Fenster die Zellengröße anpassen
 | 
						|
        window.addEventListener('resize', () => {
 | 
						|
            if (currentLevel === 'expert') {
 | 
						|
                const gameContainer = document.querySelector('.game-container');
 | 
						|
                const containerWidth = gameContainer.clientWidth - 40;
 | 
						|
                const cellSize = Math.max(15, Math.floor(containerWidth / levels.expert.cols)); // Minimalgröße 15px
 | 
						|
                document.documentElement.style.setProperty('--cell-size', `${cellSize}px`);
 | 
						|
            }
 | 
						|
        });
 | 
						|
    </script>
 | 
						|
</body>
 | 
						|
</html>  |