小游戏:基金会打地鼠

源页面
2025年8月1日
修订 9

核心指标

更新于 2025年11月6日
评分
212
↑ 220
↓ 8
支持率
96%
总票数 228
Wilson 95% 下界
93.2%
在相同票数下更稳健的支持率估计
争议指数
0.135

评分趋势

按周聚合
加载图表中...

最近修订

1 / 4
编辑内容
3 个月前
编辑内容
3 个月前
编辑内容
3 个月前

最近投票

1 / 23
2025-10-26
2025-10-16
2025-10-14
2025-10-05
2025-10-04
2025-09-30
2025-09-29
2025-09-23
2025-09-22
2025-09-21

页面源码

源码字符数 15422文字字数 277
[[include :scp-wiki-cn:credit:start]]
本页面由[[*user leather_boots]]与[[*user FATEfoggy]]合著,于中文分部最先发布,后翻译到基金会主站与国际站。
[[include :scp-wiki-cn:credit:end]]

这是一个网页小游戏,规则很简单。洞里面会出现Bright博士,你须要在有限的时间内尽量多地点击Bright博士,就像打地鼠游戏一样。

[[html]]
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>基金会打地鼠</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#8B4513',
                        secondary: '#CD853F',
                        accent: '#FFA500',
                        dark: '#2D2A24',
                    },
                    fontFamily: {
                        game: ['"Comic Sans MS"', '"Marker Felt"', 'Arial', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .game-shadow {
                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
            }
            .btn-hover {
                transition: all 0.2s ease;
            }
            .btn-hover:hover {
                transform: translateY(-2px);
                box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-amber-50 to-orange-100 min-h-screen flex flex-col items-center justify-center p-4 font-game text-dark">
<audio id="hitSound" preload="auto">
  <source src="http://scpsandboxcn.wikidot.com/local--files/balloon/hit_sound.wav" type="audio/wav">
</audio>
    <div class="w-full max-w-2xl mx-auto">
        <header class="text-center mb-4">
            <h1 class="text-[clamp(1.5rem,4vw,2.5rem)] font-bold text-primary mb-1 tracking-tight">基金会打地鼠</h1>
            <p class="text-gray-600 text-[clamp(0.9rem,1.5vw,1rem)]">在有限的时间内尽可能多地点击从洞里面跑出来的Bright博士</p>
        </header>

        <div class="game-container bg-secondary/30 rounded-xl p-3 md:p-4 game-shadow mb-4">
            <div class="flex flex-wrap justify-between items-center mb-3">
                <div class="flex items-center gap-1 bg-white/80 px-3 py-1 rounded-lg">
                    <i class="fa fa-clock-o text-primary text-lg"></i>
                    <span id="timer" class="text-xl font-bold">45</span>
                    <span class="text-sm ml-1">秒</span>
                </div>
                
                <div class="flex items-center gap-1 bg-white/80 px-3 py-1 rounded-lg">
                    <i class="fa fa-star text-accent text-lg"></i>
                    <span id="score" class="text-xl font-bold">0</span>
                    <span class="text-sm ml-1">分</span>
                </div>
            </div>

            <div id="game-board" class="grid grid-cols-4 gap-1.5 md:gap-2 max-w-md mx-auto relative">
            </div>

            <div id="game-overlay" class="hidden absolute inset-0 bg-white/90 rounded-lg flex flex-col items-center justify-center z-20">
                <!-- 通关图片(位于文字上方) -->
                <img id="clear-image" src="https://scpsandboxcn.wdfiles.com/local--files/balloon/clear.png" alt="通关成功" class="mb-4 max-w-[200px] hidden">
                <h2 id="final-score-overlay" class="text-2xl md:text-3xl font-bold text-primary mb-3"></h2>
                <p id="score-rank-overlay" class="text-lg md:text-xl text-gray-700 mb-5"></p>
                <button id="restart-btn-overlay" class="bg-primary hover:bg-primary/90 text-white text-lg md:text-xl font-bold py-2 px-6 rounded-full btn-hover shadow">
                    再来一局
                </button>
            </div>

            <div id="failed-overlay" class="hidden absolute inset-0 bg-white/90 rounded-lg flex flex-col items-center justify-center z-20">
                <!-- 失败图片(位于文字上方) -->
                <img id="fail-image" src="https://scpsandboxcn.wdfiles.com/local--files/balloon/fail.png" alt="游戏失败" class="mb-4 max-w-[200px]">
                <h2 class="text-2xl md:text-3xl font-bold text-red-600 mb-4">游戏失败</h2>
                <p class="text-lg md:text-xl text-gray-700 mb-5">你点到SCP-096了</p>
                <button id="try-again-btn-overlay" class="bg-primary hover:bg-primary/90 text-white text-lg md:text-xl font-bold py-2 px-6 rounded-full btn-hover shadow">
                    再试一次
                </button>
            </div>
        </div>

        <div id="start-screen" class="text-center py-6">
            <button id="start-btn" class="bg-primary hover:bg-primary/90 text-white text-lg md:text-xl font-bold py-2 px-6 rounded-full btn-hover shadow">
                开始游戏
            </button>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const gameBoard = document.getElementById('game-board');
            const startBtn = document.getElementById('start-btn');
            const restartBtn = document.getElementById('restart-btn-overlay');
            const tryAgainBtn = document.getElementById('try-again-btn-overlay');
            const timerDisplay = document.getElementById('timer');
            const scoreDisplay = document.getElementById('score');
            const startScreen = document.getElementById('start-screen');
            const gameOverlay = document.getElementById('game-overlay');
            const failedOverlay = document.getElementById('failed-overlay');
            const finalScoreDisplay = document.getElementById('final-score-overlay');
            const scoreRankDisplay = document.getElementById('score-rank-overlay');
            const clearImage = document.getElementById('clear-image'); // 通关图片元素
            
            const EMPTY_HOLE = 'http://scpsandboxcn.wikidot.com/local--files/balloon/empty_hole.png';
            const MOLE = 'https://scpsandboxcn.wdfiles.com/local--files/balloon/hole_with_jkb.png';
            const HIT_MOLE = 'https://scpsandboxcn.wdfiles.com/local--files/balloon/hole_hit.png';
            const BOMB = 'https://scpsandboxcn.wdfiles.com/local--files/balloon/96.png';
            const GAME_OVER_IMG = 'https://scpsandboxcn.wikidot.com/local--files/balloon/gameover.png';
            
            let score = 0;
            let timer = 45;
            let gameInterval;
            let holes = [];
            let bombHole = null;
            const INITIAL_MOLES = 3;
            const MAX_BOMBS = 1;
            
            function createHoles() {
                gameBoard.innerHTML = '';
                holes = [];
                
                for (let i = 0; i < 16; i++) {
                    const hole = document.createElement('div');
                    hole.className = 'aspect-square rounded-lg overflow-hidden relative cursor-pointer';
                    hole.dataset.id = i;
                    hole.dataset.state = 'empty';
                    
                    const img = document.createElement('img');
                    img.src = EMPTY_HOLE;
                    img.alt = '空洞';
                    img.className = 'w-full h-full object-cover';
                    
                    hole.appendChild(img);
                    gameBoard.appendChild(hole);
                    holes.push(hole);
                    
                    hole.addEventListener('click', () => handleHoleClick(hole));
                }
            }
            
            function startGame() {
                score = 0;
                timer = 45;
                scoreDisplay.textContent = score;
                timerDisplay.textContent = timer;
                bombHole = null;
                clearImage.classList.add('hidden'); // 隐藏通关图片
                
                startScreen.classList.add('hidden');
                gameOverlay.classList.add('hidden');
                failedOverlay.classList.add('hidden');
                gameBoard.classList.remove('hidden');
                
                createHoles();
                initializeMoles();
                
                gameInterval = setInterval(() => {
                    timer--;
                    timerDisplay.textContent = timer;
                    
                    if (timer === 0) {
                        endGame();
                    } else if ([25, 30, 35].includes(timer)) {
                        showBomb();
                    }
                }, 1000);
            }
            
            function initializeMoles() {
                let molesCreated = 0;
                
                while (molesCreated < INITIAL_MOLES) {
                    const emptyHoles = holes.filter(hole => hole.dataset.state === 'empty');
                    if (emptyHoles.length === 0) break;
                    
                    const randomHole = emptyHoles[Math.floor(Math.random() * emptyHoles.length)];
                    randomHole.dataset.state = 'mole';
                    randomHole.querySelector('img').src = MOLE;
                    randomHole.querySelector('img').alt = 'Bright博士';
                    
                    molesCreated++;
                }
            }
            
            function replaceMole() {
                const emptyHoles = holes.filter(hole => hole.dataset.state === 'empty');
                if (emptyHoles.length === 0) return;
                
                const randomHole = emptyHoles[Math.floor(Math.random() * emptyHoles.length)];
                randomHole.dataset.state = 'mole';
                randomHole.querySelector('img').src = MOLE;
                randomHole.querySelector('img').alt = 'Bright博士';
            }
            
            function getBombCount() {
                return holes.filter(hole => hole.dataset.state === 'bomb').length;
            }
            
            function showBomb() {
                if (getBombCount() >= MAX_BOMBS) return;
                
                const availableHoles = holes.filter(hole => 
                    hole.dataset.state === 'empty' || hole.dataset.state === 'mole'
                );
                
                if (availableHoles.length === 0) return;
                
                const randomHole = availableHoles[Math.floor(Math.random() * availableHoles.length)];
                
                if (randomHole.dataset.state === 'mole') {
                    randomHole.dataset.state = 'empty';
                    randomHole.querySelector('img').src = EMPTY_HOLE;
                    randomHole.querySelector('img').alt = '空洞';
                    setTimeout(replaceMole, 0);
                }
                randomHole.dataset.state = 'bomb';
                randomHole.querySelector('img').src = BOMB;
                randomHole.querySelector('img').alt = 'SCP-096';
                bombHole = randomHole;
                
                setTimeout(() => {
                    if (bombHole && bombHole.dataset.state === 'bomb') {
                        bombHole.dataset.state = 'empty';
                        bombHole.querySelector('img').src = EMPTY_HOLE;
                        bombHole.querySelector('img').alt = '空洞';
                        bombHole = null;
                    }
                }, 3000);
            }
            
            function handleHoleClick(hole) {
                if (hole.dataset.state === 'mole') {
                    hitMole(hole);
                } else if (hole.dataset.state === 'bomb') {
                    hitBomb(hole);
                }
            }
            
            function hitMole(hole) {
                const hitSound = document.getElementById('hitSound');
                hitSound.currentTime = 0;
                hitSound.play().catch(e => console.log('音效播放失败:', e));
                hole.dataset.state = 'hit';
                hole.querySelector('img').src = HIT_MOLE;
                hole.querySelector('img').alt = '被击中的Bright博士';
                score++;
                scoreDisplay.textContent = score;

                
                setTimeout(() => {
                    hole.dataset.state = 'empty';
                    hole.querySelector('img').src = EMPTY_HOLE;
                    hole.querySelector('img').alt = '空洞';
                    replaceMole();
                }, 500);
            }
            
            function hitBomb(hole) {
                hole.dataset.state = 'hitBomb';
                
                clearInterval(gameInterval);
                
                setTimeout(() => {
                    failedOverlay.classList.remove('hidden');
                }, 500);
            }
            
            function endGame() {
                clearInterval(gameInterval);
                
                holes.forEach(hole => {
                    hole.removeEventListener('click', handleHoleClick);
                });
                
                // 当分数大于20分时显示通关图片
                if (score > 20) {
                    clearImage.classList.remove('hidden');
                } else {
                    clearImage.classList.add('hidden');
                }
                
                finalScoreDisplay.textContent = `最终得分: ${score}`;
                
                let rankText;
                if (score == 0) rankText = '您似乎不会操作,或者设备出故障了。';
                else if (score <= 30) rankText = '您的成绩超过了4%的D级人员。';
                else if (score <= 45) rankText = '您的成绩超过了46%的D级人员。';
                else if (score <= 55) rankText = '您的成绩超过了61%的D级人员。';
                else if (score <= 65) rankText = '您的成绩超过了78%的D级人员。';
                else if (score <= 75) rankText = '您的成绩超过了84%的D级人员。';
                else if (score <= 80) rankText = '您的成绩超过了92%的D级人员。';
                else if (score <= 85) rankText = '您的成绩超过了64%的研究员。';
                else if (score <= 90) rankText = '您的成绩超过了87%的研究员。';
                else if (score <= 95) rankText = '您的成绩超过了93%的研究员。';
                else if (score <= 100) rankText = '您的成绩超过了96%的研究员。';
                else if (score <= 105) rankText = '您的成绩超过了98%的研究员。';
                else if (score <= 110) rankText = '您的成绩超过了43%的站点主管。';
                else if (score <= 115) rankText = '您的成绩超过了65%的站点主管。';
                else if (score <= 120) rankText = '您的成绩超过了77%的站点主管。';
                else if (score <= 125) rankText = '您的成绩超过了89%的站点主管。';
                else if (score <= 130) rankText = '您的成绩超过了71%的O5议会成员。';
                else if (score <= 135) rankText = '您的成绩超过了88%的O5议会成员。';
                else if (score <= 145) rankText = '您的成绩超过了96%的O5议会成员。';
                else if (score <= 180) rankText = '您的成绩超过了100%的O5议会成员。恭喜。';
                else rankText = '您开连点器了,对吧?';
                
                scoreRankDisplay.textContent = rankText;
                gameOverlay.classList.remove('hidden');
            }
            
            startBtn.addEventListener('click', startGame);
            restartBtn.addEventListener('click', startGame);
            tryAgainBtn.addEventListener('click', startGame);
        });
    </script>
</body>
</html>
    
[[/html]]

------

游戏界面需要加载后才会在上方显示,这大概需要20秒时间。如果游戏出现显示问题或者加载失败可以刷新网页。第一次运行游戏可能比较卡顿,运行一会就会变流畅。

负责本页面程序的是[[*user leather_boots]],负责本页面美术的是[[*user FATEfoggy]]。任何关于本页面的想法都欢迎在讨论区反馈,我们会认真阅读每一条讨论帖 :)