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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容