Memory

<!DOCTYPE html>

<html lang=“de“>

<head>

  <meta charset=“UTF-8″>

  <title>Lustiges Memory-Spiel – 10 Emoji-Paare</title>

  <meta name=“viewport“ content=“width=device-width, initial-scale=1.0″>

  <style>

    body {

      background: linear-gradient(135deg, #232946 0%, #5f6caf 100%);

      font-family: ‚Segoe UI‘, ‚Arial‘, sans-serif;

      margin: 0;

      min-height: 100vh;

      color: #fff;

      display: flex;

      flex-direction: column;

      align-items: center;

    }

    header {

      margin-top: 32px;

      margin-bottom: 16px;

      text-align: center;

    }

    h1 {

      font-size: 2.2rem;

      letter-spacing: 1px;

      margin-bottom: 8px;

    }

    .controls {

      display: flex;

      gap: 24px;

      align-items: center;

      justify-content: center;

      margin-bottom: 24px;

    }

    .moves {

      font-size: 1.1rem;

      background: rgba(35,41,70,0.7);

      padding: 6px 18px;

      border-radius: 18px;

      box-shadow: 0 1px 4px rgba(0,0,0,0.08);

    }

    .restart-btn {

      background: linear-gradient(90deg, #ffb800 0%, #ff6f3c 100%);

      color: #232946;

      border: none;

      border-radius: 18px;

      padding: 8px 22px;

      font-size: 1rem;

      font-weight: bold;

      cursor: pointer;

      box-shadow: 0 2px 8px rgba(0,0,0,0.10);

      transition: background 0.2s, transform 0.1s;

    }

    .restart-btn:hover {

      background: linear-gradient(90deg, #ff6f3c 0%, #ffb800 100%);

      transform: scale(1.05);

    }

    .game-board {

      display: grid;

      grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));

      gap: 18px;

      max-width: 480px;

      margin: 0 auto 32px auto;

      width: 100%;

      padding: 0 8px;

    }

    @media (max-width: 600px) {

      .game-board {

        max-width: 340px;

        gap: 12px;

      }

    }

    .card {

      perspective: 800px;

      width: 100%;

      aspect-ratio: 1/1.3;

      cursor: pointer;

      position: relative;

      user-select: none;

      outline: none;

    }

    .card-inner {

      width: 100%;

      height: 100%;

      transition: transform 0.5s cubic-bezier(.4,2,.6,1);

      transform-style: preserve-3d;

      position: relative;

    }

    .card.flipped .card-inner,

    .card.matched .card-inner {

      transform: rotateY(180deg);

    }

    .card-front, .card-back {

      position: absolute;

      width: 100%;

      height: 100%;

      backface-visibility: hidden;

      border-radius: 16px;

      display: flex;

      align-items: center;

      justify-content: center;

      font-size: 2.5rem;

      font-weight: bold;

      box-shadow: 0 2px 12px rgba(0,0,0,0.13);

      transition: box-shadow 0.2s;

    }

    .card-front {

      background: #fff;

      color: #232946;

      transform: rotateY(180deg);

      font-size: 2.7rem;

      letter-spacing: 1px;

      justify-content: center;

      align-items: center;

      display: flex;

    }

    .card-back {

      background: #232946;

      background-image:

        repeating-linear-gradient(135deg, #fff2 0 2px, transparent 2px 20px),

        radial-gradient(circle at 70% 30%, #ffe066 0 2px, transparent 2px 100%),

        radial-gradient(circle at 30% 70%, #ffb800 0 2px, transparent 2px 100%);

      color: #ffe066;

      font-size: 2.1rem;

      display: flex;

      align-items: center;

      justify-content: center;

      transition: box-shadow 0.2s;

    }

    .card:not(.flipped):not(.matched):hover .card-back {

      box-shadow: 0 0 0 4px #ffe06655, 0 2px 12px rgba(0,0,0,0.18);

      filter: brightness(1.08);

    }

    .card.matched .card-inner {

      box-shadow: 0 0 16px 4px #00e67688, 0 2px 12px rgba(0,0,0,0.18);

    }

    .card.matched .card-front {

      border: 3px solid gold;

      box-shadow: 0 0 16px 4px #ffe06688;

      filter: brightness(1.13);

      animation: matched-glow 1.2s infinite alternate;

    }

    @keyframes matched-glow {

      from { box-shadow: 0 0 16px 4px #ffe06688; }

      to   { box-shadow: 0 0 32px 8px #ffe066cc; }

    }

    /* Overlay for win message */

    .overlay {

      position: fixed;

      top: 0; left: 0; right: 0; bottom: 0;

      background: rgba(35,41,70,0.92);

      display: flex;

      flex-direction: column;

      align-items: center;

      justify-content: center;

      z-index: 100;

      color: #ffe066;

      font-size: 2.1rem;

      letter-spacing: 1px;

      opacity: 0;

      pointer-events: none;

      transition: opacity 0.4s;

    }

    .overlay.show {

      opacity: 1;

      pointer-events: all;

    }

    .overlay .congrats {

      font-size: 2.5rem;

      margin-bottom: 18px;

      font-weight: bold;

      text-shadow: 0 2px 12px #232946;

    }

    .overlay .moves {

      color: #fff;

      font-size: 1.2rem;

      margin-bottom: 24px;

    }

    .overlay .restart-btn {

      font-size: 1.1rem;

      padding: 10px 28px;

    }

    /* Remove tap highlight on mobile */

    .card, .restart-btn {

      -webkit-tap-highlight-color: transparent;

    }

  </style>

</head>

<body>

  <header>

    <h1>🎲 Lustiges Memory-Spiel</h1>

    <div class=“controls“>

      <span class=“moves“>Züge: <span id=“moveCounter“>0</span></span>

      <button class=“restart-btn“ id=“restartBtn“>🔄 Neues Spiel</button>

    </div>

  </header>

  <main>

    <div class=“game-board“ id=“gameBoard“></div>

  </main>

  <div class=“overlay“ id=“winOverlay“>

    <div class=“congrats“>🎉 Glückwunsch! 🎉</div>

    <div class=“moves“>Du hast das Spiel in <span id=“finalMoves“>0</span> Zügen geschafft!</div>

    <button class=“restart-btn“ id=“overlayRestartBtn“>Nochmal spielen</button>

  </div>

  <script>

    // Emoji Motive

    const EMOJIS = [‚🤡‘,’🎃‘,’👾‘,’🦄‘,’🐸‘,’🤖‘,’👻‘,’🦊‘,’🎯‘,’🍕‘];

    const PAIRS = 10;

    let cards = [];

    let flippedCards = [];

    let matchedCount = 0;

    let moves = 0;

    let lockBoard = false;

    const gameBoard = document.getElementById(‚gameBoard‘);

    const moveCounter = document.getElementById(‚moveCounter‘);

    const restartBtn = document.getElementById(‚restartBtn‘);

    const winOverlay = document.getElementById(‚winOverlay‘);

    const finalMoves = document.getElementById(‚finalMoves‘);

    const overlayRestartBtn = document.getElementById(‚overlayRestartBtn‘);

    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 createCards() {

      // Create 2 of each emoji, assign unique IDs

      let cardData = [];

      EMOJIS.forEach((emoji, idx) => {

        cardData.push({emoji, id: idx + ‚a‘});

        cardData.push({emoji, id: idx + ‚b‘});

      });

      return shuffle(cardData);

    }

    function renderBoard() {

      gameBoard.innerHTML = “;

      cards = createCards();

      matchedCount = 0;

      moves = 0;

      flippedCards = [];

      lockBoard = false;

      moveCounter.textContent = ‚0‘;

      cards.forEach((card, idx) => {

        const cardElem = document.createElement(‚div‘);

        cardElem.className = ‚card‘;

        cardElem.tabIndex = 0;

        cardElem.dataset.emoji = card.emoji;

        cardElem.dataset.id = card.id;

        cardElem.innerHTML = `

          <div class=“card-inner“>

            <div class=“card-front“>${card.emoji}</div>

            <div class=“card-back“>⭐</div>

          </div>

        `;

        cardElem.addEventListener(‚click‘, () => handleCardClick(cardElem));

        cardElem.addEventListener(‚keydown‘, (e) => {

          if (e.key === ‚Enter‘ || e.key === ‚ ‚) {

            e.preventDefault();

            handleCardClick(cardElem);

          }

        });

        gameBoard.appendChild(cardElem);

      });

    }

    function handleCardClick(cardElem) {

      if (lockBoard) return;

      if (cardElem.classList.contains(‚flipped‘) || cardElem.classList.contains(‚matched‘)) return;

      if (flippedCards.length === 2) return;

      cardElem.classList.add(‚flipped‘);

      flippedCards.push(cardElem);

      if (flippedCards.length === 2) {

        moves++;

        moveCounter.textContent = moves;

        const [card1, card2] = flippedCards;

        if (card1.dataset.emoji === card2.dataset.emoji) {

          // Match!

          setTimeout(() => {

            card1.classList.add(‚matched‘);

            card2.classList.add(‚matched‘);

            flippedCards = [];

            matchedCount++;

            if (matchedCount === PAIRS) {

              setTimeout(showWinOverlay, 600);

            }

          }, 350);

        } else {

          // Not a match

          lockBoard = true;

          setTimeout(() => {

            card1.classList.remove(‚flipped‘);

            card2.classList.remove(‚flipped‘);

            flippedCards = [];

            lockBoard = false;

          }, 1000);

        }

      }

    }

    function showWinOverlay() {

      finalMoves.textContent = moves;

      winOverlay.classList.add(’show‘);

    }

    function hideWinOverlay() {

      winOverlay.classList.remove(’show‘);

    }

    function restartGame() {

      hideWinOverlay();

      renderBoard();

    }

    // Event Listeners

    restartBtn.addEventListener(‚click‘, restartGame);

    overlayRestartBtn.addEventListener(‚click‘, restartGame);

    // Start game on load

    renderBoard();

  </script>

</body>

</html>