forks

Creation chat

ClarkZhang
make me a maze game
02-28 00:49

登录 后可以评论

Assistant
# Maze Game Implementation I'll create a responsive maze game with a clean design that works well on both mobile and desktop. The game will feature keyboard controls for desktop and touch controls for mobile devices. (HTML code has been generated and updated; see above for the current version.) ## Features of the Maze Game: 1. **Responsive Design**: Works on both mobile and desktop devices 2. **Theme Support**: Light and dark mode with toggle button 3. **Game Mechanics**: - Navigate through a randomly generated maze - Move counter to track your progress - Win screen when you reach the goal 4. **Controls**: - Keyboard arrow keys for desktop - On-screen buttons for mobile - Swipe gestures for mobile 5. **Visual Design**: - Clean, modern interface with Tailwind CSS - Color-coded elements (player, goal, walls) - Smooth animations and transitions 6. **Game Features**: - Generate new mazes with the click of a button - Restart functionality - Move counter The game is contained within a fixed-size container to ensure it's visible in iframes, and all interactive elements are designed to work well on touch devices with appropriate spacing and touch targets. To play: 1. Use arrow keys on desktop or on-screen buttons/swipe on mobile to navigate 2. Try to reach the green goal circle with the fewest moves 3. Click "Generate New Maze" to create a new challenge 4. Toggle between light and dark mode using the button in the top-right corner The console in the bottom-right of the preview can be used to check for any logs or errors during gameplay.
▼ Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Maze Runner Game</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script>tailwind.config = { darkMode: 'class' }</script>
    <style>
        .maze-cell {
            transition: background-color 0.2s;
        }
        .player-cell {
            background-color: #3b82f6;
            border-radius: 50%;
            z-index: 10;
        }
        .goal-cell {
            background-color: #10b981;
            border-radius: 50%;
        }
        .wall-cell {
            background-color: #94a3b8;
        }
        .path-cell {
            background-color: #e2e8f0;
        }
        .visited-cell {
            background-color: #dbeafe;
        }
        .dark .path-cell {
            background-color: #1e293b;
        }
        .dark .visited-cell {
            background-color: #1e3a8a;
        }
        .dark .wall-cell {
            background-color: #64748b;
        }
        .touch-controls {
            touch-action: manipulation;
        }
    </style>
</head>
<body class="min-h-screen bg-slate-50 dark:bg-slate-900 text-slate-900 dark:text-slate-100 flex flex-col items-center justify-center p-4">
    <!-- Theme toggle button -->
    <button id="theme-toggle-btn" class="fixed top-4 right-4 z-10 p-2 rounded-md hover:bg-gray-200 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors flex items-center justify-center" aria-label="Toggle theme" onclick="toggleTheme()">
        <svg id="icon-moon" class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998z"/></svg>
        <svg id="icon-sun" class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24" aria-hidden="true" style="display:none"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"></path></svg>
    </button>
    
    <script>
        function toggleTheme(){ 
            var el=document.documentElement; 
            var isDark=!el.classList.contains('dark'); 
            el.classList.toggle('dark',isDark); 
            localStorage.setItem('theme',isDark?'dark':'light'); 
            applyTheme(isDark); 
        }
        function applyTheme(isDark){ 
            document.getElementById('icon-moon').style.display=isDark?'none':'block'; 
            document.getElementById('icon-sun').style.display=isDark?'block':'none'; 
        }
        document.addEventListener('DOMContentLoaded',function(){ 
            var saved=localStorage.getItem('theme'); 
            var isDark=saved==='dark'||(!saved&&window.matchMedia('(prefers-color-scheme: dark)').matches); 
            document.documentElement.classList.toggle('dark',isDark); 
            applyTheme(isDark); 
        });
    </script>

    <div class="w-full max-w-3xl flex flex-col items-center">
        <header class="text-center mb-6">
            <h1 class="text-3xl md:text-4xl font-bold mb-2">Maze Runner</h1>
            <p class="text-slate-600 dark:text-slate-300 mb-4">Navigate through the maze to reach the goal!</p>
        </header>

        <div class="w-full bg-white dark:bg-slate-800 rounded-xl shadow-lg p-4 mb-6">
            <div class="flex justify-between items-center mb-4">
                <div class="flex items-center space-x-4">
                    <div class="flex items-center">
                        <div class="w-4 h-4 bg-blue-500 rounded-full mr-2"></div>
                        <span class="text-sm">Player</span>
                    </div>
                    <div class="flex items-center">
                        <div class="w-4 h-4 bg-emerald-500 rounded-full mr-2"></div>
                        <span class="text-sm">Goal</span>
                    </div>
                </div>
                <div class="text-lg font-semibold">
                    Moves: <span id="move-count">0</span>
                </div>
            </div>

            <div class="relative">
                <div id="maze-container" class="mx-auto w-full max-w-md aspect-square bg-slate-100 dark:bg-slate-700 rounded-lg overflow-hidden border border-slate-200 dark:border-slate-600">
                    <!-- Maze will be generated here -->
                </div>
                
                <div id="win-message" class="absolute inset-0 flex items-center justify-center bg-black/70 rounded-lg hidden">
                    <div class="text-center p-6 bg-white dark:bg-slate-800 rounded-xl">
                        <h2 class="text-2xl font-bold mb-2">Congratulations!</h2>
                        <p class="mb-4">You solved the maze in <span id="final-moves" class="font-bold">0</span> moves!</p>
                        <button id="restart-btn" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors">Play Again</button>
                    </div>
                </div>
            </div>
        </div>

        <!-- Mobile Controls -->
        <div class="md:hidden w-full max-w-xs mb-6">
            <div class="grid grid-cols-3 gap-3">
                <div></div>
                <button id="up-btn" class="touch-controls bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 h-16 rounded-lg flex items-center justify-center text-2xl font-bold">↑</button>
                <div></div>
                <button id="left-btn" class="touch-controls bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 h-16 rounded-lg flex items-center justify-center text-2xl font-bold">←</button>
                <button id="down-btn" class="touch-controls bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 h-16 rounded-lg flex items-center justify-center text-2xl font-bold">↓</button>
                <button id="right-btn" class="touch-controls bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 h-16 rounded-lg flex items-center justify-center text-2xl font-bold">→</button>
            </div>
        </div>

        <div class="text-center">
            <p class="text-slate-600 dark:text-slate-300 mb-2">Use arrow keys or swipe to move</p>
            <button id="new-maze-btn" class="px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-white rounded-lg transition-colors">Generate New Maze</button>
        </div>
    </div>

    <script>
        // Maze dimensions
        const ROWS = 15;
        const COLS = 15;
        
        // Game state
        let maze = [];
        let playerPos = { row: 0, col: 0 };
        let goalPos = { row: ROWS - 1, col: COLS - 1 };
        let moveCount = 0;
        let gameActive = true;
        
        // DOM elements
        const mazeContainer = document.getElementById('maze-container');
        const moveCountElement = document.getElementById('move-count');
        const winMessage = document.getElementById('win-message');
        const finalMovesElement = document.getElementById('final-moves');
        const restartBtn = document.getElementById('restart-btn');
        const newMazeBtn = document.getElementById('new-maze-btn');
        
        // Mobile controls
        const upBtn = document.getElementById('up-btn');
        const downBtn = document.getElementById('down-btn');
        const leftBtn = document.getElementById('left-btn');
        const rightBtn = document.getElementById('right-btn');
        
        // Initialize the game
        function initGame() {
            generateMaze();
            renderMaze();
            moveCount = 0;
            moveCountElement.textContent = moveCount;
            gameActive = true;
            winMessage.classList.add('hidden');
        }
        
        // Generate a simple maze (random walls)
        function generateMaze() {
            maze = [];
            for (let row = 0; row < ROWS; row++) {
                maze[row] = [];
                for (let col = 0; col < COLS; col++) {
                    // Create borders
                    if (row === 0 || row === ROWS - 1 || col === 0 || col === COLS - 1) {
                        maze[row][col] = 1; // Wall
                    } else {
                        // Random walls (30% chance)
                        maze[row][col] = Math.random() < 0.3 ? 1 : 0;
                    }
                }
            }
            
            // Ensure start and end positions are clear
            maze[0][0] = 0; // Start
            maze[ROWS - 1][COLS - 1] = 0; // End
            
            // Set player and goal positions
            playerPos = { row: 0, col: 0 };
            goalPos = { row: ROWS - 1, col: COLS - 1 };
        }
        
        // Render the maze
        function renderMaze() {
            mazeContainer.innerHTML = '';
            
            // Create grid container
            const grid = document.createElement('div');
            grid.className = 'grid w-full h-full';
            grid.style.gridTemplateColumns = `repeat(${COLS}, 1fr)`;
            grid.style.gridTemplateRows = `repeat(${ROWS}, 1fr)`;
            
            // Render each cell
            for (let row = 0; row < ROWS; row++) {
                for (let col = 0; col < COLS; col++) {
                    const cell = document.createElement('div');
                    cell.className = 'maze-cell';
                    cell.dataset.row = row;
                    cell.dataset.col = col;
                    
                    // Apply cell styles based on type
                    if (row === playerPos.row && col === playerPos.col) {
                        cell.classList.add('player-cell');
                    } else if (row === goalPos.row && col === goalPos.col) {
                        cell.classList.add('goal-cell');
                    } else if (maze[row][col] === 1) {
                        cell.classList.add('wall-cell');
                    } else {
                        cell.classList.add('path-cell');
                    }
                    
                    grid.appendChild(cell);
                }
            }
            
            mazeContainer.appendChild(grid);
        }
        
        // Move player
        function movePlayer(direction) {
            if (!gameActive) return;
            
            let newRow = playerPos.row;
            let newCol = playerPos.col;
            
            switch (direction) {
                case 'up':
                    newRow--;
                    break;
                case 'down':
                    newRow++;
                    break;
                case 'left':
                    newCol--;
                    break;
                case 'right':
                    newCol++;
                    break;
            }
            
            // Check if move is valid
            if (newRow >= 0 && newRow < ROWS && newCol >= 0 && newCol < COLS && maze[newRow][newCol] !== 1) {
                playerPos.row = newRow;
                playerPos.col = newCol;
                moveCount++;
                moveCountElement.textContent = moveCount;
                
                renderMaze();
                
                // Check if player reached the goal
                if (playerPos.row === goalPos.row && playerPos.col === goalPos.col) {
                    winGame();
                }
            }
        }
        
        // Win game
        function winGame() {
            gameActive = false;
            finalMovesElement.textContent = moveCount;
            winMessage.classList.remove('hidden');
        }
        
        // Event listeners for keyboard controls
        document.addEventListener('keydown', (e) => {
            switch (e.key) {
                case 'ArrowUp':
                    movePlayer('up');
                    e.preventDefault();
                    break;
                case 'ArrowDown':
                    movePlayer('down');
                    e.preventDefault();
                    break;
                case 'ArrowLeft':
                    movePlayer('left');
                    e.preventDefault();
                    break;
                case 'ArrowRight':
                    movePlayer('right');
                    e.preventDefault();
                    break;
            }
        });
        
        // Event listeners for mobile controls
        upBtn.addEventListener('click', () => movePlayer('up'));
        downBtn.addEventListener('click', () => movePlayer('down'));
        leftBtn.addEventListener('click', () => movePlayer('left'));
        rightBtn.addEventListener('click', () => movePlayer('right'));
        
        // Restart button
        restartBtn.addEventListener('click', initGame);
        
        // New maze button
        newMazeBtn.addEventListener('click', initGame);
        
        // Initialize the game on load
        window.addEventListener('DOMContentLoaded', initGame);
        
        // Add swipe detection for mobile
        let touchStartX = 0;
        let touchStartY = 0;
        
        mazeContainer.addEventListener('touchstart', (e) => {
            touchStartX = e.changedTouches[0].screenX;
            touchStartY = e.changedTouches[0].screenY;
        }, { passive: false });
        
        mazeContainer.addEventListener('touchend', (e) => {
            if (!gameActive) return;
            
            const touchEndX = e.changedTouches[0].screenX;
            const touchEndY = e.changedTouches[0].screenY;
            
            const diffX = touchEndX - touchStartX;
            const diffY = touchEndY - touchStartY;
            
            // Determine swipe direction
            if (Math.abs(diffX) > Math.abs(diffY)) {
                // Horizontal swipe
                if (diffX > 0) {
                    movePlayer('right');
                } else {
                    movePlayer('left');
                }
            } else {
                // Vertical swipe
                if (diffY > 0) {
                    movePlayer('down');
                } else {
                    movePlayer('up');
                }
            }
            
            e.preventDefault();
        }, { passive: false });
    </script>
</body>
</html>
02-28 00:51

登录 后可以评论

Comments

登录 后可以评论