最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

阿望教你用vue寫掃雷小游戲

 更新時間:2020年01月20日 08:36:38   作者:Awang  
這篇文章主要介紹了阿望教你用vue寫掃雷小游戲,本文通過實例代碼效果圖展示的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下

前言

話說阿望還在大學時,某一天寢室突然停網(wǎng)了,于是和室友兩人不約而同地打開了掃雷,比相同難度下誰更快找出全部的雷,玩得不亦樂乎,就這樣,掃雷伴我們度過了斷網(wǎng)的一周,是整整一周啊,不用上課的那種,可想而知我們是有多無聊了。

這兩天臨近過年了,該放假的已經(jīng)放假了,不該放假的已經(jīng)請假了,公交不打擠了,地鐵口不堵了,公司也去了大半部分的人了,就留阿望這種不得不留下來值班的人守著空蕩蕩的辦公室了,于是,多年前那種無所事事的斷網(wǎng)心態(tài)再次襲來,于是,想玩掃雷的心再次蹦跶出來,于是,點開了電腦的附件,于是,發(fā)現(xiàn)我的電腦上并沒有掃雷【手動微笑.jpg】。

怎么想起要寫掃雷的阿望就不多廢話了,直接開干。

掃雷游戲規(guī)則

想當年阿望還是在大學才參透掃雷的游戲規(guī)則的,初高中的時候都是靠運氣瞎點,從沒贏過,當然了,境界提升以后,追求的自然就不是贏了,而是速度。

來,看規(guī)則:

大白話游戲規(guī)則,計算邏輯如下:

游戲開始,選擇難度 鼠標左鍵隨機點開一個格子A(你想用右鍵標雷也可以) 左鍵點擊后一共有三種情況 1) 是數(shù)字,假設是2,表示以該格子A為中心的九宮格除了該格子以外的8個格子內(nèi)有2個雷 2)是空白,表示以該格子A為中心的九宮格除了該格子以外的8個格子內(nèi)沒有雷,并且系統(tǒng)計算分別以這8個格子為中心九宮格除了該格子以外的8個格子是否是空白 a. 是空白,繼續(xù)計算以這8個格子為中心九宮格除了該格子以外的8個格子是否是空白,循環(huán)擴散 b. 是格子邊界,停止邊界擴散 c. 是數(shù)字,數(shù)字格子翻出來顯示,停止擴散 3)是雷,game over 了。。。 如果點第一次只翻了一個數(shù)字是比較難開始游戲的,如果第一次翻了一大片出來,恭喜你,可以開始秀你的智商了,在確認是雷點的格子點右鍵,即可標記地雷格,表示你認定這個格子是地雷 如果數(shù)字周圍的雷被全部標記出來了,但數(shù)字周圍還有沒被翻開的格子的話,雙擊該格子,自動將其他格子翻開

好,這下規(guī)則我們了解了,接下來,摩拳擦掌,開始寫代碼咯,本次代碼用vue來寫,沒有原因,習慣了而已。

掃雷代碼邏輯

看著游戲規(guī)則,我們先來理一理,要如何完成這個功能,我們以最簡單的,最能使人理解的步驟,來完成這次功能。

  1. 難度選擇
  2. 根據(jù)選擇的游戲難度繪制游戲主界面,就是格盤
  3. 根據(jù)選擇的游戲難度隨機生成地雷放到盤中
  4. 計算每個格子周圍的雷數(shù)
  5. 完成用戶交互(左鍵點擊翻格子,右鍵點擊放雷)
  6. 空白格擴散翻格子
  7. 計算游戲結(jié)束

生成項目

避免vue新手不知如何下手,那就從建項目開始吧,環(huán)境安裝我就不講了,腳手架也是要有的

第一步,初始化lovesweeping工程(阿望不喜歡地雷,喜歡小桃心)

項目很小,不需要路由,不需要vuex,即可完成,只帶了sass,連eslint都可以不要,看官們可以根據(jù)自己的喜好建項目

項目生成之后,helloworld就可以刪掉了,它的存在并沒有什么意義

文件切分

這一步主要是構(gòu)建工程結(jié)構(gòu),簡單畫一下主要的幾個文件

- src
 - components
  - SelectLevel.vue [新增,難度選擇組件]
  - LoveSweeping.vue [新增,游戲界面組件]
 - App.vue [父組件,負責組件間的切換和某些數(shù)據(jù)傳遞]
 - main.js
- package.json

好,初步認識了項目結(jié)構(gòu)以后,咱把該新建的建好,可以不加東西,不報錯就行

然后就是把組件間的切換代碼寫好,再來一步步的填充代碼

難度選擇

這一步很簡單,首先畫好難度選擇的頁面,難度可以自己設置,你覺得合理就行,我這里的數(shù)據(jù)格式是這樣的,用一個對象表示一個難度等級,對象中包含了難度描述,以及難度設置,設置中包含了格子橫排數(shù),格子縱排數(shù),雷數(shù)

// 難度
 level: [
  {
   text: '青銅', // 難度描述
   value: [9, 9, 10] // 格子橫排數(shù),格子縱排數(shù),雷數(shù)
  }, {
   text: '黃金',
   value: [12, 9, 20] 
 ]

然后模板中直接渲染列表,這樣做的好處是,想要增加難度直接在數(shù)組中添加數(shù)據(jù)即可

<li v-for="(item, index) in level" :key="index" @click="handleChoseLevel(item.value)"></li>

該組件中只有一個方法:選擇難度之后,跳轉(zhuǎn)到游戲主界面上去,因為項目沒有用路由,直接使用組件間的切換,所以,這個方法只負責告訴父組件,我已經(jīng)選擇好難度了,可以開始游戲了

// 選擇難度
 handleChoseLevel(level) {
  this.$emit("chose-level", level);
 }

代碼如下:

界面長這樣,當然,你要覺得難看自己換個樣式也行

游戲界面

畫格盤

通過游戲難度選擇來決定游戲格盤的大小,組件間已通過App將游戲難度傳至界面組件中,我們用props把數(shù)據(jù)接收到,消化成自己的數(shù)據(jù),畫格盤需要的數(shù)據(jù)有:橫排格子數(shù),縱排格子數(shù)

畫格子:我們將格子的索引暴露出來,后續(xù)可以幫助我們試錯。整個格局有兩種方式來表示格盤,坐標式和索引式,比如橫9縱9的格子,[0, 0]代表第1個格子,[2, 3]代表第三行第四列也就是第20個格子。此次使用索引式來標志格盤

<div 
  v-for="col in cols" :key="Math.random() + col"
  class="game-content-row">
  <span 
   v-for="row in rows" :key="Math.random() + row"
   class="game-block">
   <span></span>
  </span>
 </div>

隨機生成地雷

首先data中添加一個minePosition屬性,用來記錄雷點位置

隨機生成地雷比較簡單,主要注意,生成的地雷點數(shù)在格盤個數(shù)范圍內(nèi),那么就可以寫出隨機生成的地雷了。界面組件已收集到橫排格子數(shù)、縱排格子數(shù)、雷數(shù),那么就能得到格子總數(shù),假設橫9縱9,10個雷,那么就是生成10個81以內(nèi)的隨機數(shù)(如果索引從0開始,即80以內(nèi))。

// 隨機獲取雷點位置
 getMinePosition() {
  // 定義一個數(shù)組裝不重復的格點
  let mineArr = [];
  // 循環(huán)雷數(shù)生成不重復的雷點
  for (let n = 0; n < this.gameInfo[2]; n++) {
   const random = Math.floor(Math.random() * this.latticeNum);
   if (mineArr.indexOf(random) === -1) {
    mineArr.push(random);
   } else {
    n--;
   }
  }
  this.minePosition = mineArr;
 },

把地雷位置暴露出來

格子周圍的雷數(shù)

確認了雷點位置,接下來要做的就是確認每一個非雷點位置周圍的雷的數(shù)量,我們用對象來描述一個格子,這個對象主要包含以下幾個屬性

// 格子屬性
 lattice: [{
  index: 0, // 格子索引
  mineNum: 0, // 周圍雷數(shù)
  isMine: false, // 是否是雷
  isOpen: false, // 是否已經(jīng)被點開
  isMark: false, // 是否被標記
 }],

這里我們主要用到index, isMine, mineNum屬性,這一步,主要是計算每個格子元素的mineNum值,依賴于以下兩個方法,個人覺得掃雷游戲最難理解的,最難捋清的邏輯,其中一個就是獲取非雷點位置周圍8個位置索引的方法getLatticeIndex(另一個是點擊空白格擴散)

// 獲取格子周圍的雷數(shù),
 getMineNumAroundLattice(lattice, index) {
  // 先獲取格子周圍的有效索引
  const latticeIndexArr = this.getLatticeIndex(index);
  // 循環(huán)索引,索引值在雷點數(shù)組中的,即為雷,當前格子的雷點數(shù)加1
  latticeIndexArr.forEach(i => {
   if (this.minePosition.indexOf(i) > -1) {
    lattice.mineNum ++;
   }
  });
 },
 // 獲取格子周圍的有效索引
 getLatticeIndex(index) {
  // 存索引值的變量
  let latticeIndexArr = [];
  // 當前格子位于第幾行
  const latticeRow = Math.ceil(index / this.rows);
  // 當前格子位于第幾列(求余為0說明是最右邊一列)
  const latticeCol = Math.ceil(index % this.rows) || this.rows;
  // 第一行沒有上一行,不需要計算減1的行值,最后一行沒有下一行,不需要計算加1的行值
  for (let i = (latticeRow === 1 ? 0 : -1); i < (latticeRow === this.cols ? 1 : 2); i++) {
   // 第一列沒有左列,不需要計算減1的列值,最后一列沒有右列,不需要計算加1的列值
   for (let j = (latticeCol === 1 ? 0 : -1); j < (latticeCol === this.rows ? 1 : 2); j++) {
    // 索引值 = (當前行值 + (上一行【-1】/當前行【0】/下一行【+1】) - 1【1是索引從0開始,所以需要減去】) * 每行格子數(shù) + 當前列值 + (上一列【-1】/當前列【0】/下一列【+1】)
    const latticeIndex = (latticeRow + i - 1) * this.rows + (latticeCol + j);
    latticeIndexArr.push(latticeIndex);
   }
  }
  return latticeIndexArr;
 },

有了這兩個方法,咱成功地獲取到了每個非雷點格子周圍的雷的數(shù)量,來,展示出來,這樣展示的好處是,我們一眼就可以看出算法是否正確

沒問題了,來,接著往下走,格盤數(shù)據(jù)基本都設置好了,那我們接下來要做的就是,點開格子操作

點擊交互

這一步先做簡單點,有個明顯的區(qū)別就可以了,點雷我們先不管,先看點數(shù)字和空白的情況,首先得明確,到時候格子的可見屬性是全部要被隱藏的,點擊了才會顯示出來,這就用到了我們上一步提到的isOpen屬性,默認肯定全是不可見的,點擊之后,非雷翻開

點數(shù)字

點數(shù)字很簡單,直接翻開,將isOpen屬性設置為true

來點不一樣的,isOpen === true 的時候字體變紅色,走你┏ (゜ω゜)=☞

@click.left="handleClickLattice(lattice[(col - 1) * rows + row - 1])"
// 點了格子
 handleClickLattice(lattice) {
  // 是數(shù)字
  if (lattice.mineNum) {
   if (!lattice.isOpen && !lattice.isMark) {
    lattice.isOpen = true;
   }
  } 
 },

點空白

第二個難點來咯,點空白格需要注意以下幾點:1、空白格表示周圍8格都沒有雷 2、擴散周圍8格,判斷雷數(shù),循環(huán)往復 3、遇邊界停止擴散,遇數(shù)字停止擴散

假設橫9縱9的格盤,第二排第三列格為空白格即第12格,那么點了該空白格之后,首先將其與周圍8格(2,3,4,11,12,13,20,21,22)一起,isOpen置為true,然后分別以周圍8格為中心,判斷該格子是數(shù)字,停止擴散,是空白格,繼續(xù)擴散

這一步寫完,

// 代碼把下半部分補齊
 handleClickLattice(lattice) {
  ... else {
    // 是空白
    const latticeIndexArr = this.getLatticeIndex(lattice.index);
    this.showWhiteAround(lattice, latticeIndexArr);
   }
 },
 // 展示周圍的空白標記,直至邊緣(格子邊緣或者數(shù)字)
 showWhiteAround(lattice, latticeIndexArr) {
  // 避免有重復的數(shù)據(jù)停不下來,去個重
  latticeIndexArr = [...new Set(latticeIndexArr)];
  for (let i = 0; i < latticeIndexArr.length; i++) {
   const item = latticeIndexArr[i];
   latticeIndexArr.splice(i, 1);
   i--;
   if (this.lattice[item].isOpen) {
    continue;
   }
   this.lattice[item].isOpen = true;
   if (!this.lattice[item].mineNum) {
    const arr = this.getLatticeIndex(this.lattice[item].index);
    this.showWhiteAround(this.lattice[item], latticeIndexArr.concat(arr));
   } 
  }
 },

基本明面上的掃雷步驟就已經(jīng)完成了,handleClickLattice方法再加一步判斷,如果是雷,游戲結(jié)束

右鍵標記雷點

這個就很簡單了,寫個右擊事件,修改一下格子的isMark和isOpen屬性,這一步的基本邏輯就是

右擊格子 格子本身已經(jīng)被打開 1)是:格子已經(jīng)被標記為地雷? a. 是:取消標記(isMark和isOpen取反),剩余地雷數(shù)+1 b. 否:說明是右擊了已經(jīng)被點開的數(shù)字格,不做任何操作 2)否:isMark和isOpen取反,記錄該格子已經(jīng)被標記為地雷,格子處于打開狀態(tài),剩余地雷數(shù)-1,判斷是否結(jié)束

// 右鍵確認是雷點
  handleSureMinePoint(lattice) {
   if (!lattice.isOpen) {
    lattice.isMark = true;
    lattice.isOpen = true;
    this.minePosition.splice(this.minePosition.indexOf(lattice.index), 1);
    this.judgeIsOver();
   } else {
    if (lattice.isMark) {
     lattice.isMark = false;
     lattice.isOpen = false;
     this.minePosition.push(lattice.index);
    }
   }
  },

游戲是否結(jié)束

游戲結(jié)束一共有三種情況:1、點到雷了,直接結(jié)束 2、雷被標記完了(有可能失敗了,標錯了) 3、翻開的格子數(shù) + 雷數(shù) = 總格子數(shù)

完成功能

接下來要做的就是把格子屬性隱藏起來,假裝不知道,再假裝鼠標一點,格子就翻過來了。這就用到之前提到的格子屬性isMark和isOpen,本身元素處于隱藏狀態(tài),當被標記或者被打開的時候設置相應的屬性使其可見就行了,如此,便完成了掃雷的基本功能,有興趣的小朋友可以自己融合多種功能試一試

當然,這只是其中一種實現(xiàn)方式,把所有的計算全部放在玩游戲之前了,愛動腦筋的朋友們也可以想想,如果放在每一次點擊時做計算該如何組織代碼

阿望的源代碼中還集合了【重開一局】、【改變難度】、【游戲計時】等功能,樣式兼容手機和PC在線玩,在手機上玩的時候我在糾結(jié)手機如何模仿PC端的右鍵點擊標雷操作,沒有好的想法,不想用雙擊,于是多加了一個狀態(tài),點擊頁面【標記】按鈕,即表示標記雷點,再點擊一次表示還原,正常點開數(shù)字格,坐火車無聊的小朋友可以玩一玩喲

查看阿望的源碼: mineSweeping

在線試玩:mine-sweeping-online

希望各位看官不吝右上角賜個小星星哦,阿望這廂有禮啦,新年快樂啦 ★,° :.☆( ̄▽ ̄)/$: .°★ 。

總結(jié)

以上所述是小編給大家介紹的阿望教你用vue寫掃雷小游戲,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!

相關文章

  • vue?中使用?bimface詳情

    vue?中使用?bimface詳情

    這篇文章主要介紹了vue?中使用?bimface詳情,分別有安裝?vue?腳手架、創(chuàng)建項目、引入?bimface?響應的文件、修改?App.vue?文件,實現(xiàn)頁面渲染等步驟,需要的小伙伴可以參考一下
    2021-12-12
  • vue2 webpack proxy與nginx配置方式

    vue2 webpack proxy與nginx配置方式

    這篇文章主要介紹了vue2 webpack proxy與nginx配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • vue?Keep-alive組件緩存的簡單使用代碼

    vue?Keep-alive組件緩存的簡單使用代碼

    keep-alive是Vue提供的一個抽象組件,用來對組件進行緩存,從而節(jié)省性能,下面這篇文章主要給大家介紹了關于vue?Keep-alive組件緩存的簡單使用,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-09-09
  • Vue CLI3搭建的項目中路徑相關問題的解決

    Vue CLI3搭建的項目中路徑相關問題的解決

    這篇文章主要介紹了Vue CLI3搭建的項目中路徑相關問題的解決,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 詳解Vue-cli中的靜態(tài)資源管理(src/assets和static/的區(qū)別)

    詳解Vue-cli中的靜態(tài)資源管理(src/assets和static/的區(qū)別)

    這篇文章主要介紹了Vue-cli中的靜態(tài)資源管理(src/assets和static/的區(qū)別,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • vue實現(xiàn)接口封裝的實現(xiàn)示例

    vue實現(xiàn)接口封裝的實現(xiàn)示例

    本文主要介紹了vue實現(xiàn)接口封裝的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-11-11
  • 前端vue3搭建超詳細指南(快速上手搭建)

    前端vue3搭建超詳細指南(快速上手搭建)

    這篇文章主要介紹了使用Vue?3和Element-plus搭建前端項目的過程,包括項目搭建、Element-plus安裝和引入、axios安裝、sass使用、app.vue配置、組件創(chuàng)新、路由配置以及使用輔助插件來提高開發(fā)效率,需要的朋友可以參考下
    2025-02-02
  • vue-cli構(gòu)建vue項目的步驟詳解

    vue-cli構(gòu)建vue項目的步驟詳解

    這篇文章主要介紹了vue-cli構(gòu)建vue項目的步驟詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • 在vue中使用SockJS實現(xiàn)webSocket通信的過程

    在vue中使用SockJS實現(xiàn)webSocket通信的過程

    最近接到一個業(yè)務需求,需要做一個聊天信息的實時展示的界面,下面小編把實現(xiàn)過程記錄下來,對vue中使用SockJS實現(xiàn)webSocket通信的相關知識感興趣的朋友一起看看吧
    2018-08-08
  • 詳解Vue全局組件的掛載之實現(xiàn)彈窗組件

    詳解Vue全局組件的掛載之實現(xiàn)彈窗組件

    這篇文章主要為大家詳細介紹了如何通過Vue全局組件的掛載來實現(xiàn)彈窗組件,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的可以了解一下
    2022-11-11

最新評論

米林县| 东乌珠穆沁旗| 元谋县| 沂水县| 房产| 福清市| 新化县| 恩平市| 扶风县| 北流市| 娄烦县| 西和县| 佳木斯市| 奉化市| 同江市| 嫩江县| 丰台区| 鸡西市| 边坝县| 合川市| 迁安市| 定安县| 吴川市| 仙游县| 南郑县| 应城市| 沅陵县| 东光县| 科技| 凤冈县| 辽源市| 玉龙| 漳平市| 镶黄旗| 内黄县| 淮安市| 桐梓县| 平顺县| 葫芦岛市| 遂宁市| 宜君县|