HTML+CSS+JS扫雷游戏
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>扫雷游戏</title>
<link rel="stylesheet" href="index.css">
<script src="index.js" defer ></script>
</head>
<body>
<div class="container">
<h1>扫雷游戏</h1>
<p>注意:左键探测,右键插旗,再次右键可取消插旗</p>
<div class="level">
<button class="active">初级</button>
<button>中级</button>
<button>高级</button>
</div>
<div class="info">
<p>总雷数:<span class="mineNum"></span></p>
<p>插旗数:<span class="flagNum"></span></p>
</div>
<div class="mineArea"></div>
</div>
</body>
</html>
index.js
var config = {
easy: {
row: 10,
col: 10,
mineNum: 10
},
normal: {
row: 15,
col: 15,
mineNum: 30
},
hard: {
row: 20,
col: 20,
mineNum: 60
}
}
var curLevel = config.easy
function $(selector) {
return document.querySelector(selector)
}
function $$(selector) {
return document.querySelectorAll(selector)
}
var mineArray = null
var mineArea = $('.mineArea')
var tableData = []
var flagArray = []
var buttons = $$('.level>button')
var flagNum = $('.flagNum')
var mineNumber = $('.mineNum')
function initMine() {
var arr = new Array(curLevel.row * curLevel.col)
for (var i = 0; i < arr.length; i++) {
arr[i] = i
}
arr.sort(() => 0.5 - Math.random())
return arr.slice(0, curLevel.mineNum);
}
function clearScene(){
mineArea.innerHTML = ''
flagArray = []
flagNum.innerHTML = 0
mineNumber.innerHTML = curLevel.mineNum
}
function init() {
clearScene();
mineArray = initMine();
var table = document.createElement('table')
var index = 0
for (var i = 0; i < curLevel.row; i++) {
var tr = document.createElement('tr')
tableData[i] = []
for (var j = 0; j < curLevel.col; j++) {
var td = document.createElement('td')
var div = document.createElement('div')
tableData[i][j] = {
row: i,
col: j,
type: 'number',
value: 0,
index,
checked: false
}
div.dataset.id = index
div.classList.add('canFlag')
if (mineArray.includes(tableData[i][j].index)) {
tableData[i][j].type = 'mine';
div.classList.add('mine')
}
td.appendChild(div)
tr.appendChild(td)
index++
}
table.appendChild(tr)
}
mineArea.appendChild(table)
mineArea.onmousedown = function (e) {
if (e.button === 0) {
searchArea(e.target)
}
if (e.button === 2) {
flag(e.target)
}
}
}
function showAnswer() {
var isAllRight = true
var mineArr = $$('td>div.mine')
for (var i = 0; i < mineArr.length; i++) {
mineArr[i].style.opacity = 1
}
for (var i = 0; i < flagArray.length; i++) {
if (flagArray[i].classList.contains('mine')) {
flagArray[i].classList.add('right')
} else {
flagArray[i].classList.add('error')
isAllRight = false
}
}
if (!isAllRight || flagArray.length !== curLevel.mineNum) {
gameOver(false)
}
mineArea.onmousedown = null
}
function getTableItem(cell) {
var index = cell.dataset.id
var flatTableData = tableData.flat()
return flatTableData.filter(item => item.index == index)[0]
}
function getBound(obj) {
var rowTop = obj.row - 1 < 0 ? 0 : obj.row - 1
var rowBottom = obj.row + 1 === curLevel.row ? curLevel.row - 1 : obj.row + 1
var colLeft = obj.col - 1 < 0 ? 0 : obj.col - 1
var colRight = obj.col + 1 === curLevel.col ? curLevel.col - 1 : obj.col + 1
return {
rowTop,
rowBottom,
colLeft,
colRight
}
}
function findMineNum(obj) {
var count = 0
var { rowTop, rowBottom, colLeft, colRight } = getBound(obj)
for (var i = rowTop; i <= rowBottom; i++) {
for (var j = colLeft; j <= colRight; j++) {
if (tableData[i][j].type == 'mine') {
count++
}
}
}
return count
}
function getDOM(obj) {
var divArray = $$('td>div')
return divArray[obj.index]
}
function getAround(cell) {
if (!cell.classList.contains('flag')) {
cell.parentNode.style.border = 'none'
cell.classList.remove('canFlag')
var tableItem = getTableItem(cell)
if (!tableItem) {
return;
}
tableItem.checked = true
var mineNum = findMineNum(tableItem)
if (!mineNum) {
var { rowTop, rowBottom, colLeft, colRight } = getBound(tableItem)
for (var i = rowTop; i <= rowBottom; i++) {
for (var j = colLeft; j <= colRight; j++) {
if (!tableData[i][j].checked) {
getAround(getDOM(tableData[i][j]))
}
}
}
} else {
var cl = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight']
cell.classList.add(cl[mineNum])
cell.innerHTML = mineNum
}
}
}
function searchArea(cell) {
if (cell.classList.contains('mine')) {
cell.classList.add('error');
showAnswer()
return
}
getAround(cell)
}
function isWin() {
for (var i = 0; i < flagArray.length; i++) {
if (!flagArray[i].classList.contains('mine')) {
return false
}
return true
}
}
function gameOver(isWin) {
var mess = ''
if (isWin) {
mess = '恭喜您,获得胜利'
} else {
mess = '很遗憾,游戏失败'
}
setTimeout(function () {
window.alert(mess)
}, 0)
}
function flag(cell) {
if (cell.classList.contains('canFlag')) {
if (!flagArray.includes(cell)) {
flagArray.push(cell)
cell.classList.add('flag')
if (flagArray.length === curLevel.mineNum) {
if (isWin()) {
gameOver(true)
}
showAnswer()
}
} else {
var index = flagArray.indexOf(cell)
flagArray.splice(index, 1)
cell.classList.remove('flag')
}
flagNum.innerHTML = flagArray.length
}
}
function bindEvent() {
mineArea.oncontextmenu = function (e) {
e.preventDefault();
}
$('.level').onclick = function (e) {
for (var i = 0; i < buttons.length; i++) {
buttons[i].classList.remove('active')
}
e.target.classList.add('active')
switch(e.target.innerHTML){
case "初级":{
curLevel = config.easy
break;
};
case "中级":{
curLevel = config.normal
break;
};
case "高级":{
curLevel = config.hard
break;
};
}
init()
}
}
function main() {
init();
bindEvent();
}
main();
index.css
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'KAITI';
}
body{
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background:linear-gradient(to bottom right, rgb(128, 128, 237), pink) ;
}
.container{
margin: 10px;
}
h1{
text-align: center;
margin: 10px;
color: rgb(8, 74, 198);
}
p{
text-align: center;
margin: 10px;
}
.container .level{
text-align: center;
padding: 10px;
}
.container .level button{
width: 100px;
height: 30px;
margin-left: 10px;
margin-right: 10px;
background: linear-gradient( rgb(12, 107, 224),rgb(7, 201, 140));
font-size: 20px;
color: rgb(249, 249, 248);
transition: transform 0.3s;
}
.container .level button:hover{
cursor: pointer;
transform: scale(1.25);
}
.container .level button.active{
background: linear-gradient(rgb(229, 45, 45) ,rgb(79, 35, 166));
}
.container .info{
font-size: 20px;
display: flex;
justify-content: center;
align-items: center;
}
.container .info p{
margin-right: 20px;
margin-left: 20px;
}
.container .info p span{
color: #e30a19;
}
.container .area{
display: grid;
align-items: center;
justify-content: center;
}
.container .mineArea{
display: flex;
justify-content: center;
}
.container .mineArea table{
background:rgb(246, 228, 231);
border-spacing: 1px;
}
.container .mineArea table td{
width: 24px;
height: 24px;
border: 2px solid;
background-color: rgb(179, 211, 244);
border-color: #f8f0f0 rgb(2, 34, 94) rgb(2, 21, 56) #f8f0f0;
text-align: center;
line-height: 24px;
font-weight: bold;
cursor: pointer;
}
.container .mineArea table td>div{
width: 100%;
height: 100%;
border-color: #fff;
background: rgb(179, 211, 244);
}
.container .mineArea table td>div.mine{
background: rgb(179, 211, 244) url('./image/mine.png') center/cover no-repeat;
opacity: 0;
}
.container .mineArea table td>div.flag{
background: rgb(179, 211, 244) url('./image/flag.png') center/cover no-repeat;
opacity: 1;
}
.container .mineArea table td>div.error{
background-color: rgb(239, 151, 151) ;
}
.container .mineArea table td>div.right{
background-color: rgb(159, 234, 168) ;
opacity: 1;
}
.container .mineArea table td>div.zero{
border-color: #fff;
background: rgb(179, 211, 244);
}
.container .mineArea table td>div.one{
border-color: #fff;
background: rgb(179, 211, 244);
color: blue;
}
.container .mineArea table td>div.two{
border-color: #fff;
background: rgb(179, 211, 244);
color: rgb(222, 56, 153);
}
.container .mineArea table td>div.three{
border-color: #fff;
background: rgb(179, 211, 244);
color: rgb(27, 206, 161);
}
.container .mineArea table td>div.four{
border-color: #fff;
background: rgb(179, 211, 244);
color: rgb(76, 214, 38);
}
.container .mineArea table td>div.five{
border-color: #fff;
background: rgb(179, 211, 244);
color: rgb(164, 197, 33);
}
.container .mineArea table td>div.six{
border-color: #fff;
background: rgb(179, 211, 244);
color: rgb(192, 69, 69);
}
.container .mineArea table td>div.seven{
border-color: #fff;
background: rgb(179, 211, 244);
color: rgb(7, 97, 44);
}
.container .mineArea table td>div.eight{
border-color: #fff;
background: rgb(179, 211, 244);
color: rgb(155, 8, 84);
}
运行结果