利用事件委托写一个简易扫雷游戏

本文介绍如何利用事件委托来编写一个简单的扫雷游戏。首先讲解了事件委托的概念、原理及其适用场景,接着详细阐述了游戏的实现步骤,包括界面设计、事件委托的添加、功能函数的编写和雷区的随机生成。最后展示了实现效果和关键代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 事件代理(委托)

可以解决的问题:如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能
基本原理:事件委托是利用事件的冒泡原理来实现的,何为事件冒泡(事件从最深的节点开始,然后逐步向上传播事件)
事件代理的适用场景:应用频繁触发事件时 || 当列表频繁创建删除时

2. 一个简易的扫雷游戏

我是从下面几步来完成的:
(1). 先完成界面的设计(界面的初始方块与初始数组的大小是对应的)
(2). 添加点击事件(利用事件委托)
(3). 完成事件触发调用的函数(在这个过程中需要计算“九宫格”雷区的数目)
(4). 写一个随机生成雷区的函数


界面的样式以及布局
*{
    margin : 0;
    padding: 0;
}
body {
    font-family: "微软雅黑";
    font-size: 14px;
    background : #615454;
}
.box {
    width: 320px;
    position: fixed;
    left: 50%;
    top: 20%;
    margin-left: -160px;
    background: #fff;
}
.box span{
    width: 30px;
    height: 30px;
    display: block;
    border: 1px solid #ddd;
    float: left;
    background : #b3a157;
    cursor: pointer;
    text-align: center;
    line-height: 30px;
}
.box span.danger{
    background: black;
}
.box span.safety{
    background: white;
}
<div id="box" class='box'></div>

初始化界面的代码:

controller.draw = function() {
    var html = '';
    for(var i = 0, len = controller.arr.length; i < len; i++) {
        for(var j = 0, len1 = controller.arr[i].length; j < len1; j++) {
            html += "<span></span>";
        }
        html += '<br>';
    }

    controller.box.innerHTML = html;    
}
controller.arr = [
    [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
    [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
];

事件委托的代码

在这里我把span的点击事件委托给div,给div添加了点击事件,通过event对象可以得到鼠标点击的元素,通过event获得点击的位置,计算出发生点击的span横纵坐标,计算出九宫格内的地雷数目并显示

controller.clickEve = function() {
    window.addEventListener ? controller.box.addEventListener('click', controller.gover, false) : attachEvent('onclick', controller.gover); 
}
controller.gover = function(eve) {
    eve = eve || window.event;
    var num = 0, 
        i = 0,
        j = 0,
        targetElement = eve.target || eve.srcElemeent,
        pointerXY = controller.getPointer(eve),
        boxOffsetLeft = controller.box.offsetLeft,
        boxOffsetTop = controller.box.offsetTop,
        relativeLeft = pointerXY.pointerX - boxOffsetLeft,
        relativeTop = pointerXY.pointerY - boxOffsetTop;

    //x代表行数的下标, y代表列数的下标
    i = relativeLeft % 32 == 0 ? Math.floor(relativeLeft / 32 - 1) : Math.floor(relativeLeft / 32);
    j = relativeTop % 32 == 0 ? Math.floor(relativeTop / 32 - 1) : Math.floor(relativeTop / 32);

    if(controller.arr[i][j] == 1) {
        targetElement.className = 'danger';
        setTimeout(function() {
            alert('游戏结束');
            controller.random();
            controller.draw();
        }, 300);    
    }else {
        for(x = i-1; x <= i+1; x++) {
            for(y = j-1; y <= j+1; y++) {
                if(x < 0 || y < 0 || x > controller.arr.length-1 || y > controller.arr.length-1) {
                    continue;
                }
                if(controller.arr[x][y] == 1) {
                    num++;
                }
            }
        }
        targetElement.className = 'safety';
        targetElement.innerText = num ? num : "";
    }
}

出现的效果:

这里写图片描述


整个的JS代码如下,最下面的注释解释了计算九宫格雷的数目的思路:

var controller = function() {}
controller.box = document.getElementById('box');
controller.draw = function() {
    var html = '';
    for(var i = 0, len = controller.arr.length; i < len; i++) {
        for(var j = 0, len1 = controller.arr[i].length; j < len1; j++) {
            html += "<span></span>";
        }
        html += '<br>';
    }

    controller.box.innerHTML = html;    
}
controller.arr = [
    [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
    [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
];

controller.gover = function(eve) {
    eve = eve || window.event;
    var num = 0, 
        i = 0,
        j = 0,
        targetElement = eve.target || eve.srcElemeent,
        pointerXY = controller.getPointer(eve),
        boxOffsetLeft = controller.box.offsetLeft,
        boxOffsetTop = controller.box.offsetTop,
        relativeLeft = pointerXY.pointerX - boxOffsetLeft,
        relativeTop = pointerXY.pointerY - boxOffsetTop;

    //x代表行数的下标, y代表列数的下标
    i = relativeLeft % 32 == 0 ? Math.floor(relativeLeft / 32 - 1) : Math.floor(relativeLeft / 32);
    j = relativeTop % 32 == 0 ? Math.floor(relativeTop / 32 - 1) : Math.floor(relativeTop / 32);

    if(controller.arr[i][j] == 1) {
        targetElement.className = 'danger';
        setTimeout(function() {
            alert('游戏结束');
            controller.random();
            controller.draw();
        }, 300);    
    }else {
        for(x = i-1; x <= i+1; x++) {
            for(y = j-1; y <= j+1; y++) {
                if(x < 0 || y < 0 || x > controller.arr.length-1 || y > controller.arr.length-1) {
                    continue;
                }
                if(controller.arr[x][y] == 1) {
                    num++;
                }
            }
        }
        targetElement.className = 'safety';
        targetElement.innerText = num ? num : "";
    }
}

controller.clickEve = function() {
    window.addEventListener ? controller.box.addEventListener('click', controller.gover, false) : attachEvent('onclick', controller.gover); 
}

controller.getPointer = function(event) {
    var pointerXY = {
        pointerX : event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)),
        pointerY : event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop))
    } 
    return pointerXY; 
} 

controller.random = function() {
    for(var i = 0; i < controller.arr.length; i++) {
        for(var j = 0; j < controller.arr.length; j++) {
            controller.arr[i] = controller.arr[i].sort(function(){
                return 0.5-Math.random();   // 0-1  从小到大或者从小到大
            });
        }
    }
}

//i-1: j-1   i-1 : j   i-1: j+1
//i  : j-1    点击处    i  : j+1
//i+1: j-1   i+1 : j   i+1: j+1

所写内容如有不足,欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值