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