Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Color Memory Challenge</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .game-tile { | |
| transition: all 0.3s ease; | |
| transform-style: preserve-3d; | |
| } | |
| .game-tile.flipped { | |
| transform: rotateY(180deg); | |
| } | |
| .game-tile-face { | |
| backface-visibility: hidden; | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| border-radius: 0.5rem; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| color: white; | |
| font-weight: bold; | |
| } | |
| .game-tile-front { | |
| background: linear-gradient(135deg, #374151, #6B7280); | |
| } | |
| .game-tile-back { | |
| background: linear-gradient(135deg, #3B82F6, #1D4ED8); | |
| transform: rotateY(180deg); | |
| } | |
| .game-tile.matched .game-tile-front { | |
| opacity: 0.2; | |
| } | |
| .confetti { | |
| position: absolute; | |
| width: 10px; | |
| height: 10px; | |
| background-color: #f00; | |
| border-radius: 50%; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { transform: scale(1); } | |
| 50% { transform: scale(1.05); } | |
| } | |
| .pulse-animation { | |
| animation: pulse 1.5s infinite; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-900 text-white min-h-screen flex flex-col items-center justify-center p-4"> | |
| <div class="max-w-4xl w-full"> | |
| <header class="text-center mb-8"> | |
| <h1 class="text-4xl md:text-5xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-600 mb-2"> | |
| Color Memory Challenge | |
| </h1> | |
| <p class="text-gray-300 mb-4">Match all pairs of colors to win!</p> | |
| <div class="flex justify-center items-center space-x-6 mb-4"> | |
| <div class="bg-gray-800 px-4 py-2 rounded-lg"> | |
| <span class="text-blue-400"><i class="fas fa-stopwatch mr-2"></i></span> | |
| <span id="timer">00:00</span> | |
| </div> | |
| <div class="bg-gray-800 px-4 py-2 rounded-lg"> | |
| <span class="text-yellow-400"><i class="fas fa-star mr-2"></i></span> | |
| <span id="moves">0</span> moves | |
| </div> | |
| <div class="bg-gray-800 px-4 py-2 rounded-lg"> | |
| <span class="text-purple-400"><i class="fas fa-brain mr-2"></i></span> | |
| <span id="memory">100%</span> memory | |
| </div> | |
| </div> | |
| <button id="start-game" class="bg-gradient-to-r from-green-500 to-emerald-600 hover:from-green-600 hover:to-emerald-700 text-white font-bold py-3 px-6 rounded-full shadow-lg transition-all duration-300 transform hover:scale-105"> | |
| <i class="fas fa-play mr-2"></i> Start Game | |
| </button> | |
| </header> | |
| <div id="game-board" class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3 sm:gap-4 mb-8"></div> | |
| <div id="game-modal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-gray-800 rounded-xl p-8 max-w-lg w-full mx-4 text-center transform transition-all duration-500 scale-0"> | |
| <div class="text-4xl mb-4 text-green-400"><i class="fas fa-trophy"></i></div> | |
| <h2 class="text-3xl font-bold mb-2">You Won!</h2> | |
| <p class="text-gray-300 mb-6">Congratulations on completing the challenge!</p> | |
| <div class="grid grid-cols-2 gap-4 mb-6"> | |
| <div class="bg-gray-700 p-3 rounded-lg"> | |
| <p class="text-sm text-gray-400">Time</p> | |
| <p class="text-xl font-bold" id="modal-time"></p> | |
| </div> | |
| <div class="bg-gray-700 p-3 rounded-lg"> | |
| <p class="text-sm text-gray-400">Moves</p> | |
| <p class="text-xl font-bold" id="modal-moves"></p> | |
| </div> | |
| <div class="bg-gray-700 p-3 rounded-lg"> | |
| <p class="text-sm text-gray-400">Memory Usage</p> | |
| <p class="text-xl font-bold" id="modal-memory"></p> | |
| </div> | |
| <div class="bg-gray-700 p-3 rounded-lg"> | |
| <p class="text-sm text-gray-400">Difficulty</p> | |
| <p class="text-xl font-bold" id="modal-difficulty"></p> | |
| </div> | |
| </div> | |
| <div class="flex justify-center gap-4"> | |
| <button id="play-again" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded-full transition-all"> | |
| Play Again | |
| </button> | |
| <button id="close-modal" class="bg-gray-600 hover:bg-gray-700 text-white font-bold py-2 px-6 rounded-full transition-all"> | |
| Close | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <footer class="mt-auto text-center text-gray-500 py-4 text-sm"> | |
| <p>© 2023 Color Memory Challenge | Built with <i class="fas fa-heart text-red-500"></i> using HTML, CSS & JavaScript</p> | |
| </footer> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Game state variables | |
| let gameStarted = false; | |
| let timerInterval; | |
| let seconds = 0; | |
| let moves = 0; | |
| let memoryPercentage = 100; | |
| let firstTile = null; | |
| let secondTile = null; | |
| let lockBoard = false; | |
| let matchedPairs = 0; | |
| let difficulty = 'medium'; | |
| let colorPairs = []; | |
| let audioEnabled = true; | |
| // DOM elements | |
| const gameBoard = document.getElementById('game-board'); | |
| const startButton = document.getElementById('start-game'); | |
| const timerDisplay = document.getElementById('timer'); | |
| const movesDisplay = document.getElementById('moves'); | |
| const memoryDisplay = document.getElementById('memory'); | |
| const gameModal = document.getElementById('game-modal'); | |
| const modalTime = document.getElementById('modal-time'); | |
| const modalMoves = document.getElementById('modal-moves'); | |
| const modalMemory = document.getElementById('modal-memory'); | |
| const modalDifficulty = document.getElementById('modal-difficulty'); | |
| const playAgainButton = document.getElementById('play-again'); | |
| const closeModalButton = document.getElementById('close-modal'); | |
| // Color palettes for different difficulty levels | |
| const colorPalettes = { | |
| easy: [ | |
| '#FF5252', '#4CAF50', '#2196F3', '#FFC107', | |
| '#9C27B0', '#00BCD4', '#E91E63', '#FF9800' | |
| ], | |
| medium: [ | |
| '#FF5252', '#4CAF50', '#2196F3', '#FFC107', | |
| '#9C27B0', '#00BCD4', '#E91E63', '#FF9800', | |
| '#795548', '#607D8B', '#8BC34A', '#FF5722', | |
| '#673AB7', '#009688', '#3F51B5', '#CDDC39' | |
| ], | |
| hard: [ | |
| '#EF5350', '#66BB6A', '#42A5F5', '#FFA726', | |
| '#AB47BC', '#26C6DA', '#EC407A', '#FF7043', | |
| '#8D6E63', '#78909C', '#9CCC65', '#E57373', | |
| '#7E57C2', '#26A69A', '#5C6BC0', '#DCE775', | |
| '#FF5252', '#4CAF50', '#2196F3', '#FFC107', | |
| '#9C27B0', '#00BCD4', '#E91E63', '#FF9800' | |
| ] | |
| }; | |
| // Sounds | |
| const sounds = { | |
| flip: new Audio('https://assets.mixkit.co/sfx/preview/mixkit-game-click-1114.mp3'), | |
| match: new Audio('https://assets.mixkit.co/sfx/preview/mixkit-unlock-game-notification-253.mp3'), | |
| win: new Audio('https://assets.mixkit.co/sfx/preview/mixkit-winning-chimes-2015.mp3'), | |
| wrong: new Audio('https://assets.mixkit.co/sfx/preview/mixkit-retro-arcade-lose-2027.mp3') | |
| }; | |
| // Initialize the game | |
| function initGame() { | |
| // Reset game state | |
| gameStarted = false; | |
| clearInterval(timerInterval); | |
| seconds = 0; | |
| moves = 0; | |
| memoryPercentage = 100; | |
| matchedPairs = 0; | |
| firstTile = null; | |
| secondTile = null; | |
| lockBoard = false; | |
| // Update displays | |
| timerDisplay.textContent = '00:00'; | |
| movesDisplay.textContent = '0'; | |
| memoryDisplay.textContent = '100%'; | |
| // Determine difficulty based on screen width | |
| const screenWidth = window.innerWidth; | |
| if (screenWidth < 640) { // Mobile | |
| difficulty = 'easy'; | |
| colorPairs = [...colorPalettes.easy, ...colorPalettes.easy]; | |
| } else if (screenWidth < 1024) { // Tablet | |
| difficulty = 'medium'; | |
| colorPairs = [...colorPalettes.medium, ...colorPalettes.medium]; | |
| } else { // Desktop | |
| difficulty = 'hard'; | |
| colorPairs = [...colorPalettes.hard, ...colorPalettes.hard]; | |
| } | |
| // Shuffle the colors | |
| colorPairs = shuffleArray(colorPairs); | |
| // Clear and rebuild the game board | |
| gameBoard.innerHTML = ''; | |
| // Create tiles | |
| colorPairs.forEach((color, index) => { | |
| const tile = document.createElement('div'); | |
| tile.classList.add('game-tile', 'cursor-pointer', 'aspect-square', 'relative'); | |
| tile.dataset.index = index; | |
| tile.dataset.color = color; | |
| const frontFace = document.createElement('div'); | |
| frontFace.classList.add('game-tile-face', 'game-tile-front'); | |
| frontFace.innerHTML = '<i class="fas fa-question text-2xl sm:text-3xl opacity-70"></i>'; | |
| const backFace = document.createElement('div'); | |
| backFace.classList.add('game-tile-face', 'game-tile-back'); | |
| backFace.style.backgroundColor = color; | |
| backFace.innerHTML = `<div class="w-1/2 h-1/2 rounded-lg" style="background-color: ${color}; border: 2px solid white;"></div>`; | |
| tile.appendChild(frontFace); | |
| tile.appendChild(backFace); | |
| tile.addEventListener('click', flipTile); | |
| gameBoard.appendChild(tile); | |
| }); | |
| // Update modal difficulty display | |
| modalDifficulty.textContent = difficulty.charAt(0).toUpperCase() + difficulty.slice(1); | |
| // Reset start button | |
| startButton.innerHTML = '<i class="fas fa-play mr-2"></i> Start Game'; | |
| startButton.classList.remove('bg-gradient-to-r', 'from-red-500', 'to-red-600'); | |
| startButton.classList.add('bg-gradient-to-r', 'from-green-500', 'to-emerald-600', 'hover:from-green-600', 'hover:to-emerald-700'); | |
| // Show memory tiles briefly at start | |
| if (gameStarted) { | |
| showTilesBriefly(); | |
| } | |
| } | |
| // Shuffle array using Fisher-Yates algorithm | |
| function shuffleArray(array) { | |
| for (let i = array.length - 1; i > 0; i--) { | |
| const j = Math.floor(Math.random() * (i + 1)); | |
| [array[i], array[j]] = [array[j], array[i]]; | |
| } | |
| return array; | |
| } | |
| // Start the game | |
| function startGame() { | |
| if (gameStarted) return; | |
| gameStarted = true; | |
| startButton.innerHTML = '<i class="fas fa-sync-alt mr-2"></i> Restart'; | |
| startButton.classList.remove('bg-gradient-to-r', 'from-green-500', 'to-emerald-600', 'hover:from-green-600', 'hover:to-emerald-700'); | |
| startButton.classList.add('bg-gradient-to-r', 'from-red-500', 'to-red-600', 'hover:from-red-600', 'hover:to-red-700'); | |
| // Start timer | |
| seconds = 0; | |
| updateTimer(); | |
| timerInterval = setInterval(() => { | |
| seconds++; | |
| updateTimer(); | |
| // Reduce memory percentage over time | |
| if (seconds % 5 === 0 && memoryPercentage > 20) { | |
| memoryPercentage -= 1; | |
| memoryDisplay.textContent = `${memoryPercentage}%`; | |
| } | |
| }, 1000); | |
| // Show tiles briefly at start | |
| showTilesBriefly(); | |
| } | |
| // Update timer display | |
| function updateTimer() { | |
| const minutes = Math.floor(seconds / 60); | |
| const remainingSeconds = seconds % 60; | |
| timerDisplay.textContent = `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`; | |
| } | |
| // Show all tiles briefly at game start | |
| function showTilesBriefly() { | |
| const tiles = document.querySelectorAll('.game-tile'); | |
| tiles.forEach(tile => tile.classList.add('flipped')); | |
| setTimeout(() => { | |
| tiles.forEach(tile => tile.classList.remove('flipped')); | |
| }, 2000); | |
| } | |
| // Flip a tile | |
| function flipTile() { | |
| if (!gameStarted) { | |
| startGame(); | |
| return; | |
| } | |
| if (lockBoard || this.classList.contains('flipped') || this.classList.contains('matched')) { | |
| return; | |
| } | |
| // Play sound | |
| if (audioEnabled) sounds.flip.play(); | |
| this.classList.add('flipped'); | |
| if (!firstTile) { | |
| firstTile = this; | |
| return; | |
| } | |
| secondTile = this; | |
| moves++; | |
| movesDisplay.textContent = moves; | |
| checkForMatch(); | |
| } | |
| // Check if the flipped tiles match | |
| function checkForMatch() { | |
| const isMatch = firstTile.dataset.color === secondTile.dataset.color; | |
| if (isMatch) { | |
| disableTiles(); | |
| // Play match sound | |
| if (audioEnabled) sounds.match.play(); | |
| matchedPairs++; | |
| // Check if all pairs are matched | |
| if (matchedPairs === colorPairs.length / 2) { | |
| setTimeout(endGame, 500); | |
| } | |
| } else { | |
| unflipTiles(); | |
| // Play wrong sound | |
| if (audioEnabled) sounds.wrong.play(); | |
| } | |
| } | |
| // Disable matched tiles | |
| function disableTiles() { | |
| firstTile.classList.add('matched'); | |
| secondTile.classList.add('matched'); | |
| // Add some visual feedback | |
| firstTile.classList.add('pulse-animation'); | |
| secondTile.classList.add('pulse-animation'); | |
| setTimeout(() => { | |
| firstTile.classList.remove('pulse-animation'); | |
| secondTile.classList.remove('pulse-animation'); | |
| }, 1000); | |
| resetBoard(); | |
| } | |
| // Unflip tiles that don't match | |
| function unflipTiles() { | |
| lockBoard = true; | |
| setTimeout(() => { | |
| firstTile.classList.remove('flipped'); | |
| secondTile.classList.remove('flipped'); | |
| resetBoard(); | |
| }, 1000); | |
| } | |
| // Reset the board state | |
| function resetBoard() { | |
| [firstTile, secondTile] = [null, null]; | |
| lockBoard = false; | |
| } | |
| // End the game | |
| function endGame() { | |
| clearInterval(timerInterval); | |
| // Play win sound | |
| if (audioEnabled) sounds.win.play(); | |
| // Update modal with results | |
| modalTime.textContent = timerDisplay.textContent; | |
| modalMoves.textContent = moves; | |
| modalMemory.textContent = `${memoryPercentage}%`; | |
| // Show modal with animation | |
| const modalContent = gameModal.querySelector('.transform'); | |
| gameModal.classList.remove('hidden'); | |
| setTimeout(() => { | |
| modalContent.classList.remove('scale-0'); | |
| modalContent.classList.add('scale-100'); | |
| }, 50); | |
| // Add confetti effect | |
| createConfetti(); | |
| } | |
| // Create confetti effect | |
| function createConfetti() { | |
| const colors = ['#f00', '#0f0', '#00f', '#ff0', '#f0f', '#0ff']; | |
| const container = document.body; | |
| for (let i = 0; i < 100; i++) { | |
| const confetti = document.createElement('div'); | |
| confetti.classList.add('confetti'); | |
| // Random properties | |
| const color = colors[Math.floor(Math.random() * colors.length)]; | |
| const size = Math.random() * 10 + 5; | |
| const posX = Math.random() * window.innerWidth; | |
| const delay = Math.random() * 3; | |
| const duration = Math.random() * 3 + 2; | |
| confetti.style.backgroundColor = color; | |
| confetti.style.width = `${size}px`; | |
| confetti.style.height = `${size}px`; | |
| confetti.style.left = `${posX}px`; | |
| confetti.style.top = '-10px'; | |
| confetti.style.zIndex = '1000'; | |
| // Animation | |
| confetti.style.animation = `fall ${duration}s ease-in ${delay}s forwards`; | |
| // Create keyframes dynamically | |
| const keyframes = ` | |
| @keyframes fall { | |
| to { | |
| transform: translateY(${window.innerHeight + 10}px) rotate(${Math.random() * 360}deg); | |
| opacity: 0; | |
| } | |
| } | |
| `; | |
| const style = document.createElement('style'); | |
| style.innerHTML = keyframes; | |
| document.head.appendChild(style); | |
| container.appendChild(confetti); | |
| // Remove after animation | |
| setTimeout(() => { | |
| confetti.remove(); | |
| style.remove(); | |
| }, (duration + delay) * 1000); | |
| } | |
| } | |
| // Event listeners | |
| startButton.addEventListener('click', initGame); | |
| playAgainButton.addEventListener('click', () => { | |
| const modalContent = gameModal.querySelector('.transform'); | |
| modalContent.classList.remove('scale-100'); | |
| modalContent.classList.add('scale-0'); | |
| setTimeout(() => { | |
| gameModal.classList.add('hidden'); | |
| initGame(); | |
| startGame(); | |
| }, 300); | |
| }); | |
| closeModalButton.addEventListener('click', () => { | |
| const modalContent = gameModal.querySelector('.transform'); | |
| modalContent.classList.remove('scale-100'); | |
| modalContent.classList.add('scale-0'); | |
| setTimeout(() => { | |
| gameModal.classList.add('hidden'); | |
| initGame(); | |
| }, 300); | |
| }); | |
| // Initialize the game | |
| initGame(); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=A3qualityo/game" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |