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> |