js+canvas实现简单扫雷小游戏

扫雷小游戏作为windows自带的一个小游戏,受到很多人的喜爱,今天我们就来尝试使用h5的canvas结合js来实现这个小游戏。

要写游戏,首先要明确游戏的规则,扫雷游戏是一个用鼠标操作的游戏,通过点击方块,根据方块的数字推算雷的位置,标记出所有的雷,打开所有的方块,即游戏成功,若点错雷的位置或标记雷错误,则游戏失败。

具体的游戏操作如下

1.可以通过鼠标左键打开隐藏的方块,打开后若不是雷,则会向四个方向扩展

2.可以通过鼠标右键点击未打开的方块来标记雷,第二次点击取消标记

3.可以通过鼠标右键点击已打开且有数字的方块来检查当前方块四周的标记是否正确

接下来开始编写代码

首先写好HTML的结构,这里我简单地使用一个canvas标签,其他内容的扩展在之后实现(游戏的规则,游戏的难度设置)

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> #canvas { display: block; margin: 0 auto; } </style> </head> <body> <div> <canvas></canvas> </div> <script src="https://www.jb51.net/js/game.js"></script> </body> </html>

接下来我们来初始化一些内容。包括canvas画布的宽高,游戏共有几行几列,几个雷,每个格子的大小。

//获取canvas画布 var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); canvas.width = 480; canvas.height = 480; //定义各属性 let R = 3; //格子圆角半径 let L = 15; //每个格子实际长 let P = 16; //每个格子占长 let row = 30; //行数 let col = 30; //列数 let N = 50; //雷数

为了后面的操作,我要用几个数组来储存一些位置,一个方块是否为雷的数组,该数组用于描绘出整个画面每个方块对应的内容;一个数组用于描述方块状态,即是否打开或者被标记;一个数组用来记载生成的雷的位置;一个数组用来记载标记的位置。

var wholeArr = drawInitialize(row, col, N, R, L, P); var gameArr = wholeArr[0] //位置数组 var bombArr = wholeArr[1] //雷的位置数组 var statusArr = zoneInitialize(row, col); //状态数组 0为未打开且未标记 1为打开 2为标记 var signArr = []; //标记数组 //画出初始界面 function drawInitialize(row, col, n, R, L, P) { let arr = initialize(row, col, n); for (let r = 0; r < row; r++) { for (let c = 0; c < col; c++) { drawRct(r * P, c * P, L, R, 'rgb(102,102,102)', context);//该方法用于绘制整个画面,下面会写出声明 } } return arr; } //初始化 function initialize(row, col, n) { let gameArr = zoneInitialize(row, col); //生成没有标记雷的矩阵 let bomb = bombProduce(n, gameArr, row, col); gameArr = signArrNum(bomb[0], bomb[1], n, row, col); return [gameArr, bomb[1]]; } //界面矩阵初始化 function zoneInitialize(row, col) { //生成row行col列的矩阵 let cArr = new Array(col); let rArr = new Array(row); cArr = cArr.fill(0); //将行的每个位置用0填充 for (let i = 0; i < row; i++) rArr[i] = [...cArr]; return rArr; } //随机生成雷 function bombProduce(n, arr, row, col) { //随机生成n个雷 let count = 0; let bombArr = []; while (true) { if (count === n) break; let r = Math.floor(Math.random() * row); let c = Math.floor(Math.random() * col); if (arr[c][r] === 0) { arr[c][r] = -1; bombArr[count] = strProduce(c, r); count++; } } return [arr, bombArr]; } //标记数字 function signArrNum(gArr, bArr, n, row, col) { for (let i = 0; i < n; i++) { //为每个雷的四周的非雷的数字标记加一 let r = parseInt(analyseStr(bArr[i]).row); let c = parseInt(analyseStr(bArr[i]).col); if (r > 0 && gArr[c][r - 1] != -1)//判断该位置是否为雷,是则不进行操作 gArr[c][r - 1]++; if (r < row - 1 && gArr[c][r + 1] !== -1) gArr[c][r + 1]++; if (c > 0 && gArr[c - 1][r] !== -1) gArr[c - 1][r]++; if (c < col - 1 && gArr[c + 1][r] !== -1) gArr[c + 1][r]++; if (r > 0 && c > 0 && gArr[c - 1][r - 1] != -1) gArr[c - 1][r - 1]++; if (r < row - 1 && c < col - 1 && gArr[c + 1][r + 1] != -1) gArr[c + 1][r + 1]++; if (r > 0 && c < col - 1 && gArr[c + 1][r - 1] != -1) gArr[c + 1][r - 1]++; if (r < row - 1 && c > 0 && gArr[c - 1][r + 1] != -1) gArr[c - 1][r + 1]++; } return gArr; } //生成字符串 function strProduce(r, c) { return `row:${c}|col:${r}`; } //解析雷数组字符串 function analyseStr(str) { str = str.split('|'); str[0] = str[0].split(':'); str[1] = str[1].split(':'); return { row: str[0][1], col: str[1][1] }; }

接下来将绘制的方法写出来,这里我使用红色的方块来代表雷

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/5c95a71ebb66ecb5a5259550b2f6c3d4.html