Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Word Match Puzzle</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <style> | |
| .card { | |
| perspective: 1000px; | |
| transition: all 0.3s ease; | |
| } | |
| .card-inner { | |
| position: relative; | |
| width: 100%; | |
| height: 100%; | |
| text-align: center; | |
| transition: transform 0.6s; | |
| transform-style: preserve-3d; | |
| } | |
| .card.flipped .card-inner { | |
| transform: rotateY(180deg); | |
| } | |
| .card-front, .card-back { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| backface-visibility: hidden; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| border-radius: 0.5rem; | |
| } | |
| .card-front { | |
| background-color: #3b82f6; | |
| color: white; | |
| } | |
| .card-back { | |
| background-color: #10b981; | |
| color: white; | |
| transform: rotateY(180deg); | |
| } | |
| .matched { | |
| opacity: 0.5; | |
| transform: scale(0.95); | |
| } | |
| @keyframes celebration { | |
| 0% { transform: scale(1); } | |
| 50% { transform: scale(1.2); } | |
| 100% { transform: scale(1); } | |
| } | |
| .celebrate { | |
| animation: celebration 0.5s ease; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-100 min-h-screen flex flex-col items-center justify-center p-4"> | |
| <div class="text-center mb-8"> | |
| <h1 class="text-3xl font-bold text-blue-600 mb-2">Word Match Puzzle</h1> | |
| <p class="text-gray-700">Match the 3-letter word cards to win!</p> | |
| <div class="mt-4 flex gap-4 justify-center"> | |
| <div class="bg-white p-3 rounded-lg shadow"> | |
| <span class="font-semibold">Matches:</span> <span id="matches">0</span>/4 | |
| </div> | |
| <div class="bg-white p-3 rounded-lg shadow"> | |
| <span class="font-semibold">Attempts:</span> <span id="attempts">0</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-4 gap-4 max-w-2xl mb-8" id="game-board"> | |
| <!-- Cards will be generated here by JavaScript --> | |
| </div> | |
| <button id="reset-btn" class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-6 rounded-full transition"> | |
| Reset Game | |
| </button> | |
| <div id="win-message" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden"> | |
| <div class="bg-white p-8 rounded-lg shadow-xl text-center max-w-md"> | |
| <h2 class="text-2xl font-bold text-green-500 mb-4">Congratulations! 🎉</h2> | |
| <p class="text-gray-700 mb-6">You matched all the words in <span id="final-attempts" class="font-bold">0</span> attempts!</p> | |
| <button id="play-again-btn" class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-6 rounded-full transition"> | |
| Play Again | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Game data | |
| const words = ['CAT', 'DOG', 'SUN', 'CAR', 'BAT', 'BED', 'HAT', 'PEN']; | |
| let cards = []; | |
| let flippedCards = []; | |
| let matches = 0; | |
| let attempts = 0; | |
| let canFlip = true; | |
| // DOM elements | |
| const gameBoard = document.getElementById('game-board'); | |
| const matchesDisplay = document.getElementById('matches'); | |
| const attemptsDisplay = document.getElementById('attempts'); | |
| const resetBtn = document.getElementById('reset-btn'); | |
| const winMessage = document.getElementById('win-message'); | |
| const playAgainBtn = document.getElementById('play-again-btn'); | |
| const finalAttemptsDisplay = document.getElementById('final-attempts'); | |
| // Initialize game | |
| initGame(); | |
| // Event listeners | |
| resetBtn.addEventListener('click', initGame); | |
| playAgainBtn.addEventListener('click', initGame); | |
| function initGame() { | |
| // Reset game state | |
| cards = []; | |
| flippedCards = []; | |
| matches = 0; | |
| attempts = 0; | |
| canFlip = true; | |
| // Update displays | |
| matchesDisplay.textContent = matches; | |
| attemptsDisplay.textContent = attempts; | |
| // Clear game board | |
| gameBoard.innerHTML = ''; | |
| // Hide win message | |
| winMessage.classList.add('hidden'); | |
| // Create pairs of words | |
| const gameWords = [...words].sort(() => 0.5 - Math.random()).slice(0, 4); | |
| const wordPairs = [...gameWords, ...gameWords].sort(() => 0.5 - Math.random()); | |
| // Create cards | |
| wordPairs.forEach((word, index) => { | |
| const card = document.createElement('div'); | |
| card.className = 'card h-24 w-24 cursor-pointer'; | |
| card.dataset.index = index; | |
| card.dataset.word = word; | |
| card.innerHTML = ` | |
| <div class="card-inner"> | |
| <div class="card-front font-bold text-xl">?</div> | |
| <div class="card-back font-bold text-xl">${word}</div> | |
| </div> | |
| `; | |
| card.addEventListener('click', flipCard); | |
| gameBoard.appendChild(card); | |
| cards.push(card); | |
| }); | |
| } | |
| function flipCard() { | |
| if (!canFlip || this.classList.contains('flipped') || this.classList.contains('matched')) { | |
| return; | |
| } | |
| // Flip the card | |
| this.classList.add('flipped'); | |
| flippedCards.push(this); | |
| // Check for match when two cards are flipped | |
| if (flippedCards.length === 2) { | |
| canFlip = false; | |
| attempts++; | |
| attemptsDisplay.textContent = attempts; | |
| // Check if words match | |
| if (flippedCards[0].dataset.word === flippedCards[1].dataset.word) { | |
| // Match found | |
| setTimeout(() => { | |
| flippedCards.forEach(card => { | |
| card.classList.add('matched'); | |
| card.classList.add('celebrate'); | |
| setTimeout(() => card.classList.remove('celebrate'), 500); | |
| }); | |
| matches++; | |
| matchesDisplay.textContent = matches; | |
| flippedCards = []; | |
| canFlip = true; | |
| // Check for win | |
| if (matches === 4) { | |
| setTimeout(() => { | |
| finalAttemptsDisplay.textContent = attempts; | |
| winMessage.classList.remove('hidden'); | |
| }, 500); | |
| } | |
| }, 500); | |
| } else { | |
| // No match | |
| setTimeout(() => { | |
| flippedCards.forEach(card => { | |
| card.classList.remove('flipped'); | |
| }); | |
| flippedCards = []; | |
| canFlip = true; | |
| }, 1000); | |
| } | |
| } | |
| } | |
| }); | |
| </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=suri/word-match-puzzle" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |