🧠 Memory – JavaScript Spiel programmieren

In dieser Anleitung lernst du Schritt für Schritt, wie du das klassische Memory (Paare finden) Spiel in JavaScript programmierst. Du baust ein Spiel mit 20 Karten (10 Paaren) und schönen Symbolen.

📝 Was du brauchst:
✅ Einen Texteditor (z.B. Notepad, VS Code)
✅ Einen Webbrowser (Chrome, Firefox, Safari)
✅ Lust auf ein kniffliges Gedächtnisspiel!

🎯 Das fertige Memory-Spiel – zum Ausprobieren!

Klicke auf Karten und finde die passenden Paare!

🧠 MEMORY 20 Karten

🎯 Finde die Paare!
💡 Klicke auf zwei Karten – finde das passende Paar!

📚 Schritt-für-Schritt Anleitung

Kopiere den Code aus jedem Schritt in deine Datei und teste ihn!

1

HTML-Grundgerüst erstellen

Erstelle eine neue Datei mit dem Namen memory.html. Füge dieses Grundgerüst ein:

<!DOCTYPE html> <html> <head> <title>Memory</title> <style> body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: #1a1a2e; font-family: Arial, sans-serif; margin: 0; padding: 20px; } .container { background: #2d2d44; padding: 30px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); text-align: center; } .grid { display: grid; grid-template-columns: repeat(5, 80px); gap: 10px; margin: 20px 0; } .card { width: 80px; height: 80px; background: #4a6fa5; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 36px; cursor: pointer; transition: all 0.3s; color: white; border: 2px solid #6a8fc5; user-select: none; } .card.flipped { background: #2d2d44; border-color: #89b4fa; } .card.matched { background: #2d5a2d; border-color: #6bcb77; cursor: default; opacity: 0.7; } .card:hover:not(.flipped):not(.matched) { transform: scale(1.05); } .status { color: white; font-size: 22px; margin: 15px 0; } .reset { background: #ff6b6b; border: none; color: white; padding: 10px 30px; border-radius: 10px; font-size: 18px; cursor: pointer; } </style> </head> <body> <div class="container"> <h1 style="color: white;">🧠 Memory</h1> <div class="grid" id="grid"></div> <div class="status" id="status">Finde die Paare!</div> <button class="reset" id="reset">🔄 Neues Spiel</button> </div> <script> // Hier kommt später der JavaScript-Code rein console.log("Memory geladen!"); </script> </body> </html>
✅ Teste es! Öffne die Datei im Browser. Du siehst einen leeren Bereich mit Überschrift und Button.
2

Symbole und Spielvariablen definieren

Ersetze den Inhalt von <script> mit diesem Code:

// ====== 1. Symbole (10 verschiedene) ====== const SYMBOLS = ['🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼', '🐨', '🐯']; // ====== 2. DOM-Elemente ====== const grid = document.getElementById('grid'); const statusDisplay = document.getElementById('status'); const resetButton = document.getElementById('reset'); // ====== 3. Spielvariablen ====== let cards = []; let flippedCards = []; let matchedPairs = 0; let isLocked = false; let moves = 0; let timer = null; let seconds = 0; console.log('✅ Memory geladen! Symbole:', SYMBOLS);
✅ Teste es! In der Konsole siehst du die Symbole und die Meldung.
3

Karten mischen und anzeigen

Füge diese Funktionen hinzu:

// ====== 4. Karten mischen ====== function shuffle(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; } // ====== 5. Spiel initialisieren ====== function initGame() { // 10 Paare = 20 Karten let deck = [...SYMBOLS, ...SYMBOLS]; deck = shuffle(deck); cards = deck.map((symbol, index) => ({ id: index, symbol: symbol, flipped: false, matched: false })); flippedCards = []; matchedPairs = 0; isLocked = false; moves = 0; seconds = 0; clearInterval(timer); timer = null; renderCards(); updateStatus(); } // ====== 6. Karten rendern ====== function renderCards() { grid.innerHTML = ''; cards.forEach((card, index) => { const cardElement = document.createElement('div'); cardElement.className = 'card'; cardElement.dataset.index = index; // Alle Karten sind zuerst umgedreht (flipped = false) if (card.flipped) { cardElement.classList.add('flipped'); cardElement.textContent = card.symbol; } else { cardElement.textContent = '?'; } if (card.matched) { cardElement.classList.add('matched'); cardElement.textContent = card.symbol; } cardElement.addEventListener('click', () => handleCardClick(index)); grid.appendChild(cardElement); }); } // ====== 7. Status aktualisieren ====== function updateStatus() { const totalPairs = SYMBOLS.length; if (matchedPairs === totalPairs) { statusDisplay.textContent = `🎉 Gewonnen! ${moves} Züge, ${seconds}s`; } else { statusDisplay.textContent = `🧠 ${matchedPairs}/${totalPairs} Paare gefunden • ${moves} Züge`; } } // Spiel starten initGame();
✅ Teste es! Du siehst 20 Karten mit "?" – das sind deine verdeckten Memory-Karten!
4

Klick-Logik: Karten umdrehen und Paare prüfen

Füge diese Funktionen hinzu:

// ====== 8. Karte umdrehen ====== function flipCard(index) { const card = cards[index]; if (card.flipped || card.matched || isLocked) return false; card.flipped = true; flippedCards.push(index); renderCards(); return true; } // ====== 9. Karten vergleichen ====== function checkMatch() { const [idx1, idx2] = flippedCards; const card1 = cards[idx1]; const card2 = cards[idx2]; if (card1.symbol === card2.symbol) { // Paar gefunden! card1.matched = true; card2.matched = true; matchedPairs++; flippedCards = []; updateStatus(); renderCards(); // Prüfen ob gewonnen if (matchedPairs === SYMBOLS.length) { clearInterval(timer); statusDisplay.textContent = `🎉 Gewonnen! ${moves} Züge, ${seconds}s`; } return true; } return false; } // ====== 10. Karten zurücksetzen (bei falschem Paar) ====== function resetFlipped() { isLocked = true; setTimeout(() => { cards.forEach((card) => { if (card.flipped && !card.matched) { card.flipped = false; } }); flippedCards = []; isLocked = false; renderCards(); }, 600); } // ====== 11. Klick-Handler ====== function handleCardClick(index) { if (isLocked) return; if (flippedCards.length >= 2) return; if (cards[index].flipped || cards[index].matched) return; // Timer starten beim ersten Zug if (moves === 0 && matchedPairs === 0) { timer = setInterval(() => { seconds++; if (matchedPairs < SYMBOLS.length) { updateStatus(); } }, 1000); } flipCard(index); moves++; if (flippedCards.length === 2) { const match = checkMatch(); if (!match) { resetFlipped(); } updateStatus(); } else { updateStatus(); } }
✅ Teste es! Klicke auf Karten – sie drehen sich um und zeigen Symbole! Finde zwei gleiche – sie bleiben offen!
5

Reset-Button und Timer

Füge den Reset-Button und den Timer-Code hinzu:

// ====== 12. Spiel zurücksetzen ====== function resetGame() { clearInterval(timer); timer = null; seconds = 0; initGame(); } // ====== 13. Event-Listener ====== resetButton.addEventListener('click', resetGame); // Spiel starten initGame();
✅ Teste es! Klicke auf "Neues Spiel" – das Spiel wird zurückgesetzt! Der Timer startet beim ersten Klick und stoppt, wenn alle Paare gefunden sind.

📋 Kompletter Code – perfekt zum Reinkopieren!

Hier ist der ganze Memory-Code mit allen Funktionen.

<!DOCTYPE html> <html> <head> <title>Memory</title> <style> body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: #1a1a2e; font-family: Arial, sans-serif; margin: 0; padding: 20px; } .container { background: #2d2d44; padding: 30px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); text-align: center; max-width: 700px; width: 100%; } .grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin: 20px 0; } .card { aspect-ratio: 1 / 1; background: #4a6fa5; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 36px; cursor: pointer; transition: all 0.3s; color: white; border: 2px solid #6a8fc5; user-select: none; font-weight: bold; } .card.flipped { background: #2d2d44; border-color: #89b4fa; } .card.matched { background: #2d5a2d; border-color: #6bcb77; cursor: default; opacity: 0.8; } .card:hover:not(.flipped):not(.matched) { transform: scale(1.05); border-color: #89b4fa; } .status { color: white; font-size: 22px; margin: 15px 0; padding: 10px; background: #1a1a2e; border-radius: 10px; } .reset { background: #ff6b6b; border: none; color: white; padding: 10px 30px; border-radius: 10px; font-size: 18px; cursor: pointer; transition: all 0.2s; } .reset:hover { transform: scale(1.05); } @media (max-width: 500px) { .card { font-size: 24px; } .grid { gap: 6px; } } @media (max-width: 380px) { .card { font-size: 18px; } } </style> </head> <body> <div class="container"> <h1 style="color: white;">🧠 Memory</h1> <div class="grid" id="grid"></div> <div class="status" id="status">Finde die Paare!</div> <button class="reset" id="reset">🔄 Neues Spiel</button> </div> <script> const SYMBOLS = ['🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼', '🐨', '🐯']; const grid = document.getElementById('grid'); const statusDisplay = document.getElementById('status'); const resetButton = document.getElementById('reset'); let cards = []; let flippedCards = []; let matchedPairs = 0; let isLocked = false; let moves = 0; let timer = null; let seconds = 0; function shuffle(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; } function initGame() { let deck = [...SYMBOLS, ...SYMBOLS]; deck = shuffle(deck); cards = deck.map((symbol, index) => ({ id: index, symbol: symbol, flipped: false, matched: false })); flippedCards = []; matchedPairs = 0; isLocked = false; moves = 0; seconds = 0; clearInterval(timer); timer = null; renderCards(); updateStatus(); } function renderCards() { grid.innerHTML = ''; cards.forEach((card, index) => { const cardElement = document.createElement('div'); cardElement.className = 'card'; cardElement.dataset.index = index; if (card.flipped || card.matched) { cardElement.classList.add('flipped'); cardElement.textContent = card.symbol; } else { cardElement.textContent = '?'; } if (card.matched) { cardElement.classList.add('matched'); } cardElement.addEventListener('click', () => handleCardClick(index)); grid.appendChild(cardElement); }); } function updateStatus() { const totalPairs = SYMBOLS.length; if (matchedPairs === totalPairs) { statusDisplay.textContent = `🎉 Gewonnen! ${moves} Züge, ${seconds}s`; } else { statusDisplay.textContent = `🧠 ${matchedPairs}/${totalPairs} Paare • ${moves} Züge`; } } function flipCard(index) { const card = cards[index]; if (card.flipped || card.matched || isLocked) return false; card.flipped = true; flippedCards.push(index); renderCards(); return true; } function checkMatch() { const [idx1, idx2] = flippedCards; const card1 = cards[idx1]; const card2 = cards[idx2]; if (card1.symbol === card2.symbol) { card1.matched = true; card2.matched = true; matchedPairs++; flippedCards = []; updateStatus(); renderCards(); if (matchedPairs === SYMBOLS.length) { clearInterval(timer); statusDisplay.textContent = `🎉 Gewonnen! ${moves} Züge, ${seconds}s`; } return true; } return false; } function resetFlipped() { isLocked = true; setTimeout(() => { cards.forEach((card) => { if (card.flipped && !card.matched) { card.flipped = false; } }); flippedCards = []; isLocked = false; renderCards(); }, 600); } function handleCardClick(index) { if (isLocked) return; if (flippedCards.length >= 2) return; if (cards[index].flipped || cards[index].matched) return; if (moves === 0 && matchedPairs === 0) { timer = setInterval(() => { seconds++; if (matchedPairs < SYMBOLS.length) { updateStatus(); } }, 1000); } flipCard(index); moves++; if (flippedCards.length === 2) { const match = checkMatch(); if (!match) { resetFlipped(); } updateStatus(); } else { updateStatus(); } } function resetGame() { clearInterval(timer); timer = null; seconds = 0; initGame(); } resetButton.addEventListener('click', resetGame); initGame(); </script> </body> </html>
🎯 JETZT BIST DU DRAN!
1. Kopiere den kompletten Code in eine neue Datei.
2. Speichere sie als memory.html.
3. Öffne die Datei im Browser.
4. Finde alle Paare – viel Spaß!

💡 Erweiterungsideen:
- Füge mehr Symbole hinzu (z.B. 🦄, 🐉, 🐧)
- Ändere die Anzahl der Karten (z.B. 4x4 = 16 Karten)
- Füge einen Highscore (bestes Ergebnis) hinzu

🎉 GLÜCKWUNSCH!
Du hast dein eigenes Memory-Spiel programmiert!
Du hast gelernt, wie man Karten mischt, umdreht und Paare findet –
und sogar einen Timer eingebaut!
🔄 Seite neu laden