栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

做一个扫雷游戏

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

做一个扫雷游戏

论游戏中,最深入人心的游戏是什么?最经典的游戏是什么?理所当然,是《扫雷》。

项目地址:项目地址


这就是游戏的整体ui。

首先制作游戏的h5骨架:
可以使用一个div作为容器来放置每个方格,至于时间表,可以最为图片:

index.html




    
    扫雷
    
    



    
    





然后编写下css文件,设置html部件的样式
css/index.css

#chess{
    border: #000 solid 1px;
    margin: 10px auto;
}
.block{
    width: 28px;
    height: 28px;
    margin: 0;
    border: #000 solid 1px;
    background-color: #eee;
    float: left;
    font-weight: bold;
    text-align: center;
    line-height: 30px;
    font-size: 20px;
    cursor: pointer;
}
.block:hover{
    background-color: #ccc;
}
#info{
    margin: 0 auto;
    text-align: center;
}
.face{
    border: 2px solid #808080;
    border-left-color: #fff;
    border-top-color: #fff;
    height: 20px;
    width: 20px
}
.face:active{
    border-top:2px solid #808080;
    border-bottom:1px solid #808080;
    border-right:1px solid #808080;
    border-left:2px solid #808080;
}

接下来就开始实现游戏的逻辑实现,首先初始化一些基本变量与数组:

var chess = [];// 存储雷区的值
const num = 100;// 存储地雷数
var surplusNum = num;// 存储剩余地雷数
var styles = [
    "#00f",
    "#0f0",
    "#f00",
    "#08f",
    "#f30",
    "#0fa",
    "#943",
    "#eee"
];// 存储不同数字的颜色样式
var die = false;// 存储是否游戏结束
var chessJq = $("#chess");// 为雷区的jQuery对象
var chessLength = 25;// 为雷区的边长

为了能在游戏结束后能重复开始游戏,则我们将一些初始化代码放入init函数中,并在开始调用它:

init();
function init() {
    // 判断是否地雷数大于格子数
    if (num > Math.pow(chessLength,2))
 return;
    // 设置雷区长宽
    $("#chess").css({
 "width": chessLength * 30,
 "height": chessLength * 30
    });
    // 初始化雷区
    for (let i = 0 ; i < chessLength ; i++){
 chess[i] = [];
 for (let j = 0 ; j < chessLength ; j++){
     chess[i][j] = 0;
 }
    }
    for (let i = 0 ; i < num ; i++){
 while (true){
     var x = Math.floor(Math.random() * chess.length),y = Math.floor(Math.random() * chess.length);
     if (chess[y][x] == 0){
  chess[y][x] = -1;
  break;
     }
 }
    }
    // 初始化数字标记
    for (let i = 0 ; i < chess.length ; i++){
 for (let j = 0 ; j < chess.length ; j++){
     if (chess[i][j] == -1)
  continue;
     chess[i][j] += get(i - 1,j);
     chess[i][j] += get(i + 1,j);
     chess[i][j] += get(i,j - 1);
     chess[i][j] += get(i,j + 1);
     chess[i][j] += get(i - 1,j - 1);
     chess[i][j] += get(i + 1,j + 1);
     chess[i][j] += get(i + 1,j - 1);
     chess[i][j] += get(i - 1,j + 1);
 }
    }
    // 清空雷区
    chessJq.empty();
    for (let i = 0 ; i < chess.length ; i++){
 for (let j = 0 ; j < chess.length ; j++){
     // chessJq.append("");
     // if (chess[i][j] > 0){
     //     $("#" + i + "-" + j).html(chess[i][j]);
     // }
     chessJq.append("");
 }
    }
    surplusNum = num;
    update();
}
function get(i,j) {
    if (i < 0 || i >= chess.length || j < 0 || j >= chess.length)
 return 0;
    if (chess[i][j] == -1)
 return 1;
    return 0;
}

然后,接着实现点击雷区方格露出数字、与右击标记的代码,对此,可以添加一个mousedown的事件。

$(".block").mousedown(function (e) {
    if (die)
 return;
    var me = $(this);
    if (e.which == 1){// left click
 open(me,true,0);
    } else {// right click
 if (me.html().search(/0/g) !== -1){
     me.html("");
     surplusNum--;
     update();
 } else if (me.html().search(/flag/g) !== -1) {
     me.html("");
     surplusNum++;
     update();
 } else {
     me.html("");
 }
 if (surplusNum == 0){
     for (let i = 0 ; i < chess.length ; i++){
  for (let j = 0 ; j < chess.length ; j++){
      if (chess[i][j] == -1 && $("#" + i + "-" + j).html().search("flag") == -1){
   die = true;
   break;
      }
  }
     }
     if (die){
  $("#start").attr("src","img/face_fail.bmp");
  dieShow();
     } else {
  $("#start").attr("src","img/face-win.bmp");
     }
 }
    }
});

细心的同学们肯定发现了,接着,我们要开始实现open函数,该函数应该有两个模式,一个是程序自动翻出附近的数字,一个是打开用户操作的方格。可以使用传一个布尔值来判断,并使用递归实现自动翻出附近的数字。


function open(me,canBoom,level) {
    var id = me.attr("id");
    var tmp = id.split("-");
    var x = tmp[1] * 1;
    var y = tmp[0] * 1;
    if (level > 5){
 return;
    }
    if (me.html().search(/flag/g) != -1 || me.html().search(/ask/g) != -1)
 return;
    if (chess[y][x] == -1 && canBoom){
 me.html("");
 die = true;
 $("#start").attr("src","img/face_fail.bmp");
 dieShow();
    } else if (chess[y][x] > 0){
 me.html(chess[y][x]);
 me.css({
     "color": styles[chess[y][x]],
     "background-image": "url("img/0.bmp")"
 });
 let tmp = $("#" + y + "-" + x);
 if (tmp.html().search(/flag/g) != -1 || tmp.html().search(/ask/g) != -1)
     return;
 if (chess[y - 1][x] == -1 || chess[y + 1][x] == -1 || chess[y][x + 1] == -1 || chess[y][x - 1] == -1 ||
     chess[y - 1][x + 1] == -1 || chess[y + 1][x - 1] == -1 || chess[y + 1][x + 1] == -1 || chess[y - 1][x - 1] == -1
 ){
     return;
 }
 open($("#" + (y - 1) + "-" + (x)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x)),false,level + 1);
 open($("#" + (y) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y) + "-" + (x - 1)),false,level + 1);
 open($("#" + (y - 1) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x - 1)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y - 1) + "-" + (x - 1)),false,level + 1);
    } else {
 me.html("");
 let tmp = $("#" + y + "-" + x);
 if (tmp.html().search(/flag/g) != -1 || tmp.html().search(/ask/g) != -1)
     return;
 if (chess[y - 1][x] == -1 || chess[y + 1][x] == -1 || chess[y][x + 1] == -1 || chess[y][x - 1] == -1 ||
     chess[y - 1][x + 1] == -1 || chess[y + 1][x - 1] == -1 || chess[y + 1][x + 1] == -1 || chess[y - 1][x - 1] == -1
 ){
     return;
 }
 open($("#" + (y - 1) + "-" + (x)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x)),false,level + 1);
 open($("#" + (y) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y) + "-" + (x - 1)),false,level + 1);
 open($("#" + (y - 1) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x - 1)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y - 1) + "-" + (x - 1)),false,level + 1);
    }
}

仔细阅读以上代码,可以发现还有两个函数未实现: update与dieShow。

先啃软柿子,编写update的代码:

function update() {
    surplusNum += "";
    if (surplusNum.length == 2)
 surplusNum = "0" + surplusNum;
    if (surplusNum.length == 1)
 surplusNum = "00" + surplusNum;
    if (surplusNum.length == 0)
 surplusNum = "000";
    $("#b-h").attr("src","img/d" + surplusNum.charAt(0) + ".bmp");
    $("#b-t").attr("src","img/d" + surplusNum.charAt(1) + ".bmp");
    $("#b-o").attr("src","img/d" + surplusNum.charAt(2) + ".bmp");
    surplusNum *= 1;
}

至于dieShow的代码,可以通过遍历存储雷区的数组编写:

function dieShow() {
    for (let i = 0 ; i < chess.length ; i++){
 for (let j = 0 ; j < chess.length ; j++){
     let tmp = $("#" + i + "-" + j);
     if (chess[i][j] == -1){// have boom
  if (tmp.html().search(/blood/g) != -1)
      continue;
  tmp.html("");
     } else if (tmp.html().search(/flag/g) != -1 && chess[i][j] != -1){// not have boom and user is marked
  tmp.html("");
     } else if (chess[i][j] > 0){
  me.html(chess[i][j]);
  tmp.css({
      "color": styles[chess[i][j]],
      "background-image": "url("img/0.bmp")"
  });
     } else {
  tmp.html("");
     }
 }
    }
}

再编写点击按钮重来的代码

$("#start").click(function () {
    $(this).attr("src","img/face_normal.bmp");
    die = false;
    init();
});

这时测试,游戏就基本完成了...等等,为什么右击无法标记?

因为我们忘写了一个重要而简洁的事件响应函数

$(".block").bind("contextmenu", function(){
    return false;
});

最后js部分全部代码如下:

var chess = [];
const num = 100;
var surplusNum = num;
var styles = [
    "#00f",
    "#0f0",
    "#f00",
    "#08f",
    "#f30",
    "#0fa",
    "#943",
    "#eee"
];
var die = false;
var chessJq = $("#chess");
var chessLength = 25;
init();
function init() {
    if (num > Math.pow(chessLength,2))
 return;
    $("#chess").css({
 "width": chessLength * 30,
 "height": chessLength * 30
    });
    for (let i = 0 ; i < chessLength ; i++){
 chess[i] = [];
 for (let j = 0 ; j < chessLength ; j++){
     chess[i][j] = 0;
 }
    }
    for (let i = 0 ; i < num ; i++){
 while (true){
     var x = Math.floor(Math.random() * chess.length),y = Math.floor(Math.random() * chess.length);
     if (chess[y][x] == 0){
  chess[y][x] = -1;
  break;
     }
 }
    }
    for (let i = 0 ; i < chess.length ; i++){
 for (let j = 0 ; j < chess.length ; j++){
     if (chess[i][j] == -1)
  continue;
     chess[i][j] += get(i - 1,j);
     chess[i][j] += get(i + 1,j);
     chess[i][j] += get(i,j - 1);
     chess[i][j] += get(i,j + 1);
     chess[i][j] += get(i - 1,j - 1);
     chess[i][j] += get(i + 1,j + 1);
     chess[i][j] += get(i + 1,j - 1);
     chess[i][j] += get(i - 1,j + 1);
 }
    }
    chessJq.empty();
    for (let i = 0 ; i < chess.length ; i++){
 for (let j = 0 ; j < chess.length ; j++){
     // chessJq.append("");
     // if (chess[i][j] > 0){
     //     $("#" + i + "-" + j).html(chess[i][j]);
     // }
     chessJq.append("");
 }
    }
    $(".block").mousedown(function (e) {
 if (die)
     return;
 var me = $(this);
 if (e.which == 1){// left click
     open(me,true,0);
 } else {// right click
     if (me.html().search(/0/g) !== -1){
  me.html("");
  surplusNum--;
  update();
     } else if (me.html().search(/flag/g) !== -1) {
  me.html("");
  surplusNum++;
  update();
     } else {
  me.html("");
     }
     if (surplusNum == 0){
  for (let i = 0 ; i < chess.length ; i++){
      for (let j = 0 ; j < chess.length ; j++){
   if (chess[i][j] == -1 && $("#" + i + "-" + j).html().search("flag") == -1){
die = true;
break;
   }
      }
  }
  if (die){
      $("#start").attr("src","img/face_fail.bmp");
      dieShow();
  } else {
      $("#start").attr("src","img/face-win.bmp");
  }
     }
 }
    });
    $(".block").bind("contextmenu", function(){
 return false;
    });
    surplusNum = num;
    update();
}
function dieShow() {
    for (let i = 0 ; i < chess.length ; i++){
 for (let j = 0 ; j < chess.length ; j++){
     let tmp = $("#" + i + "-" + j);
     if (chess[i][j] == -1){// have boom
  if (tmp.html().search(/blood/g) != -1)
      continue;
  tmp.html("");
     } else if (tmp.html().search(/flag/g) != -1 && chess[i][j] != -1){// not have boom and user is marked
  tmp.html("");
     } else if (chess[i][j] > 0){
  me.html(chess[i][j]);
  tmp.css({
      "color": styles[chess[i][j]],
      "background-image": "url("img/0.bmp")"
  });
     } else {
  tmp.html("");
     }
 }
    }
}
function open(me,canBoom,level) {
    var id = me.attr("id");
    var tmp = id.split("-");
    var x = tmp[1] * 1;
    var y = tmp[0] * 1;
    if (level > 5){
 return;
    }
    if (me.html().search(/flag/g) != -1 || me.html().search(/ask/g) != -1)
 return;
    if (chess[y][x] == -1 && canBoom){
 me.html("");
 die = true;
 $("#start").attr("src","img/face_fail.bmp");
 dieShow();
    } else if (chess[y][x] > 0){
 me.html(chess[y][x]);
 me.css({
     "color": styles[chess[y][x]],
     "background-image": "url("img/0.bmp")"
 });
 let tmp = $("#" + y + "-" + x);
 if (tmp.html().search(/flag/g) != -1 || tmp.html().search(/ask/g) != -1)
     return;
 if (chess[y - 1][x] == -1 || chess[y + 1][x] == -1 || chess[y][x + 1] == -1 || chess[y][x - 1] == -1 ||
     chess[y - 1][x + 1] == -1 || chess[y + 1][x - 1] == -1 || chess[y + 1][x + 1] == -1 || chess[y - 1][x - 1] == -1
 ){
     return;
 }
 open($("#" + (y - 1) + "-" + (x)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x)),false,level + 1);
 open($("#" + (y) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y) + "-" + (x - 1)),false,level + 1);
 open($("#" + (y - 1) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x - 1)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y - 1) + "-" + (x - 1)),false,level + 1);
    } else {
 me.html("");
 let tmp = $("#" + y + "-" + x);
 if (tmp.html().search(/flag/g) != -1 || tmp.html().search(/ask/g) != -1)
     return;
 if (chess[y - 1][x] == -1 || chess[y + 1][x] == -1 || chess[y][x + 1] == -1 || chess[y][x - 1] == -1 ||
     chess[y - 1][x + 1] == -1 || chess[y + 1][x - 1] == -1 || chess[y + 1][x + 1] == -1 || chess[y - 1][x - 1] == -1
 ){
     return;
 }
 open($("#" + (y - 1) + "-" + (x)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x)),false,level + 1);
 open($("#" + (y) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y) + "-" + (x - 1)),false,level + 1);
 open($("#" + (y - 1) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x - 1)),false,level + 1);
 open($("#" + (y + 1) + "-" + (x + 1)),false,level + 1);
 open($("#" + (y - 1) + "-" + (x - 1)),false,level + 1);
    }
}
function get(i,j) {
    if (i < 0 || i >= chess.length || j < 0 || j >= chess.length)
 return 0;
    if (chess[i][j] == -1)
 return 1;
    return 0;
}
function update() {
    surplusNum += "";
    if (surplusNum.length == 2)
 surplusNum = "0" + surplusNum;
    if (surplusNum.length == 1)
 surplusNum = "00" + surplusNum;
    if (surplusNum.length == 0)
 surplusNum = "000";
    $("#b-h").attr("src","img/d" + surplusNum.charAt(0) + ".bmp");
    $("#b-t").attr("src","img/d" + surplusNum.charAt(1) + ".bmp");
    $("#b-o").attr("src","img/d" + surplusNum.charAt(2) + ".bmp");
    surplusNum *= 1;
}
$("#start").click(function () {
    $(this).attr("src","img/face_normal.bmp");
    die = false;
    init();
});

[完]

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号