iT邦幫忙

2021 iThome 鐵人賽

DAY 30
0
Modern Web

前端暴龍機,Vue2.x 進化 Vue3系列 第 30

[前端暴龍機,Vue2.x 進化 Vue3 ] Day30.Vue3 網頁小遊戲(完結篇) | ♾ 台版魷魚遊戲,玩?還是不玩?

/images/emoticon/emoticon49.gif終於~ 來到鐵人賽的最後一天啦
今天的工作就是把小專題剩下的功能給完成,為這次的鐵人賽歡呼~ 完賽啦!!!

我的 vue 翻牌配對小遊戲

修改為按下卡牌後只將該卡牌翻開

<div class="card" @click="transCard(card)" v-for="card in remderCards" :key="card.id">
  <div class="front" :class="{transfront: card.ispair}" :style="{color: card.cardColor}">
    {{ card.cardText }}
  </div>
  <div class="back" :class="{transback: card.ispair}"></div>
</div>

@click 時,將點到的該卡牌 ispair 設定為 true,產生翻牌效果(觸發綁定的 calss)

function transCard(item){
  item.ispair = true;
}

https://ithelp.ithome.com.tw/upload/images/20210826/20120722S5RrvWG7Vq.jpg

完成配對判斷

宣告一個變數存放要配對的第一張牌

 const tempCard = ref({});

改寫,當點選卡牌時,除了要做翻牌的動作,還需要判斷是否配對成功

function transCard(item){
  item.ispair = true;
  if (Object.keys(tempCard.value).length === 0){
    // 紀錄要配對的第一張牌
    tempCard.value = item;
  }else{
    // 判斷是否配對成功
    // 配對成功
    if(item.cardText === tempCard.value.cardText) {
      console.log("配對成功")
    }else{
      console.log("配對失敗")
    }
  }
}

https://ithelp.ithome.com.tw/upload/images/20210826/20120722vhgNRe1EDO.jpg

繼續,把判斷配對寫成一個 function,搭配延遲達到兩張都翻開後再判斷的效果
如果配對成功,我們必需清除暫存的第一張牌,讓我們可以繼續翻下一組的配對
如果配對失敗,則將兩張卡牌恢復覆蓋狀態,同時清除暫存的卡牌,開始新的一組配對

function transCard(item){
  item.ispair = true;
  if (Object.keys(tempCard.value).length === 0){
    // 紀錄要配對的第一張牌
    tempCard.value = item;
  }else{
    // 達到兩張都翻開後在判斷的效果
    setTimeout(()=>{
      checkPair(item)
    },1000);
  }
}

function checkPair(item){
  // 判斷是否配對成功
    if(item.cardText === tempCard.value.cardText) {
      // 配對成功 >> 清除暫存的第一張牌
      tempCard.value = {};
    }else{
      // 配對失敗 >> 兩張卡牌恢復覆蓋狀態
      item.ispair = false;
      resetPrevCard();
    }
}

function resetPrevCard(){
  // 第一張牌恢復覆蓋狀態
  cardlist.value.forEach(ele=>{
    if(ele.id === tempCard.value.id){
      ele.ispair = false;
    }
  })

  // 清除第一張牌的暫存
  tempCard.value = {};
}

https://ithelp.ithome.com.tw/upload/images/20210826/20120722PkgHNEHhq6.jpg
這樣應該算是完成了瑕疵品了 XDD, 下面繼續修改

禁止連續點擊

為了預防點擊過快,還沒判斷完是否配對就可以翻開第三張牌
所以我們需要加上控制器,等待結果出爐才能繼續動作
並且為預防連續點擊到同一張而造成判斷錯誤,需要再加上判斷條件(這個測試超久的~才發現原來是這麼回事 /images/emoticon/emoticon04.gif)

// 控制是否可以繼續翻牌
const canChoose = ref(true);
// 卡片翻面控制
function transCard(item){
  if(canChoose.value === false) return;

  item.ispair = true;
  if (Object.keys(tempCard.value).length === 0){
    // 紀錄要配對的第一張牌
    tempCard.value = item;
  }else{
    // 如果點擊速度太快點到同一張返回
    if(item.id === tempCard.value.id) return;
    // 禁止繼續翻牌
    canChoose.value = false;
    // 達到兩張都翻開後在判斷的效果
    setTimeout(()=>{
      checkPair(item)
    },1000);
  }
}

function checkPair(item){
  // 判斷是否配對成功
    if(item.cardText === tempCard.value.cardText) {

      // 配對成功 
      setTimeout(()=>{
        // 清除暫存的第一張牌
        tempCard.value = {};
        // 允許繼續翻牌
        canChoose.value = true;
      },1000);

    }else{
      // 配對失敗 >> 兩張卡牌恢復覆蓋狀態
      item.ispair = false;
      resetPrevCard();
    }
}

function resetPrevCard(){
  // 第一張牌恢復覆蓋狀態
  cardlist.value.forEach(ele=>{
    if(ele.id === tempCard.value.id){
      ele.ispair = false;

      // 清除第一張牌的暫存
      tempCard.value = {};

      // 允許繼續翻牌
      setTimeout(()=>{
        canChoose.value = true;
      },1000);
    }
  })
}

避免已被翻開的牌又被當成新的配對

原本沒去注意到這點,後來才發現
所以必需要阻擋當點擊卡牌時,要先判斷是否已經是配對過的牌(利用 item.ispair === true)

function transCard(item){
      // 如果還不能翻牌或是該點選的牌已經被翻開了
      if(canChoose.value === false || item.ispair === true) return;
      .......

完成遊戲後可以重新玩一局

這邊運用簡單的計數器做控制,當達成八組的配對,重新打亂順序並把一些變數還原成預設值
所以當配對成功時,計數器做 +1 的動作,使用監聽器監聽當計數器等於八,跳出按鈕可以重新一局


.....

// 監聽是否全部配對成功
const count = ref(0);
watch(count,(newValue)=>{
  if(newValue === 8){
    alert("恭喜挑戰遊戲成功!!!")
  }
})

// 重新一局遊戲
function restartGame(){

  // 計數器歸零
  count.value = 0;

  // 清除第一張牌的暫存
  tempCard.value = {};

  // 重新寫入隨機順序
  randomIdx();
  assignIdx();

  // 還原蓋牌狀態
  cardlist.value.forEach(ele=>{
    ele.ispair = false;
  })
}

return {
  transCard,
  remderCards,
  count,
  restartGame
}

最後,防止作弊

https://ithelp.ithome.com.tw/upload/images/20210830/20120722E7gUPZoZCW.jpg
哈哈,如果被打開開發者工具
那麼會被看到卡牌花色,所以必需先隱藏掉~ 加上 v-if

 <div class="front" :class="{transfront: card.ispair}" :style="{color: card.cardColor}">
    <!--  -->
    <span v-if="card.ispair">{{ card.cardText }}</span>
  </div>

所以只有點擊卡牌作翻牌動作時,才可以顯示
https://ithelp.ithome.com.tw/upload/images/20210830/20120722NJrWcByRJL.jpg
那麼我們就完成了~/images/emoticon/emoticon12.gif

翻牌配對小遊戲演示


完賽心得

很高興自己堅持完30天,終於完賽~
想想還有點不可思議,一開始真的覺得很難,也很怕寫不出來
但是~ 撐過來了~
趁著這30天的鐵人賽文章,剛好讓自己複習 Vue 框架的一些寫法或者一些平時不會去注意的
也很開心在貼人賽開始之前有跟到一波六角學院的 Vue3 夏令營的公開免費活動
讓我跟著前進到 Vue3 ,不然自己可能毫無該怎麼前進到 Vue3 概念(哈哈~

那麼也感謝各位讀者的支持
也恭喜有跟著實作小專題的讀者
現在有了兩個小作品啦~ (應該算作品啦~ XD)

  1. 旅遊小幫手
    ➢ open api 串接
    ➢ vue 的入門實作

  2. 網頁翻牌小遊戲
    ➢ vue3 的入門實作


參考資料

javascript如何判斷Object是空物件 | IT人 wdapp


上一篇
[前端暴龍機,Vue2.x 進化 Vue3 ] Day29.Vue3 網頁小遊戲(一) | ♾ 台版魷魚遊戲,玩?還是不玩?
系列文
前端暴龍機,Vue2.x 進化 Vue330

尚未有邦友留言

立即登入留言