[前端暴龙机,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


<<:  [第24天]理财达人Mx. Ada-RSI指标

>>:  Icebear的参赛心得

[Day30] - 完赛、感想、心得

Day30 - 完赛、感想、心得 心得 坚持 - 坚持阿,哪次不坚持 当初觉得30天应该不难吧,就每...

[day8]FASTAPI建置示范-进度落後了!!

FASTAPI建置 非常快速的简介 过去讲到PYTHON建置API,大多会想到Flask以及Djan...

[Day 3]从零开始学习 JS 的连续-30 Days---字串

宣告变数的资料型别 1.数值( Number ) 2.字串( String ) 3.布林值( Boo...

【Day 27】差点被我遗忘的 x AWS RDS on Outpost x 云端资料库储存

tags: 铁人赛 AWS RDS Outposts database 前情提要 差点就跟蔡琴一样,...

Day28 - 储存帐密及自动登入

今天来做储存帐密和自动登入的功能。 提醒:今天的内容缺少了加密储存密码,是极度危险的功能,这部份预计...