403Webshell
Server IP : 119.36.225.67  /  Your IP : 43.159.78.123
Web Server : nginx/1.28.0
System : Linux 1763701629066 6.8.0-53-generic #55-Ubuntu SMP PREEMPT_DYNAMIC Fri Jan 17 15:37:52 UTC 2025 x86_64
User : www ( 1001)
PHP Version : 8.2.28
Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /www/wwwroot/www.lengcat.cn/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /www/wwwroot/www.lengcat.cn/saolei.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>经典扫雷 - 自动翻开周边</title>
    <style>
        :root {
            --bg-color: #f0f0f0;
            --board-bg: #ccc;
            --cell-bg: #ddd;
            --cell-revealed: #fff;
            --text-color: #333;
            --btn-bg: #fff;
            --btn-active-bg: #007acc;
        }
        .night-mode {
            --bg-color: #1a1a1a;
            --board-bg: #444;
            --cell-bg: #555;
            --cell-revealed: #333;
            --text-color: #eee;
            --btn-bg: #333;
            --btn-active-bg: #005a9e;
        }
        * { box-sizing: border-box; margin: 0; padding: 0; user-select: none; -webkit-user-select: none; }
        body { 
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 
            background: var(--bg-color); 
            color: var(--text-color);
            display: flex; 
            flex-direction: column;
            justify-content: center; 
            align-items: center; 
            min-height: 100vh;
            transition: background 0.3s, color 0.3s;
            padding: 10px;
        }
        .container { text-align: center; width: 100%; max-width: 100%; }
        h1 { margin-bottom: 10px; font-size: 1.5rem; }
        
        .controls { 
            margin-bottom: 15px; 
            display: flex; 
            flex-wrap: wrap; 
            justify-content: center; 
            gap: 8px; 
            align-items: center;
        }
        button { 
            padding: 6px 12px; 
            cursor: pointer; 
            background: var(--btn-bg); 
            border: 1px solid var(--board-bg); 
            border-radius: 4px; 
            color: var(--text-color);
            font-size: 0.9rem;
            transition: all 0.2s;
        }
        button:hover { opacity: 0.8; }
        button.active { background: var(--btn-active-bg); color: white; border-color: var(--btn-active-bg); }
        
        .custom-input { width: 50px; padding: 5px; border: 1px solid var(--board-bg); border-radius: 4px; background: var(--btn-bg); color: var(--text-color); text-align: center;}
        .switch-label { display: flex; align-items: center; gap: 5px; cursor: pointer; font-size: 0.9rem; padding: 0 5px;}
        .switch-label input { cursor: pointer; }

        .status-bar { 
            display: flex; 
            justify-content: space-between; 
            align-items: center; 
            margin-bottom: 10px; 
            padding: 0 5px;
            font-weight: bold; 
            font-size: 1.2rem;
            font-family: 'Courier New', monospace;
        }
        .face-btn { font-size: 1.5rem; cursor: pointer; background: none; border: none; padding: 0; line-height: 1;}

        .board { 
            display: inline-grid; 
            gap: 1px; 
            background: var(--board-bg); 
            padding: 5px; 
            border-radius: 5px; 
            margin: 0 auto;
            touch-action: manipulation;
        }
        .cell { 
            width: 30px; height: 30px; 
            background: var(--cell-bg); 
            display: flex; justify-content: center; align-items: center; 
            font-weight: bold; font-size: 1rem;
            cursor: pointer; 
            transition: background 0.1s;
        }
        .cell:active { background: var(--board-bg); }
        .cell.revealed { background: var(--cell-revealed); cursor: default; }
        .cell.flag::before { content: '🚩'; font-size: 1.1rem; }
        .cell.question::before { content: '?'; color: #888; }
        .cell.mine { background: #ffcccc; }
        .cell.mine::before { content: '💣'; }
        .cell.wrong-flag { background: #ffcccc; }
        .cell.wrong-flag::before { content: '❌'; }

        .c1 { color: blue; } .c2 { color: green; } .c3 { color: red; } .c4 { color: darkblue; }
        .c5 { color: maroon; } .c6 { color: teal; } .c7 { color: black; } .c8 { color: gray; }
        .night-mode .c7 { color: #ccc; }

        @media (max-width: 600px) {
            .cell { width: 26px; height: 26px; font-size: 0.85rem; }
            .controls { gap: 5px; }
            button { padding: 5px 8px; font-size: 0.8rem; }
        }
        .chord-hint {
        opacity: 0.3;
        transform: scale(0.9);
    }
    .c1 { color: blue; }
    .c2 { color: green; }
    .c3 { color: red; }
    .c4 { color: darkblue; }
    .c5 { color: darkred; }
    </style>
</head>
<body>
    <div class="container">
        <h1>💣 扫雷</h1>
        
        <div class="controls">
            <button onclick="game.setDifficulty(9,9,10)" id="btn-b">基础</button>
            <button onclick="game.setDifficulty(16,16,40)" id="btn-i">中级</button>
            <button onclick="game.setDifficulty(16,30,99)" id="btn-e">专家</button>
            <button onclick="game.setFullscreen()" id="btn-f">满屏</button>
            <div style="display:flex; gap:4px; align-items:center;">
                <input type="number" id="c-w" class="custom-input" value="20" min="5" max="50">
                <span>×</span>
                <input type="number" id="c-h" class="custom-input" value="20" min="5" max="50">
                <input type="number" id="c-m" class="custom-input" value="60" min="1">
                <button onclick="game.applyCustom()">GO</button>
            </div>
            <label class="switch-label">
                <input type="checkbox" id="auto-flag-toggle" checked> 自动标雷
            </label>
            <label class="switch-label">
                <input type="checkbox" id="night-toggle"> 🌙
            </label>
        </div>

        <div class="status-bar">
            <span id="mine-count">010</span>
            <button class="face-btn" id="face" onclick="game.restart()">😀</button>
            <span id="timer">000</span>
        </div>

        <div class="board" id="board"></div>
    </div>

<script>
class Minesweeper {
    constructor() {
        this.rows = 9;
        this.cols = 9;
        this.mines = 10;
        this.board = [];
        this.state = [];
        this.gameOver = false;
        this.firstClick = true;
        this.startTime = 0;
        this.timerInterval = null;
        this.flagCount = 0;
        this.revealedCount = 0;
        
        // 专业难度雷密度:99 / (16 * 30) ≈ 0.20625
        this.expertDensity = 99 / (16 * 30);
        
        this.boardEl = document.getElementById('board');
        this.mineCountEl = document.getElementById('mine-count');
        this.timerEl = document.getElementById('timer');
        this.faceEl = document.getElementById('face');
        this.autoFlagEl = document.getElementById('auto-flag-toggle');
        
        document.getElementById('night-toggle').addEventListener('change', (e) => {
            document.body.classList.toggle('night-mode', e.target.checked);
        });

        this.setDifficulty(9, 9, 10);
    }

    setDifficulty(r, c, m) {
        this.rows = r; this.cols = c; this.mines = m;
        this.updateActiveBtn();
        this.restart();
    }

    applyCustom() {
        const w = parseInt(document.getElementById('c-w').value) || 9;
        const h = parseInt(document.getElementById('c-h').value) || 9;
        const m = parseInt(document.getElementById('c-m').value) || 10;
        if (m >= w * h) { alert("地雷太多啦!"); return; }
        this.setDifficulty(h, w, m);
    }

    /**
     * 满屏模式:根据屏幕尺寸自动计算行列数,保持专家难度雷密度
     */
    setFullscreen() {
        // 获取可用屏幕尺寸(减去控制栏、状态栏等高度)
        const availableWidth = window.innerWidth - 20;
        const availableHeight = window.innerHeight - 200;
        
        // 最小格子尺寸
        const minCellSize = 16;
        const maxCellSize = 40;
        
        // 估算一个合适的格子尺寸
        let cellSize = Math.floor(Math.min(
            availableWidth / 40,  // 最多30列
            availableHeight / 24, // 最多16行
            maxCellSize
        ));
        cellSize = Math.max(cellSize, minCellSize);
        
        // 根据格子尺寸计算行列数
        let cols = Math.floor(availableWidth / cellSize);
        let rows = Math.floor(availableHeight / cellSize);
        
        // 限制最小行列数
        cols = Math.max(cols, 10);
        rows = Math.max(rows, 10);
        
        // 根据屏幕宽高比调整(如果宽屏,增加列数;如果竖屏,增加行数)
        const aspectRatio = availableWidth / availableHeight;
        if (aspectRatio > 1.5) {
            // 宽屏,增加列数,减少行数
            cols = Math.min(cols + 5, Math.floor(availableWidth / minCellSize));
            rows = Math.max(Math.floor(cols / aspectRatio), 10);
        } else if (aspectRatio < 0.7) {
            // 竖屏,增加行数,减少列数
            rows = Math.min(rows + 5, Math.floor(availableHeight / minCellSize));
            cols = Math.max(Math.floor(rows * aspectRatio), 10);
        }
        
        // 计算地雷数(保持专家难度密度)
        const totalCells = rows * cols;
        const mines = Math.floor(totalCells * this.expertDensity);
        
        this.setDifficulty(rows, cols, mines);
        this.updateActiveBtn();
    }

    updateActiveBtn() {
        document.querySelectorAll('.controls button').forEach(b => b.classList.remove('active'));
        if (this.rows===9 && this.cols===9 && this.mines===10) document.getElementById('btn-b').classList.add('active');
        else if (this.rows===16 && this.cols===16 && this.mines===40) document.getElementById('btn-i').classList.add('active');
        else if (this.rows===16 && this.cols===30 && this.mines===99) document.getElementById('btn-e').classList.add('active');
        // 满屏模式不标记active,因为行列数是动态的
    }

    restart() {
        clearInterval(this.timerInterval);
        this.board = Array(this.rows).fill().map(() => Array(this.cols).fill(0));
        this.state = Array(this.rows).fill().map(() => Array(this.cols).fill(0));
        this.gameOver = false;
        this.firstClick = true;
        this.flagCount = 0;
        this.revealedCount = 0;
        
        this.faceEl.textContent = '😀';
        this.updateMineCounter();
        this.timerEl.textContent = '000';
        this.renderBoard();
    }

    initMines(safeR, safeC) {
        let placed = 0;
        const safeZone = new Set();
        for(let dr=-1; dr<=1; dr++) {
            for(let dc=-1; dc<=1; dc++) {
                safeZone.add(`${safeR+dr},${safeC+dc}`);
            }
        }

        while (placed < this.mines) {
            const r = Math.floor(Math.random() * this.rows);
            const c = Math.floor(Math.random() * this.cols);
            if (this.board[r][c] === -1) continue;
            if (safeZone.has(`${r},${c}`)) continue;
            
            this.board[r][c] = -1;
            placed++;
        }

        for (let r = 0; r < this.rows; r++) {
            for (let c = 0; c < this.cols; c++) {
                if (this.board[r][c] === -1) continue;
                let count = 0;
                for (let dr = -1; dr <= 1; dr++) {
                    for (let dc = -1; dc <= 1; dc++) {
                        const nr = r + dr, nc = c + dc;
                        if (nr >= 0 && nr < this.rows && nc >= 0 && nc < this.cols && this.board[nr][nc] === -1) count++;
                    }
                }
                this.board[r][c] = count;
            }
        }
    }

    renderBoard() {
        this.boardEl.innerHTML = '';
        this.boardEl.style.gridTemplateColumns = `repeat(${this.cols}, 1fr)`;
        
        // 动态调整格子尺寸以适应屏幕
        const availableWidth = window.innerWidth - 40;
        const availableHeight = window.innerHeight - 250;
        const cellSize = Math.min(
            Math.floor(availableWidth / this.cols),
            Math.floor(availableHeight / this.rows),
            40
        );
        const finalCellSize = Math.max(cellSize, 20);
        
        for (let r = 0; r < this.rows; r++) {
            for (let c = 0; c < this.cols; c++) {
                const cell = document.createElement('div');
                cell.className = 'cell';
                cell.dataset.r = r;
                cell.dataset.c = c;
                cell.style.width = `${finalCellSize}px`;
                cell.style.height = `${finalCellSize}px`;
                cell.style.fontSize = `${Math.max(finalCellSize * 0.6, 12)}px`;

                cell.onmousedown = (e) => {
                    if (this.gameOver) return;
                    if (e.button === 0) this.faceEl.textContent = '😮';
                };
                cell.onmouseup = (e) => {
                    if (this.gameOver) return;
                    this.faceEl.textContent = '😀';
                };
                cell.oncontextmenu = (e) => { e.preventDefault(); this.handleRightClick(r, c); };
                cell.onclick = (e) => { if(e.button===0) this.handleClick(r, c); };

                let pressTimer;
                cell.ontouchstart = (e) => {
                    if (this.gameOver) return;
                    pressTimer = setTimeout(() => {
                        this.handleRightClick(r, c);
                        pressTimer = null;
                    }, 400);
                };
                cell.ontouchend = (e) => {
                    if (pressTimer) {
                        e.preventDefault();
                        this.handleClick(r, c);
                    }
                };
                cell.ontouchmove = () => clearTimeout(pressTimer);

                this.boardEl.appendChild(cell);
            }
        }
    }

    getCellEl(r, c) {
        return this.boardEl.querySelector(`[data-r="${r}"][data-c="${c}"]`);
    }

    updateCellUI(r, c) {
        const el = this.getCellEl(r, c);
        if (!el) return;
        
        el.className = 'cell';
        el.textContent = '';

        const s = this.state[r][c];
        const v = this.board[r][c];

        if (s === 1) {
            el.classList.add('revealed');
            if (v === -1) {
                el.classList.add('mine');
            } else if (v > 0) {
                el.textContent = v;
                el.classList.add(`c${v}`);
            }
        } else if (s === 2) {
            el.classList.add('flag');
        } else if (s === 3) {
            el.classList.add('question');
        }
    }

    handleClick(r, c) {
        if (this.gameOver) return;
        const s = this.state[r][c];
        
        // 如果点击的是已翻开的数字格子,尝试和弦操作(自动翻开周边)
        if (s === 1 && this.board[r][c] > 0) {
            this.chordOpen(r, c);
            return;
        }
        
        // 如果点击的是隐藏格子或问号格子
        if (s === 2) return; // 旗子不能点

        if (this.firstClick) {
            this.firstClick = false;
            this.initMines(r, c);
            this.startTimer();
        }

        if (this.board[r][c] === -1) {
            this.lose(r, c);
            return;
        }

        this.reveal(r, c);
        
        if (this.autoFlagEl.checked) {
            this.globalAutoFlag();
        }
        
        this.checkWin();
    }

    /**
     * 和弦操作:当数字周围旗子数等于数字时,自动翻开周围未翻开的格子
     */
    chordOpen(r, c) {
        const val = this.board[r][c];
        let flagCountAround = 0;
        const hiddenCells = [];

        // 统计周围旗子数和隐藏格子
        for (let dr = -1; dr <= 1; dr++) {
            for (let dc = -1; dc <= 1; dc++) {
                if (dr === 0 && dc === 0) continue;
                const nr = r + dr, nc = c + dc;
                if (nr < 0 || nr >= this.rows || nc < 0 || nc >= this.cols) continue;
                
                const s = this.state[nr][nc];
                if (s === 2) {
                    flagCountAround++;
                } else if (s === 0 || s === 3) {
                    hiddenCells.push({r: nr, c: nc});
                }
            }
        }

        // 只有当周围旗子数等于数字时,才触发自动翻开
        if (flagCountAround === val && hiddenCells.length > 0) {
            let hitMine = false;
            let hitR, hitC;

            hiddenCells.forEach(pos => {
                if (this.board[pos.r][pos.c] === -1) {
                    hitMine = true;
                    hitR = pos.r;
                    hitC = pos.c;
                } else {
                    this.reveal(pos.r, pos.c);
                }
            });

            if (hitMine) {
                this.lose(hitR, hitC);
                return;
            }

            if (this.autoFlagEl.checked) {
                this.globalAutoFlag();
            }
            
            this.checkWin();
        }
    }

    handleRightClick(r, c) {
        if (this.gameOver) return;
        const s = this.state[r][c];
        if (s === 1) return;

        if (s === 0) this.state[r][c] = 2;
        else if (s === 2) this.state[r][c] = 3;
        else if (s === 3) this.state[r][c] = 0;

        this.flagCount += (this.state[r][c] === 2 ? 1 : (s === 2 ? -1 : 0));
        this.updateMineCounter();
        this.updateCellUI(r, c);
    }

    reveal(r, c) {
        if (r < 0 || r >= this.rows || c < 0 || c >= this.cols) return;
        if (this.state[r][c] !== 0) return;

        this.state[r][c] = 1;
        this.revealedCount++;
        this.updateCellUI(r, c);

        if (this.board[r][c] === 0) {
            for (let dr = -1; dr <= 1; dr++) {
                for (let dc = -1; dc <= 1; dc++) {
                    if (dr === 0 && dc === 0) continue;
                    this.reveal(r + dr, c + dc);
                }
            }
        }
    }

    globalAutoFlag() {
        let changed = true;
        while (changed) {
            changed = false;
            const toFlag = [];

            for (let r = 0; r < this.rows; r++) {
                for (let c = 0; c < this.cols; c++) {
                    if (this.state[r][c] !== 1 || this.board[r][c] <= 0) continue;

                    const val = this.board[r][c];
                    let hiddenCount = 0;
                    let flagCountAround = 0;
                    const hiddenCells = [];

                    for (let dr = -1; dr <= 1; dr++) {
                        for (let dc = -1; dc <= 1; dc++) {
                            if (dr === 0 && dc === 0) continue;
                            const nr = r + dr, nc = c + dc;
                            if (nr < 0 || nr >= this.rows || nc < 0 || nc >= this.cols) continue;
                            
                            const s = this.state[nr][nc];
                            if (s === 0 || s === 3) {
                                hiddenCount++;
                                hiddenCells.push({r: nr, c: nc});
                            } else if (s === 2) {
                                flagCountAround++;
                            }
                        }
                    }

                    const remainingMines = val - flagCountAround;
                    
                    if (hiddenCount > 0 && hiddenCount === remainingMines) {
                        hiddenCells.forEach(pos => {
                            if (this.state[pos.r][pos.c] !== 2 && !toFlag.some(p => p.r === pos.r && p.c === pos.c)) {
                                toFlag.push(pos);
                            }
                        });
                    }
                }
            }

            if (toFlag.length > 0) {
                toFlag.forEach(pos => {
                    this.state[pos.r][pos.c] = 2;
                    this.flagCount++;
                    this.updateCellUI(pos.r, pos.c);
                });
                this.updateMineCounter();
                changed = true;
            }
        }
    }

    lose(hitR, hitC) {
        this.gameOver = true;
        clearInterval(this.timerInterval);
        this.faceEl.textContent = '😵';
        
        for (let r = 0; r < this.rows; r++) {
            for (let c = 0; c < this.cols; c++) {
                if (this.board[r][c] === -1 && this.state[r][c] !== 2) {
                    this.state[r][c] = 1;
                    this.updateCellUI(r, c);
                }
                if (this.board[r][c] !== -1 && this.state[r][c] === 2) {
                    const el = this.getCellEl(r, c);
                    el.classList.remove('flag');
                    el.classList.add('wrong-flag');
                }
            }
        }
        const hitEl = this.getCellEl(hitR, hitC);
        hitEl.style.background = '#ff0000';
    }

    checkWin() {
        if (this.revealedCount === this.rows * this.cols - this.mines) {
            this.gameOver = true;
            clearInterval(this.timerInterval);
            this.faceEl.textContent = '😎';
            for(let r=0; r<this.rows; r++) {
                for(let c=0; c<this.cols; c++) {
                    if(this.state[r][c] === 0 && this.board[r][c] === -1) {
                        this.state[r][c] = 2;
                        this.flagCount++;
                        this.updateCellUI(r, c);
                    }
                }
            }
            this.updateMineCounter();
        }
    }

    startTimer() {
        this.startTime = Date.now();
        this.timerInterval = setInterval(() => {
            const t = Math.floor((Date.now() - this.startTime) / 1000);
            this.timerEl.textContent = String(Math.min(t, 999)).padStart(3, '0');
        }, 1000);
    }

    updateMineCounter() {
        const left = this.mines - this.flagCount;
        this.mineCountEl.textContent = String(Math.max(-99, Math.min(999, left))).padStart(3, '0');
    }
}

const game = new Minesweeper();
</script>
</body>
</html>

Youez - 2016 - github.com/yon3zu
LinuXploit