接上篇
所有代碼可以在我的Github中找到宾舅,在線試玩:點(diǎn)擊
這一次主要做一件事,就是計(jì)算出每個(gè)方格周圍共有幾個(gè)雷,然后將數(shù)字繪制在方格中。
創(chuàng)建Mineblock對(duì)象
首先創(chuàng)建一個(gè)Mineblock對(duì)象固蛾,代表畫布中每一個(gè)方格,總共480個(gè)蒂阱。
該對(duì)象接收兩個(gè)參數(shù)洪乍,該方格所在的行和列。屬性包括了columns,rows,isMined,roundMines
开瞭。
function Mineblock (cloumns, rows) {
this.cloumns = cloumns;
this.rows = rows;
this.isMined = false;//boolean default false
this.roundMines = 0;//0-8
}
其中roundMines
代表當(dāng)前方格周圍有幾個(gè)雷懒震。
創(chuàng)建二維數(shù)組
在上一篇的基礎(chǔ)上進(jìn)行改進(jìn)罩息。
生成一個(gè)30x16總共480個(gè)元素的二維數(shù)組,存儲(chǔ)了480個(gè)Mineblock對(duì)象个扰。
同樣的瓷炮,需要在這480個(gè)元素中,挑出99個(gè)不重復(fù)的元素作為雷递宅。
for (let i = 0; i < 99; i++) {
let index = Math.floor(Math.random() * positions.length);
let position = positions[index];
let x = position.x;
let y = position.y;
mines[x][y].isMined = true;
positions.splice(index, 1);
}
沒(méi)什么好解釋的娘香,方法跟上一篇差不多。
生成數(shù)字
然后就是生成數(shù)字办龄。
讓我們回想一下掃雷的規(guī)則烘绽,當(dāng)你點(diǎn)開一個(gè)方塊時(shí),上面的數(shù)字表明了在該方塊的周圍俐填,總共8個(gè)方塊中诀姚,一共有幾個(gè)雷。
當(dāng)前方塊的位置如果是第i行玷禽,第j列的話赫段,那我需要檢查總共八個(gè)方塊,即第i-1行的三個(gè)即j-1,j,j+1矢赁,第i行的兩個(gè)j-1,j+1糯笙,第i+1行的三個(gè)j-1,j,j+1
這個(gè)用二維數(shù)組做起來(lái)就很一目了然。
var mineNum;
for (let i = 0, length1 = mines.length; i < length1; i++) {
for (let j = 0, length1 = mines[i].length; j < length1; j++) {
mineNum = 0;
for (let k = -1; k < 2; k++) {
for (let l = -1; l < 2; l++) {
if (i + l > -1 && j + k > -1 && i + l < 30 && j + k < 16) {
if (mines[i + l][j + k].isMined === true) {
mineNum++;
}
}
}
}
mines[i][j].roundMines = mineNum;
}
}
其中的檢查條件if (i + l > -1 && j + k > -1 && i + l < 30 && j + k < 16)
即保證當(dāng)?shù)谝恍谢蛘咦詈笠恍幸活惖那闆r時(shí)撩银,不會(huì)超過(guò)數(shù)組的邊界给涕。
繪制面板
繪制面板沒(méi)什么好說(shuō),不過(guò)這次不只是雷额获,還有數(shù)字的繪制够庙,從數(shù)組中的Mineblock對(duì)象的roundMines屬性獲得就好。
for (let i = 0; i < mines.length; i++) {
for (let j = 0; j < mines[i].length; j++) {
if (mines[i][j].isMined === true) {
mineContext.fillStyle = "red";
mineContext.fillRect(mines[i][j].cloumns * 20, mines[i][j].rows * 20, this.block_width, this.block_height); //繪制矩形
} else {
mineContext.fillStyle = "blue";
mineContext.font = "15px Arial";
mineContext.textAlign = 'center';
mineContext.fillText(mines[i][j].roundMines, mines[i][j].cloumns * 20 + 10, mines[i][j].rows * 20 + 15);
}
}
}
游戲結(jié)束
最后再加一個(gè)條件抄邀,當(dāng)點(diǎn)擊到雷時(shí)游戲結(jié)束耘眨,彈出一個(gè)提示框,同時(shí)清除掉遮罩層境肾。
maskCanvas.addEventListener("click", function(e) {
p = getPosition(e);
index = getMineIndex(p.x, p.y);
maskContext.clearRect(index.xIndex * BLOCK_WIDTH, index.yIndex * BLOCK_HEIGHT, BLOCK_WIDTH - 1, BLOCK_HEIGHT - 1);
if (mines[index.xIndex][index.yIndex].isMined === true) {
alert("you lose");
maskContext.clearRect(0, 0, 600, 320);
}
}, false);
效果如下: