Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', () => { | |
| // Game state | |
| let gameState = { | |
| score: 0, | |
| level: 1, | |
| moves: 0, | |
| boardSize: 4, | |
| tiles: [], | |
| matchedPairs: 0, | |
| firstSelected: null, | |
| secondSelected: null, | |
| waiting: false, | |
| hintActive: false | |
| }; | |
| // DOM elements | |
| const gameBoard = document.querySelector('custom-game-board'); | |
| const scorePanel = document.querySelector('custom-score-panel'); | |
| const newGameBtn = document.getElementById('newGameBtn'); | |
| const hintBtn = document.getElementById('hintBtn'); | |
| // Initialize game | |
| function initGame() { | |
| // Add visual feedback | |
| newGameBtn.innerHTML = '<span class="animate-pulse">Creating...</span>'; | |
| setTimeout(() => { | |
| gameState = { | |
| score: 0, | |
| level: 1, | |
| moves: 0, | |
| boardSize: 4, | |
| tiles: generateTiles(4), | |
| matchedPairs: 0, | |
| firstSelected: null, | |
| secondSelected: null, | |
| waiting: false, | |
| hintActive: false | |
| }; | |
| // Set up event listener for tile clicks | |
| gameBoard.addEventListener('tile-click', (e) => { | |
| handleTileClick(e.detail.index); | |
| }); | |
| updateScorePanel(); | |
| renderBoard(); | |
| // Add success animation | |
| newGameBtn.innerHTML = 'New Puzzle'; | |
| newGameBtn.classList.add('bg-green-500'); | |
| setTimeout(() => { | |
| newGameBtn.classList.remove('bg-green-500'); | |
| newGameBtn.classList.add('bg-purple-600'); | |
| }, 1000); | |
| // Play sound for feedback | |
| if (typeof Audio !== 'undefined') { | |
| const audio = new Audio('https://assets.mixkit.co/sfx/preview/mixkit-positive-interface-beep-221.mp3'); | |
| audio.volume = 0.3; | |
| audio.play(); | |
| } | |
| }, 500); | |
| } | |
| // Generate tiles for the board | |
| function generateTiles(size) { | |
| const totalPairs = (size * size) / 2; | |
| const symbols = []; | |
| // Generate unique symbols | |
| for (let i = 0; i < totalPairs; i++) { | |
| symbols.push(String.fromCharCode(65 + i)); | |
| symbols.push(String.fromCharCode(65 + i)); | |
| } | |
| // Shuffle the symbols | |
| return shuffleArray(symbols); | |
| } | |
| // Fisher-Yates shuffle 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; | |
| } | |
| // Render the game board | |
| function renderBoard() { | |
| gameBoard.setAttribute('size', gameState.boardSize); | |
| gameBoard.setAttribute('tiles', JSON.stringify(gameState.tiles)); | |
| } | |
| // Update score panel | |
| function updateScorePanel() { | |
| scorePanel.setAttribute('score', gameState.score); | |
| scorePanel.setAttribute('level', gameState.level); | |
| scorePanel.setAttribute('moves', gameState.moves); | |
| } | |
| // Handle tile click | |
| function handleTileClick(index) { | |
| if (gameState.waiting || gameState.tiles[index] === null || index === gameState.firstSelected) { | |
| return; | |
| } | |
| if (gameState.firstSelected === null) { | |
| gameState.firstSelected = index; | |
| gameBoard.setAttribute('selected', index.toString()); | |
| } else { | |
| gameState.secondSelected = index; | |
| gameState.moves++; | |
| checkForMatch(); | |
| } | |
| } | |
| // Check if the selected tiles match | |
| function checkForMatch() { | |
| const firstIndex = gameState.firstSelected; | |
| const secondIndex = gameState.secondSelected; | |
| if (gameState.tiles[firstIndex] === gameState.tiles[secondIndex]) { | |
| // Match found | |
| gameState.tiles[firstIndex] = null; | |
| gameState.tiles[secondIndex] = null; | |
| gameState.matchedPairs++; | |
| gameState.score += 10 * gameState.level; | |
| // Check for level completion | |
| if (gameState.matchedPairs === (gameState.boardSize * gameState.boardSize) / 2) { | |
| setTimeout(() => { | |
| levelUp(); | |
| }, 1000); | |
| } | |
| gameBoard.setAttribute('matched', `${firstIndex},${secondIndex}`); | |
| } else { | |
| // No match | |
| gameState.waiting = true; | |
| setTimeout(() => { | |
| gameBoard.removeAttribute('selected'); | |
| gameState.waiting = false; | |
| }, 1000); | |
| } | |
| gameState.firstSelected = null; | |
| gameState.secondSelected = null; | |
| updateScorePanel(); | |
| } | |
| // Level up the game | |
| function levelUp() { | |
| gameState.level++; | |
| gameState.boardSize = Math.min(8, gameState.boardSize + 2); // Max size 8x8 | |
| gameState.tiles = generateTiles(gameState.boardSize); | |
| gameState.matchedPairs = 0; | |
| updateScorePanel(); | |
| renderBoard(); | |
| } | |
| // Give hint | |
| function giveHint() { | |
| if (gameState.hintActive) return; | |
| gameState.hintActive = true; | |
| hintBtn.classList.add('bg-purple-600'); | |
| // Find first unmatched pair | |
| let firstUnmatched = null; | |
| for (let i = 0; i < gameState.tiles.length; i++) { | |
| if (gameState.tiles[i] !== null) { | |
| if (firstUnmatched === null) { | |
| firstUnmatched = i; | |
| } else if (gameState.tiles[i] === gameState.tiles[firstUnmatched]) { | |
| gameBoard.setAttribute('hint', `${firstUnmatched},${i}`); | |
| break; | |
| } | |
| } | |
| } | |
| setTimeout(() => { | |
| gameBoard.removeAttribute('hint'); | |
| gameState.hintActive = false; | |
| hintBtn.classList.remove('bg-purple-600'); | |
| }, 2000); | |
| } | |
| // Event listeners | |
| newGameBtn.addEventListener('click', initGame); | |
| hintBtn.addEventListener('click', giveHint); | |
| // Initialize the game | |
| initGame(); | |
| }); |