Vue開發(fā)掃雷小游戲

規(guī)則分析

游戲區(qū)包括雷區(qū)咧叭、地雷計(jì)數(shù)器(位于左上角,記錄剩余地雷數(shù))和計(jì)時(shí)器(位于右上角蒋纬,記錄游戲時(shí)間)萤彩,確定大小的矩形雷區(qū)中隨機(jī)布置一定數(shù)量的地雷(初級(jí)為99個(gè)方塊10個(gè)雷粪滤,中級(jí)為1616個(gè)方塊40個(gè)雷,高級(jí)為1630個(gè)方塊99個(gè)雷雀扶,自定義級(jí)別可以自己設(shè)定雷區(qū)大小和雷數(shù)杖小,但是雷區(qū)大小不能超過2430),玩家需要盡快找出雷區(qū)中的所有不是地雷的方塊怕吴,而不許踩到地雷窍侧。

狀態(tài)梳理

  1. 未掃狀態(tài)
  2. 空狀態(tài)
  3. 周圍有雷狀態(tài)(1,2,3,4,5,6,7,8)
  4. 雷爆炸狀態(tài)
  5. 標(biāo)旗狀態(tài)

偽代碼

  1. 創(chuàng)建行列變量row,column和地雷數(shù)mine
  2. 通過變量生成row*column的二維數(shù)組县踢,默認(rèn)值全部設(shè)置為10
  3. 隨機(jī)放入mine個(gè)地雷转绷,地雷標(biāo)記為數(shù)字19
  4. 放雷時(shí),雷的八個(gè)方位的數(shù)值+1硼啤,若為19則不加
  5. 循環(huán)數(shù)組渲染议经,大于等于10小于19的數(shù)字顯示為未掃狀態(tài)
  6. 點(diǎn)擊掃雷,把當(dāng)前數(shù)字-10谴返。如果值等于9煞肾,那么表里數(shù)組顯示全部雷游戲結(jié)束;其他顯示出來數(shù)字嗓袱,0顯示為空白
  7. 當(dāng)0時(shí)遞歸連鎖周圍的數(shù)字直到周圍沒有0籍救,顯示出來數(shù)字(如果為標(biāo)旗那么不解鎖)
  8. 右鍵標(biāo)旗,標(biāo)旗邏輯即當(dāng)前數(shù)字+10渠抹,取消標(biāo)旗-10
  9. 標(biāo)旗時(shí)判斷數(shù)組內(nèi)29的個(gè)數(shù)等于雷數(shù)且19的數(shù)字為0蝙昙,即全部標(biāo)記出來雷了闪萄,游戲結(jié)束
  10. 掃雷時(shí)未解鎖的區(qū)域等于雷數(shù),那么游戲結(jié)束

游戲時(shí)數(shù)組值狀態(tài)

數(shù)組值 顯示狀態(tài)
0 已解鎖的空白
1-8 周圍有雷的
9 雷爆炸
10-19 未解鎖的狀態(tài)
20-29 標(biāo)旗

編碼實(shí)現(xiàn)和效果

實(shí)現(xiàn)效果
// 雷區(qū)行數(shù)和列數(shù)
const row = ref<number>(10)
const column = ref<number>(10)
const mine = ref<number>(10)
const mineBoard = ref<number[][]>([])
const gameState = ref<boolean>(false)
const colors = ref<string[]>(['#0000CC', '#009999', '#00FF99', '#663399', '#CC0099', '#FFFF99', '#CCCC33', '#FF0033'])
const timer = ref<number>(0)
// 初始化雷場(chǎng)
const initBoard = () => {
  mineBoard.value = []
  gameState.value = false
  endTimer()
  timer.value = 0
  for (let i = 0; i < row.value; i++) {
    let rows: number[] = []
    for (let j = 0; j < column.value; j++) {
      rows.push(10)
    }
    mineBoard.value.push(rows)
  }
  layMines()
}

// 根據(jù)設(shè)置個(gè)數(shù)隨機(jī)埋雷
const layMines = () => {
  if (mine.value > row.value * column.value) {
    console.log('雷數(shù)太多了');
    alert('雷數(shù)太多放不下了')
    return
  }
  for (let i = 0; i < mine.value; i++) {
    randomLayMine()
  }
}
// 埋雷并生成雷周圍的提示
const randomLayMine = () => {
  const c = parseInt((Math.random() * column.value).toString())
  const r = parseInt((Math.random() * row.value).toString())
  if (mineBoard.value[r][c] === 19) {
    randomLayMine()
  } else {
    // 設(shè)置地雷
    mineBoard.value[r][c] = 19
    buildTips(r - 1, c - 1)
    buildTips(r - 1, c)
    buildTips(r - 1, c + 1)
    buildTips(r, c - 1)
    buildTips(r, c + 1)
    buildTips(r + 1, c - 1)
    buildTips(r + 1, c)
    buildTips(r + 1, c + 1)
  }
}

// 生成周圍地雷個(gè)數(shù)提示
const buildTips = (r: number, c: number) => {
  if (r > -1 && c > -1 && r < row.value && c < column.value && mineBoard.value[r][c] !== 19) {
    mineBoard.value[r][c]++
  }
}
// 進(jìn)行掃雷
const clearanceMine = (itm: number, r: number, c: number) => {
  if (gameState.value) {
    return
  }

  if (timer.value === 0) {
    beginTimer()
  }
  if (itm > 19) {
    mineBoard.value[r][c] -= 10
  }
  if (itm < 9) {
    return
  } else if (itm === 10) {
    chain(r, c)
  } else if (itm > 9 && itm < 19) {
    // 掃雷
    mineBoard.value[r][c] -= 10
  } else if (itm === 19) {
    for (let i = 0; i < row.value; i++) {
      for (let j = 0; j < column.value; j++) {
        if (mineBoard.value[i][j] === 19) {
          mineBoard.value[i][j] = 9
        }
      }
    }
    gameState.value = true
    beginTimer()
    console.log('游戲結(jié)束');
  }
}

// 左鍵連鎖空白區(qū)域
const chain = (r: number, c: number) => {
  if (r > -1 && c > -1 && r < row.value && c < column.value && mineBoard.value[r][c] !== 9 && mineBoard.value[r][c] < 19) {
    if (mineBoard.value[r][c] === 10) {
      mineBoard.value[r][c] -= 10
      chain(r - 1, c - 1)
      chain(r - 1, c)
      chain(r - 1, c + 1)
      chain(r, c - 1)
      chain(r, c + 1)
      chain(r + 1, c - 1)
      chain(r + 1, c)
      chain(r + 1, c + 1)
    } else if (mineBoard.value[r][c] > 10) {
      mineBoard.value[r][c] -= 10
    }
  }
}

// 右鍵標(biāo)記或者取消標(biāo)記
const markMine = (itm: number, r: number, c: number) => {
  if (timer.value === 0) {
    beginTimer()
  }
  // 已經(jīng)掃出結(jié)果的無法再右鍵奇颠,游戲結(jié)束無法右鍵
  if (itm < 9 || gameState.value) {
    return
  }
  if (itm < 20) {
    mineBoard.value[r][c] += 10
  } else {
    mineBoard.value[r][c] -= 10
  }
  testGame()
}

const testGame = () => {
  let flag = 0
  let mark = 0
  let lock = 0
  for (let i = 0; i < row.value; i++) {
    for (let j = 0; j < column.value; j++) {
      //  未標(biāo)記雷的個(gè)數(shù)
      if (mineBoard.value[i][j] === 19) {
        mark++
      }
      // 標(biāo)記個(gè)數(shù)
      if (mineBoard.value[i][j] > 19) {
        flag++
      }
      if (mineBoard.value[i][j] > 9) {
        lock++
      }
    }
  }
  // 標(biāo)記個(gè)數(shù)等于雷數(shù)败去,未掃出來的雷為0
  if (flag === mine.value && mark === 0) {
    console.log('掃雷完成,游戲結(jié)束');
    alert('恭喜過關(guān)')
    gameState.value = true
    endTimer()
  }
  if (lock === mine.value) {
    alert('恭喜過關(guān)')
    gameState.value = true
    endTimer()
  }
}
initBoard()

優(yōu)化項(xiàng)

  1. 使用canvas繪圖來實(shí)現(xiàn)效果減少HTML引發(fā)的顯示錯(cuò)亂
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末烈拒,一起剝皮案震驚了整個(gè)濱河市圆裕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荆几,老刑警劉巖吓妆,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異吨铸,居然都是意外死亡耿战,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門焊傅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剂陡,“玉大人,你說我怎么就攤上這事狐胎⊙计埽” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵握巢,是天一觀的道長(zhǎng)晕鹊。 經(jīng)常有香客問我,道長(zhǎng)暴浦,這世上最難降的妖魔是什么溅话? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮歌焦,結(jié)果婚禮上飞几,老公的妹妹穿的比我還像新娘。我一直安慰自己独撇,他們只是感情好屑墨,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纷铣,像睡著了一般卵史。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上搜立,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天以躯,我揣著相機(jī)與錄音,去河邊找鬼啄踊。 笑死忧设,一個(gè)胖子當(dāng)著我的面吹牛色鸳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播见转,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼命雀,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了斩箫?” 一聲冷哼從身側(cè)響起吏砂,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乘客,沒想到半個(gè)月后狐血,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡易核,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年匈织,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牡直。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缀匕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碰逸,到底是詐尸還是另有隱情乡小,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布饵史,位于F島的核電站满钟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏胳喷。R本人自食惡果不足惜湃番,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吭露。 院中可真熱鬧吠撮,春花似錦、人聲如沸奴饮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)戴卜。三九已至,卻和暖如春琢岩,著一層夾襖步出監(jiān)牢的瞬間投剥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工担孔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留江锨,地道東北人吃警。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像啄育,于是被迫代替她去往敵國(guó)和親酌心。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容