js實現翻牌遊戲

深海里的星星i發表於2024-08-16
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta
    name="viewport"
    content="width=device-width, initial-scale=1.0"
  >
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    .title {
      width: 512px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin: 10px auto;
    }

    html {
      --wh: 256px;
    }

    .container {
      width: 512px;
      height: 512px;
      margin: 0 auto 0;
      background-color: #eee;
      user-select: none;

    }

    @keyframes hide {
      0% {
        opacity: 1;
      }

      100% {
        opacity: 0;
      }
    }

    .card {
      position: relative;
      width: var(--wh);
      height: var(--wh);
      transform-style: preserve-3d;
      transition: all .2s;
      float: left;
      border: 1px solid #000;

      &.rotate {
        transform: rotateY(180deg);
      }

      &.hide {
        animation: hide 1s forwards;
      }

      .front {
        position: absolute;
        top: 0;
        left: 0;
        z-index: 1;
        width: 100%;
        height: 100%;
        transform: translateZ(1px);
        background-color: pink;
      }

      .after {
        position: absolute;
        top: 0;
        left: 0;
        z-index: 0;
        width: 100%;
        height: 100%;
        transform: translateZ(-1px) rotateY(180deg);
        background-color: yellow;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: calc(var(--wh) / 2)
      }
    }
  </style>
</head>

<body>
  <div class="title">
    <div class="fs">分數: 0</div>
    <div class="timeout">剩餘時間: 180秒</div>
    <button
      class="restart"
      onclick="restart()"
    >重新開始</button>
  </div>
  <div class="container">
    <div class="card rotate">
      <div class="front"></div>
      <div class="after">1</div>
    </div>
  </div>


  <script>
    const container = document.querySelector('.container');
    const fsEl = document.querySelector('.fs')
    const timeout = document.querySelector('.timeout')
    let wh = 256
    let fs = 0
    let isHandle = false
    let time = 180
    let timer = null

    function setTimer() {
      timer & clearInterval(timer)
      timer = setInterval(() => {
        time--
        timeout.innerHTML = `剩餘時間: ${time}秒`
        if (time <= 0) {
          clearInterval(timer)
          alert(`時間到!您的得分為${fs}`)
          restart()
        }
      }, 1000)
    }

    function fsAdd() {
      fsEl.textContent = `分數: ${fs}`
    }

    function render() {
      document.documentElement.style.setProperty('--wh', `${wh}px`)
      const num = (512 / wh) ** 2
      const temp = Array.from({ length: num / 2 }, (_, i) => i + 1)
      const list = [...temp, ...temp]

      const textContent = () => {
        const renderIndex = Math.floor(Math.random() * list.length)
        const val = list[renderIndex]
        list.splice(renderIndex, 1)
        return val
      }
      const els = document.createDocumentFragment()
      for (let i = 0; i < num; i++) {
        const card = document.createElement('div')
        card.classList.add('card')
        const front = document.createElement('div')
        front.classList.add('front')
        const after = document.createElement('div')
        after.classList.add('after')
        after.textContent = textContent()
        card.appendChild(front)
        card.appendChild(after)
        els.appendChild(card)
      }
      container.innerHTML = ''
      container.appendChild(els)
      addEvent()
    }

    render()

    function addEvent() {
      let boxs = document.querySelectorAll('.card')
      boxs.forEach(box => {
        box.addEventListener('click', () => {
          if (isHandle) return
          if (box.innerHTML === '') return
          isHandle = true
          box.classList.toggle('rotate')
          setTimeout(() => {
            checkIsDoublet()
          }, 300)
        })
      })
      setTimer()
    }


    function checkIsDoublet() {
      const boxs = document.querySelectorAll('.card.rotate')
      if (boxs.length === 2) {
        const first = boxs[0].querySelector('.after').textContent
        const second = boxs[1].querySelector('.after').textContent
        if (first === second) {
          console.log('===')

          boxs[0].classList.add('hide')
          boxs[1].classList.add('hide')
          fs += 1
          fsAdd()

          setTimeout(() => {
            boxs[0].innerHTML = ''
            boxs[1].innerHTML = ''
            boxs[0].classList.remove('rotate')
            boxs[1].classList.remove('rotate')
            checkIsAllClear()
          }, 300)
        } else {
          boxs[0].classList.remove('rotate')
          boxs[1].classList.remove('rotate')
          isHandle = false
        }
      } else {
        isHandle = false
      }
    }

    function checkIsAllClear() {
      const fronts = document.querySelectorAll('.card .front')
      console.log(fronts, 'fronts')
      if (!fronts.length) {
        console.log('重新渲染')
        timeout.innerHTML = `剩餘時間: 180秒`
        wh /= 2
        container.innerHTML = ''
        timer & clearInterval(timer)
        time = 180
        render()
      }
      isHandle = false
    }

    function restart() {
      wh = 256
      fs = 0
      time = 180
      timer & clearInterval(timer)
      render()
    }
  </script>
</body>

</html>

相關文章