The Hidden Storage:A Grid-Based Search Game

  Blog    |     February 03, 2026

I'll create an interactive grid-based game where players search for a hidden storage tile. The game features:

  • A 4x4 grid of tiles
  • One randomly hidden storage tile
  • Click tracking and win detection
  • Visual feedback for wrong guesses
  • Reset functionality
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">The Hidden Storage</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        body {
            background: linear-gradient(135deg, #1e3c72, #2a5298);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            color: white;
        }
        .game-container {
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            border-radius: 20px;
            padding: 30px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            text-align: center;
            max-width: 500px;
            width: 90%;
        }
        h1 {
            margin-bottom: 10px;
            font-size: 2.5rem;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
        }
        .subtitle {
            margin-bottom: 20px;
            opacity: 0.9;
            font-size: 1.1rem;
        }
        .game-stats {
            display: flex;
            justify-content: space-around;
            margin-bottom: 25px;
            gap: 15px;
        }
        .stat-box {
            background: rgba(255, 255, 255, 0.15);
            padding: 12px 20px;
            border-radius: 10px;
            flex: 1;
        }
        .stat-label {
            font-size: 0.9rem;
            opacity: 0.8;
        }
        .stat-value {
            font-size: 1.8rem;
            font-weight: bold;
            margin-top: 5px;
        }
        .grid {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 12px;
            margin-bottom: 25px;
            max-width: 400px;
            margin-left: auto;
            margin-right: auto;
        }
        .tile {
            aspect-ratio: 1;
            background: linear-gradient(145deg, #4a69bd, #1e3799);
            border: none;
            border-radius: 12px;
            cursor: pointer;
            font-size: 1.5rem;
            color: white;
            transition: all 0.3s ease;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
            position: relative;
            overflow: hidden;
        }
        .tile:hover:not(.revealed):not(.storage) {
            transform: translateY(-3px);
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
            background: linear-gradient(145deg, #5a7bd1, #2e47a9);
        }
        .tile.revealed {
            background: linear-gradient(145deg, #e74c3c, #c0392b);
            cursor: default;
            transform: scale(0.95);
        }
        .tile.storage {
            background: linear-gradient(145deg, #2ecc71, #27ae60);
            animation: pulse 1.5s infinite;
        }
        @keyframes pulse {
            0% { box-shadow: 0 0 0 0 rgba(46, 204, 113, 0.7); }
            70% { box-shadow: 0 0 0 15px rgba(46, 204, 113, 0); }
            100% { box-shadow: 0 0 0 0 rgba(46, 204, 113, 0); }
        }
        .tile.revealed::after {
            content: "โŒ";
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 1.8rem;
        }
        .tile.storage.revealed::after {
            content: "๐Ÿ”";
            font-size: 2rem;
        }
        .controls {
            display: flex;
            gap: 15px;
            justify-content: center;
        }
        button {
            background: linear-gradient(145deg, #3498db, #2980b9);
            color: white;
            border: none;
            padding: 12px 25px;
            border-radius: 8px;
            font-size: 1rem;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
        }
        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
        }
        button:active {
            transform: translateY(0);
        }
        .message {
            margin-top: 20px;
            padding: 15px;
            border-radius: 10px;
            font-weight: bold;
            min-height: 50px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
        }
        .message.win {
            background: rgba(46, 204, 113, 0.2);
            border: 2px solid #2ecc71;
        }
        .message.lose {
            background: rgba(231, 76, 60, 0.2);
            border: 2px solid #e74c3c;
        }
        .message.hidden {
            opacity: 0;
            height: 0;
            padding: 0;
            margin: 0;
            border: none;
        }
        @media (max-width: 480px) {
            .grid {
                gap: 8px;
            }
            .tile {
                font-size: 1.2rem;
            }
            h1 {
                font-size: 2rem;
            }
        }
    </style>
</head>
<body>
    <div class="game-container">
        <h1>The Hidden Storage</h1>
        <p class="subtitle">Find the secret storage tile ๐Ÿ”</p>
        <div class="game-stats">
            <div class="stat-box">
                <div class="stat-label">Attempts</div>
                <div class="stat-value" id="attempts">0</div>
            </div>
            <div class="stat-box">
                <div class="stat-label">Best Score</div>
                <div class="stat-value" id="best-score">-</div>
            </div>
        </div>
        <div class="grid" id="grid"></div>
        <div class="controls">
            <button id="reset-btn">New Game</button>
            <button id="hint-btn">Hint</button>
        </div>
        <div class="message hidden" id="message"></div>
    </div>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const grid = document.getElementById('grid');
            const attemptsDisplay = document.getElementById('attempts');
            const bestScoreDisplay = document.getElementById('best-score');
            const messageDisplay = document.getElementById('message');
            const resetBtn = document.getElementById('reset-btn');
            const hintBtn = document.getElementById('hint-btn');
            let tiles = [];
            let storageIndex = -1;
            let attempts = 0;
            let gameOver = false;
            let bestScore = localStorage.getItem('hiddenStorageBest') || '-';
            bestScoreDisplay.textContent = bestScore;
            function createGrid() {
                grid.innerHTML = '';
                tiles = [];
                attempts = 0;
                gameOver = false;
                attemptsDisplay.textContent = '0';
                messageDisplay.className = 'message hidden';
                // Create 16 tiles
                for (let i = 0; i < 16; i++) {
                    const tile = document.createElement('button');
                    tile.className = 'tile';
                    tile.dataset.index = i;
                    tile.addEventListener('click', () => handleTileClick(i));
                    grid.appendChild(tile);
                    tiles.push(tile);
                }
                // Randomly place storage
                storageIndex = Math.floor(Math.random() * 16);
                tiles[storageIndex].classList.add('storage');
            }
            function handleTileClick(index) {
                if (gameOver || tiles[index].classList.contains('revealed')) return;
                attempts++;
                attemptsDisplay.textContent = attempts;
                tiles[index].classList.add('revealed');
                if (index === storageIndex) {
                    // Win
                    gameOver = true;
                    tiles[storageIndex].classList.add('revealed');
                    messageDisplay.textContent = `๐ŸŽ‰ Found it in ${attempts} attempts!`;
                    messageDisplay.className = 'message win';
                    // Update best score
                    if (bestScore === '-' || attempts < parseInt(bestScore)) {
                        bestScore = attempts;
                        bestScoreDisplay.textContent = bestScore;
                        localStorage.setItem('hiddenStorageBest', bestScore);
                    }
                } else {
                    // Wrong guess
                    if (attempts >= 10) {
                        gameOver = true;
                        tiles[storageIndex].classList.add('revealed');
                        messageDisplay.textContent = 'Game over! Too many attempts.';
                        messageDisplay.className = 'message lose';
                    }
                }
            }
            function showHint() {
                if (gameOver) return;
                // Find unrevealed tiles
                const unrevealed = tiles.filter(tile => !tile.classList.contains('revealed'));
                if (unrevealed.length > 1) {
                    // Highlight a random unrevealed tile (could be storage or not)
                    const randomTile = unrevealed[Math.floor(Math.random() * unrevealed.length)];
                    randomTile.style.animation = 'pulse 1s';
                    setTimeout(() => {
                        randomTile.style.animation = '';
                    }, 1000);
                }
            }
            resetBtn.addEventListener('click', createGrid);
            hintBtn.addEventListener('click', showHint);
            // Initialize game
            createGrid();
        });
    </script>
</body>
</html>

How to Play:

  1. Objective: Find the hidden storage tile (marked with ๐Ÿ”) in the 4x4 grid
  2. Gameplay:
    • Click on tiles to reveal them
    • Wrong tiles turn red with an โŒ
    • The storage tile turns green when found
    • You have 10 attempts to find the storage
  3. Features:
    • Attempt counter tracks your progress
    • Best score saves your lowest attempt count
    • Hint button highlights a random unrevealed tile
    • Reset button starts a new game
  4. Win Conditions:
    • Find the storage within 10 attempts
    • Try to beat your best score!

The game uses modern design with glassmorphism effects, smooth animations, and responsive layout. All game state is managed through JavaScript with visual feedback for player actions.


Request an On-site Audit / Inquiry

SSL Secured Inquiry