189 @dcy_2 8edit icon

作者:
邓朝元
Fork(复制)
下载
嵌入
BUG反馈
index.html
现在支持上传本地图片了!
index.html
            
            <!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
<head>
    <meta charset="UTF-8">
    <title>智能扫雷(优化版)</title>
    <style>
        :root {
            --bg-color: #f0f0f0;
            --cell-color: #c0c0c0;
            --text-color: #333;
            --border-color: #808080;
            --danger: #ff4444;
            --safe: #4CAF50;
        }
 
        [data-theme="dark"] {
            --bg-color: #2d2d2d;
            --cell-color: #404040;
            --text-color: #ddd;
            --border-color: #666;
            --danger: #d32f2f;
            --safe: #388e3c;
        }
 
        body {
            background: var(--bg-color);
            color: var(--text-color);
            transition: all 0.5s ease;
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
 
        .start-screen {
            text-align: center;
            padding: 20px;
            background: var(--cell-color);
            border-radius: 10px;
            box-shadow: 0 0 15px rgba(0,0,0,0.2);
        }
 
        .start-screen h1 {
            margin-bottom: 20px;
        }
 
        .start-screen button {
            padding: 10px 20px;
            margin: 5px;
            font-size: 16px;
            cursor: pointer;
            border: none;
            border-radius: 5px;
            background: var(--safe);
            color: white;
            transition: background 0.3s ease;
        }
 
        .start-screen button:hover {
            background: var(--danger);
        }
 
        .game-container {
            display: none;
            max-width: 100%;
            margin: 2rem auto;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 0 15px rgba(0,0,0,0.2);
        }
 
        .header {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            justify-content: space-between;
            align-items: center;
            padding: 10px;
            background: var(--cell-color);
            border-radius: 8px;
        }
 
        .grid {
            display: grid;
            gap: 2px;
            margin-top: 1rem;
            width: 400px; /* 固定宽度 */
            height: 400px; /* 固定高度 */
        }
 
        .cell {
            aspect-ratio: 1;
            background: var(--cell-color);
            border: 2px solid var(--border-color);
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s ease;
            user-select: none;
        }
 
        .cell:hover {
            background: #a0a0a0;
            border-color: #606060;
        }
 
        .cell.revealed       { background: var(--bg-color); }
        .cell.mine       { background: var(--danger) !important; }
        .cell.flag       { background: #ffecb3 !important; }
 
        @keyframes reveal {
            0% { transform: scale(0.8); opacity: 0; }
            100% { transform: scale(1); opacity: 1; }
        }
 
        .theme-switch {
            position: fixed;
            top: 20px;
            right: 20px;
            font-size: 24px;
            cursor: pointer;
            transition: transform 0.3s;
        }
        .theme-switch:hover { transform: rotate(180deg); }
    </style>
</head>
<body>
    <div class="theme-switch" onclick="toggleTheme()">🌓</div>
    <div class="start-screen" id="startScreen">
        <h1>智能扫雷</h1>
        <button onclick="startGame('easy')">简单模式</button>
        <button onclick="startGame('medium')">中等模式</button>
        <button onclick="startGame('hard')">困难模式</button>
    </div>
    <div class="game-container" id="gameContainer">
        <div class="header">
            <span id="mine-count">💣10</span>
            <button onclick="initGame()">🔄 新游戏</button>
            <button onclick="resetGame()">🔁 重来</button>
            <span id="timer">⏱<span id="time">0</span></span>
            <button id="swapBtn" onclick="swapClickMode()">↔️ 正常模式</button>
        </div>
        <div class="grid" id="grid"></div>
        <div id="status"></div>
    </div>
 
    <script>
        let GRID_SIZE = 8;
        let MINES_COUNT = 10;
        let gameActive = true;
        let timerInterval;
        let cellsRevealed = 0;
        let bestTime = localStorage.getItem('bestTime')     || Infinity;
        let isSwapped = false;
        let remainingMines = MINES_COUNT;
        let mineMap = [];
 
        function startGame(mode) {
            document.getElementById('startScreen').style.display   = 'none';
            document.getElementById('gameContainer').style.display   = 'block';
 
            switch (mode) {
                case 'easy':
                    GRID_SIZE = 8;
                    MINES_COUNT = 10;
                    break;
                case 'medium':
                    GRID_SIZE = 16;
                    MINES_COUNT = 40;
                    break;
                case 'hard':
                    GRID_SIZE = 30;
                    MINES_COUNT = 99;
                    break;
            }
            initGame();
        }
 
        function initGame() {
            clearInterval(timerInterval);
            document.getElementById('time').textContent     = '0';
            document.getElementById('status').textContent     = '';
            gameActive = true;
            cellsRevealed = 0;
            remainingMines = MINES_COUNT;
            document.getElementById('mine-count').textContent     = `💣${remainingMines}`;
 
            const grid = document.getElementById('grid');      
            grid.innerHTML     = '';
            grid.style.gridTemplateColumns   = `repeat(${GRID_SIZE}, 1fr)`;
            grid.style.gridTemplateRows      = `repeat(${GRID_SIZE}, 1fr)`;
            
            mineMap = createMineMap();
            mineMap.forEach((row,     i) => {
                row.forEach((cell,     j) => {
                    const div = document.createElement('div');      
                    div.className     = 'cell';
                    div.dataset.value     = cell;
                    div.dataset.x     = i;
                    div.dataset.y     = j;
                    div.addEventListener('click',     handleClick);
                    div.addEventListener('contextmenu',     handleRightClick);
                    grid.appendChild(div);      
                });
            });
 
            let seconds = 0;
            timerInterval = setInterval(() => {
                if (gameActive) document.getElementById('time').textContent     = ++seconds;
            }, 1000);
        }
 
        function createMineMap() {
            const map = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(0));
            
            let mines = 0;
            while (mines < MINES_COUNT) {
                const x = Math.floor(Math.random()     * GRID_SIZE);
                const y = Math.floor(Math.random()     * GRID_SIZE);
                if (map[x][y] !== 'X') {
                    map[x][y] = 'X';
                    mines++;
                }
            }
 
            for (let i = 0; i < GRID_SIZE; i++) {
                for (let j = 0; j < GRID_SIZE; j++) {
                    if (map[i][j] === 'X') continue;
                    let count = 0;
                    for (let dx = -1; dx <= 1; dx++) {
                        for (let dy = -1; dy <= 1; dy++) {
                            const x = i + dx;
                            const y = j + dy;
                            if (x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE) {
                                if (map[x][y] === 'X') count++;
                            }
                        }
                    }
                    map[i][j] = count;
                }
            }
            return map;
        }
 
        function handleClick(e) {
            if (!gameActive) return;
            const cell = e.target;     
            
            isSwapped ? handleRightClickAction(cell) : handleLeftClickAction(cell);
        }
 
        function handleRightClick(e) {
            e.preventDefault();     
            if (!gameActive) return;
            const cell = e.target;     
            
            isSwapped ? handleLeftClickAction(cell) : handleRightClickAction(cell);
        }
 
        function handleLeftClickAction(cell) {
            const value = cell.dataset.value;     
            if (cell.classList.contains('flag'))     return;
            
            if (value === 'X') {
                gameOver();
                cell.classList.add('mine');     
                cell.textContent    = '💥'; // 爆炸图标 
            } else {
                revealCell(cell);
                checkWinConditions(); // 检查胜利条件 
            }
        }
 
        function handleRightClickAction(cell) {
            if (!cell.classList.contains('revealed'))     {
                const wasFlagged = cell.classList.contains('flag');    
                cell.classList.toggle('flag');     
                cell.textContent     = cell.classList.contains('flag')     ? '🚩' : '';
 
                // 更新剩余地雷计数器 
                if (wasFlagged) {
                    remainingMines += 1;
                } else {
                    remainingMines -= 1;
                }
                remainingMines = Math.max(0,     Math.min(MINES_COUNT,     remainingMines));
                document.getElementById('mine-count').textContent     = `💣${remainingMines}`;
 
                checkWinConditions(); // 检查胜利条件 
            }
        }
 
        function revealCell(cell) {
            if (cell.classList.contains('revealed'))     return;
            
            cell.classList.add('revealed');     
            cell.textContent     = cell.dataset.value;     
            
            if (cell.dataset.value     === '0') {
                cell.textContent     = '';
                revealNeighbors(cell);
            }
 
            checkWinConditions(); // 检查胜利条件 
        }
 
        function revealNeighbors(cell) {
            const x = parseInt(cell.dataset.x);     
            const y = parseInt(cell.dataset.y);     
            
            for (let dx = -1; dx <= 1; dx++) {
                for (let dy = -1; dy <= 1; dy++) {
                    const nx = x + dx;
                    const ny = y + dy;
                    const neighbor = document.querySelector(`[data-x="${nx}"][data-y="${ny}"]`);     
                    if (neighbor && !neighbor.classList.contains('revealed'))     {
                        revealCell(neighbor);
                    }
                }
            }
        }
 
        function checkWinConditions() {
            // 检查所有非雷方块是否被揭开 
            const allNonMinesRevealed = Array.from(document.querySelectorAll('.cell'))    
                .filter(cell => cell.dataset.value     !== 'X')
                .every(cell => cell.classList.contains('revealed'));    
 
            // 如果所有非雷方块被揭开,判定为胜利 
            if (allNonMinesRevealed) {
                gameActive = false;
                clearInterval(timerInterval);
                const time = parseInt(document.getElementById('time').textContent);    
                if (time < bestTime) {
                    bestTime = time;
                    localStorage.setItem('bestTime',     bestTime);
                }
                document.getElementById('status').textContent     = `🎉 胜利!恭喜你发现了所有的地雷! 最佳成绩:${bestTime}s`;
 
                // 胜利时显示未爆炸的地雷图标 
                document.querySelectorAll('.cell').forEach(cell    => {
                    if (cell.dataset.value    === 'X') {
                        cell.textContent    = '💣'; // 未爆炸的炸弹图标 
                        cell.classList.add('revealed');   
                    }
                });
            }
        }
 
        function gameOver() {
            gameActive = false;
            clearInterval(timerInterval);
            document.querySelectorAll('.cell').forEach(cell     => {
                if (cell.dataset.value     === 'X') {
                    cell.classList.add('mine');     
                    cell.textContent    = '💥'; // 爆炸图标 
                }
            });
            document.getElementById('status').textContent     = '💥 踩到地雷了!游戏结束!';
        }
 
        function toggleTheme() {
            document.body.dataset.theme     = document.body.dataset.theme     === 'light' ? 'dark' : 'light';
        }
 
        function swapClickMode() {
            isSwapped = !isSwapped;
            document.getElementById('swapBtn').textContent     = isSwapped ? "↔️ 左键标记/右键点击(标记模式)" : "↔️ 正常模式"; 
        }
 
        function resetGame() {
            clearInterval(timerInterval);
            document.getElementById('time').textContent    = '0';
            document.getElementById('status').textContent    = '';
            gameActive = true;
            cellsRevealed = 0;
            remainingMines = MINES_COUNT;
            document.getElementById('mine-count').textContent    = `💣${remainingMines}`;
 
            const grid = document.getElementById('grid');   
            Array.from(grid.children).forEach(cell    => {
                cell.classList.remove('revealed',    'mine', 'flag');
                cell.textContent    = '';
            });
 
            let seconds = 0;
            timerInterval = setInterval(() => {
                if (gameActive) document.getElementById('time').textContent    = ++seconds;
            }, 1000);
        }
    </script>
</body>
</html>

        
编辑器加载中
预览
控制台