原生JS实现扫雷小游戏
原生JS实现扫雷小游戏
- HTML部分
- CSS部分
- JavaScript部分
- 效果
-html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>原生JS扫雷</title>
<link rel="stylesheet" href="saolei.css"">
</head>
<body>
<div class="wrapper">
<div class="btn" id="btn"></div> <!--开始游戏 -->
<div class="box" id="box"></div> <!--格子-->
<div class="flagBox" id="flagBox">
<!-- 当前剩余雷数 -->
当前剩余雷数:
<span id="score">10</span>
</div>
<div class="alertBox" id="alertBox">
<div class="alertimg" id="alertimg">
<div class="close" id="close">
<!-- x图标 -->
</div>
</div>
</div>
</div>
<script src="saolei.js"></script>
</body>
</html>
-
CSS部分代码
{
margin: 0;
padding: 0;
list-style: none;
text-decoration: none;
}
.wrapper{
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background-image: url(‘zhutu.jpg’);
background-repeat: no-repeat;
background-size: 100% 100%;
}
.btn{
height: 140px;
width: 170px;
position: absolute;
left: 80px;
background-image: url(‘start.png’);
background-size: 100% 100%;
}
.box{
width: 500px;
height: 500px;
transform: perspective(800px) rotateX(45deg);
margin: 20px auto;
border-left: 1px solid #b25f27;
border-top: 1px solid #b25f27;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.3);
display: none;
}
.flagBox{
position: absolute;
top: 50px;
left: 50%;
width: 200px;
height: 50px;
margin-left: -100px;
color: #333;
font-size: 20px;
font-weight: 700;
display: none;
}
.alertBox{
display: none;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: rgba(0, 0, 0, 0.2);
}
.alertBox .alertimg{
width: 400px;
height: 250px;
/ background-image: url(‘gameover.jpg’); */
background-repeat: no-repeat;
background-size: 100% 100%;
border-radius: 20px;
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
margin: auto;
}
.alertBox .alertimg .close{
position: absolute;
right: 0;
top: 0;
width: 40px;
height: 40px;
background-image: url(‘x.jpg’);
background-size: 100% 100%;
cursor: pointer;
}
.block{
width: 49px;
height: 49px;
border-right: 1px solid #b25f27;
border-bottom: 1px solid #b25f27;
box-shadow: 0 0 4px #333 inset;
background-image: url(‘caodi.jpg’);
float: left;
}
.show{
background-image: url(‘lei.jpg’);
background-size: 100% 100%;
}
.num{
background: #ecd0a1;
line-height: 49px;
font-size: 18px;
font-weight: bold;
text-align: center;
}
.flag{
background-image: url(‘qizi.jpg’);
background-size: 100% 100%;
} -
JS代码
- //点击开始游戏===>动态生成一百个小格子 ===> 100 div //leftclick 没有雷 显示数字(代表以当前小格子为中心,周围八个格子的雷数) 扩散 (当前周围八个格子都没有雷) //leftclick 有雷 gameover //rightclick 没有标记并且没有数字==>进行标记 有标记==>取消标记 ==>标记是否正确, 10都正确标记,提示成功 //已经出现数字===>无效果 var statrBtn = document.getElementById('btn'); var box = document.getElementById('box'); var flagBox = document.getElementById('flagBox'); var alertBox = document.getElementById('alertBox'); var alertimg = document.getElementById('alertimg'); var closeBtn = document.getElementById('close'); var score = document.getElementById('score'); var minesNum;//雷的数量 var mineOver;//被标记的雷的数量 var block;//取一百个小格子 var mineMap = [];//代表当前小格子是否有雷 var startGame = true;//避免点开始游戏一直生成小格子 bindEvent(); function bindEvent() { statrBtn.onclick = function () { if(startGame == true){ box.style.display = 'block'; flagBox.style.display = 'block'; init(); startGame = false; } } box.oncontextmenu = function () {//在box内取消默认右键点击 return false; } box.onmousedown = function (e) {//判断鼠标点击的是左键还是右键 var event = e.target;//获取当前点的是哪个小格子 target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。 if (e.which == 1) {//which==1 是左键 leftClick(event); } else if (e.which == 3) {//which==3 代表右键点击 rightClick(event); } } closeBtn.onclick = function () { //点X之后所有都消失 box.style.display = 'none'; flagBox.style.display = 'none'; alertBox.style.display = 'none'; box.innerHTML = ''; startGame = true; } } function init() {//生成一百个小格子 并且插入box 同时生成10个随机的雷 minesNum = 10; mineOver = 10; score.innerHTML = mineOver; for (var i = 0; i < 10; i++) {//十行 for (var j = 0; j < 10; j++) {//十列 var con = document.createElement('div'); con.classList.add('block');//给生成的每个小格子加一个类名 con.setAttribute('id', i + '-' + j);//给每个小格子加一个id id是i和j的坐标值 box.appendChild(con); mineMap.push({ mine: 0 });//每次生成小格子往数组里面传, 传一个参数mine 初始值0 } } block = document.getElementsByClassName('block');//把一百个小格子利用同类名取出来 while (minesNum) { var mineIndex = Math.floor(Math.random() * 100);//雷通过随机数出现的位置 if (mineMap[mineIndex].mine === 0) {//没有雷 mineMap[mineIndex].mine = 1;//防止同一位置重复生成雷 block[mineIndex].classList.add('isLei');//随机出现雷的标记 minesNum--; } } } function leftClick(dom) {//点左键,看哪个小格子被点击了 if(dom.classList.contains('flag')){//被标记之后不能点击 return; } var isLei = document.getElementsByClassName('isLei'); if (dom && dom.classList.contains('isLei')) {// 判断点击的是雷 contains返回布尔值,判断指定的类名是否存在。 // console.log('gameOver'); for (var i = 0; i < isLei.length; i++) {//如果点击的是雷 把所有的雷展示出来 isLei[i].classList.add('show'); } setTimeout(function () {//让弹出的gameover延迟弹出 alertBox.style.display = 'block'; alertimg.style.backgroundImage = 'url("gameover.jpg")'; }, 800); } else {//不是雷的情况 var n = 0; var posArr = dom && dom.getAttribute('id').split('-'); //dom存在并且getAttribute到id的值是一个字符串 .split变成数组 var posX = posArr && + posArr[0]; //x值是数组第一位 var posY = posArr && + posArr[1]; //y值是数组第二位 dom && dom.classList.add('num'); //点到数字的背景 for (var i = posX - 1; i <= posX + 1; i++) { //周围八个数 for (var j = posY - 1; j <= posY + 1; j++) { var aroundBox = document.getElementById(i + '-' + j);//把周围八个取出来 if (aroundBox && aroundBox.classList.contains('isLei')) { n++; } } } // i-1,j-1 i-1,j i-1,j+1 // i,j-1 i,j i,j+1 // i+1,j-1 i+1,j i+1,j+1 dom && (dom.innerHTML = n); if (n == 0) {//扩散情况 当点击到的是0,再遍历周围八个每一个 for (var i = posX; i <= posX + 1; i++) { //再遍历周围八个 for (var j = posY; j <= posY + 1; j++) { var nearBox = document.getElementById(i + '-' + j); if (nearBox && nearBox.length != 0) { if(!nearBox.classList.contains('check')){//如果不存在classlist不包括check,每个判断一次 nearBox.classList.add('check')//显示完的加一个标记 被判断过的 被显示过的 leftClick(nearBox); }//n = 0的时候结束 } } } } } } function rightClick(dom){//右键点击 标旗 有数字的就不能插旗了 if(dom.classList.contains('num')){//判断当前被点击的dom的classlist是否包含点完出数字的num return; //不做任何动作 } dom.classList.toggle('flag'); //toggle() 方法切换元素的可见状态。 如果被选元素可见,则隐藏这些元素,如果被选元素隐藏,则显示这些元素。 if(dom.classList.contains('isLei') && dom.classList.contains('flag')){//如果点到的是雷而且插上了红旗 // 剩余雷数 mineOver--; } if(dom.classList.contains('isLei') && !dom.classList.contains('flag')){//如果有雷 没有插旗 mineOver ++; } score.innerHTML = mineOver; if(mineOver == 0){//当剩余雷是0的时候 alertBox.style.display = 'block'; alertimg.style.backgroundImage = 'url("baby.jpg")'; setTimeout(function(){ alert('恭喜!!!!!再来一遍吧!!!!!!'); },2500); } }