html实现扫雷游戏

实现代码:

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>Document</title>
  <style>html {
  font-size: 10px;
}

body {
  counter-reset: total cleared bombs flagged;
  font-size: 1.6rem;
  font-family: sans-serif;
}
H1 {
  font-size:2rem;
  margin:1rem auto;
  width:fit-content
}
#game {
  overflow:hidden;
  position:relative;
  margin:0 auto;
  background:lightgrey;
  width:fit-content;
  height:fit-content;
  padding:1rem;
  border:0.3rem outset lightgrey;
  border-radius:1rem;
}
/*
 grid square.
*/

.square {
  position: relative;
  float: left;
  display: block;
  width: 2rem;
  height: 2rem;
  border: 1px grey solid;
  background-color: lightgrey;
  text-align: center;
}
/*
these will be the "buttons"
that hide the grid.
*/

.square > label,
.square > .flag {
  position: absolute;
  left: -0.1rem;
  top: -0.1rem;
  right: -0.1rem;
  bottom: -0.1rem;
  border: 0.2rem outset grey;
  background-color: darkgrey;
}
/*
switch for flag mode and clear mode
*/
#flag-mode {
  display:none;
}
/*
buttons for global settings
*/
[for="flag-mode"],
[for="show-bombs"] {
  display:block;
  margin:0 auto;
  width:fit-content;
  background:lightgrey;
  padding:0 0.5rem;
  border:2px outset grey;
  border-radius:0.5rem;
  margin:0.2rem auto;
}
#flag-mode:not(:checked) + [for="flag-mode"]:after {
  content:" OFF ";
  font-weight:bold;
}
#flag-mode:checked + [for="flag-mode"]:after {
  content:" ON ";
  font-weight:bold;
}

/*
checkboxes to control state of each square
these need to be "visible"
for the counter to work.
push them far off to the left.
*/
.open-square,.flag-square {
  position: absolute;
  left: -1000rem;
}
/*
count the total clearable
*/
.open-square:not(.bomb) {
  counter-increment:total;
}
/*
count the number of bombs
*/
.open-square.bomb {
  counter-increment:bombs;
}
/*
hide the label "button" when it's clicked
*/
.open-square:checked + .square > label {
  display: none;
}
/*
show the number of surounding bombs (if any)
with different colors for the count values
*/
:not(.bomb)[data-count] + .square:before {
  line-height:2rem;
  font-weight:bold;
}
:not(.bomb)[data-count="1"] + .square:before {
  content:"1";
  color: blue;
}
:not(.bomb)[data-count="2"] + .square:before {
  content:"2";
  color: green;
}
:not(.bomb)[data-count="3"] + .square:before {
  content:"3";
  color: red;
}
:not(.bomb)[data-count="4"] + .square:before {
  content:"4";
  color: darkblue;
}
:not(.bomb)[data-count="5"] + .square:before {
  content:"5";
  color: brown;
}
:not(.bomb)[data-count="6"] + .square:before {
  content:"6";
  color: cyan;
}
:not(.bomb)[data-count="7"] + .square:before {
  content:"7";
  color: black;
}
:not(.bomb)[data-count="8"] + .square:before {
  content:8;
  color: grey;
}
/*
bomb square.
*/
.bomb + .square {
  background-color: red
}
.bomb + .square:before {
  content: "💣";
  line-height: 2rem;
  font-size: 1.2rem;
}
/*
default hide the flag
*/
.flag {
  display:none;
}
/*
show the flag if square is flagged
and count it
*/
.flag-square:checked ~ .flag {
  display:block;
  counter-increment:flagged;
}
/*
display flag as needed
*/
.flag-square:checked ~ .flag-label:before,
.flag-square:checked ~ .flag:before {
content:"🚩"
}
/*
hide the label when not in flag mode
*/
#flag-mode:not(:checked) ~ .square > .flag-label {
  display:none;
}
/*
only show the flag if the square isn't in "show" mode.
*/
#flag-mode:checked ~ .show-square:not(:checked) + .square > .flag-label {
  display:block;
}

/*
increment cleared counter 
for each non-bomb checked
and keep the total intact
*/
.open-square:not(.bomb):checked {
  counter-increment: total cleared;
}
/*
various counter displays
*/
.bombs {
  width:50%;
  text-align:center;
}
.score {
  clear:both;
  float:right;
  text-align:right;
  width:50%;
  text-align:center;
}

/*
track the bombs
*/
.bombs:after {
  content: counter(bombs) "🚩" counter(flagged);
  line-height:3rem;
  border:0.2rem inset lightgrey;
  padding:0.2rem 0.5rem;
  background-color:white;
  border-radius:0.5rem;
}
/*
track the total cleareable & cleared 
*/
.score:after {
  content: counter(cleared) " of " counter(total);
  line-height:3rem;
  border:0.2rem inset lightgrey;
  padding:0.2rem 0.5rem;
  background-color:white;
  border-radius:0.5rem;
}
/*
default setting is the win state
*/
.message {
  clear: left;
  color: limegreen;
  text-align:center;
  font-weight:bold;
}
.message:before {
  content: "(: YOU WIN! :) "
}
/*
  block user interaction with
  game board after a win.
*/
.pane
{
  display:block;
  position:absolute;
  left:0;
  right:0;
  top:0;
  bottom:0;
}
/*
override for the playing state
*/
.open-square:not(.grouped):not(.bomb):not(:checked) ~ .message:before,
.group-master:not(:checked) ~ .message:before
{
  content: none;
}
/*
  play state. hide the blocking pane.
*/
.open-square:not(.grouped):not(.bomb):not(:checked) ~ .pane,
.group-master:not(:checked) ~ .pane,
.lost-game
{
  display: none;
}
/*
finally, the losing state
*/
.open-square.bomb:checked ~ .message {
  color: red;
}
/*
  reinstate the blocking pane
*/
.open-square.bomb:checked ~ .pane
{
  position:relative;
  display:block;
}
.open-square.bomb:checked ~ .message:before {
  content: " ): You Lose :(" !important;
}
/*
display thre show bombs button if you've lost
*/
.open-square.bomb:checked ~ .lost-game
{
  position:relative;
  display:block;
  z-index:2
}
/*
display any hidden bombs
*/
#show-bombs:checked ~ .bomb + .square > label {
  display:none;
}
/*
mark any falsely flagged squares as wrong.
*/
#show-bombs:checked ~ .open-square:not(.bomb) + .square > .flag:after {
  content: "❌";
  position:absolute;
  top:-0.4rem;
  left:-0.1rem;
}
  </style>
 </head>
 <body>
 <div id="game">
  <h1>Bomb CSSweeper</h1>
  <input type="checkbox" id="show-bombs" hidden>
  <input type="checkbox" id="flag-mode">
  <label for="flag-mode">🚩mode</label>
  <div class="pane"></div>
  <div class="score">Cleared:
    <br>
  </div>
  <div class="bombs">Bombs:
    <br>
  </div>
  <div class="message"></div>
  <div class="lost-game">
    <label for="show-bombs">Show Bombs</label>
  </div>
</div>
<script>
/*
  Using Javascript to :
  - generate a board of randomized size.
  - randomly place bombs
  - insert custom CSS to display board size properly
  - find and group empty & ajacent squares 
    for fast clearing
  - insert custom CSS to handle the group clearing. 
*/
// randomize board size and bomb count
var rows = Math.floor(10 + (Math.random() * 5));
var cols = Math.floor(10 + (Math.random() * 5));
var bombs = Math.floor(15 + (Math.random() * 10));
var i, s, l, fi, fs, fl;
var game = document.getElementById('game');
var pane = game.querySelector('.pane');
var grid = [];
//add stylesheet handle board size
var style = document.createElement('style');
//row wrapping.
style.innerHTML = ".square:nth-of-type(" + cols + "n+1) {clear:left;}\n";
game.insertBefore(style, pane);
//add the grid elements
for (var r = 1; r <= rows; r++) {
  grid[r] = [];
  for (var c = 1; c <= cols; c++) {
    //controls the showing of a grid
    i = grid[r][c] = document.createElement('input');
    i.type = 'checkbox';
    i.classList.add('open-square')
    i.id = 'open-r' + r + '-c' + c;
    i.r = r;
    i.c = c;
    game.insertBefore(i, pane);
    //the actual grid square
    s = document.createElement('span');
    s.classList.add('square');
    game.insertBefore(s, pane);
    //hide the square contents 
    //and switches the show control
    l = document.createElement('label');
    l.htmlFor = i.id;
    l.classList.add('open-label');
    s.appendChild(l);
    //flag switch control
    fi = document.createElement('input');
    fi.type = "checkbox";
    fi.classList.add('flag-square');
    fi.id = 'flag-r' + r + '-c' + c;
    s.appendChild(fi);
    //only visible is squre "flagged"
    //hide the square contents
    //and the show label
    fs = document.createElement('span');
    fs.classList.add('flag');
    s.appendChild(fs);
    //only visible in "flag mode" 
    //(if square not "shown") 
    //and switches the flag control
    fl = document.createElement('label');
    fl.htmlFor = fi.id;
    fl.classList.add('flag-label');
    s.appendChild(fl);
  }
}
//randomly assign bomb state to some
for (var b = 0; b < bombs; b++) {
  do {
    r = 1 + (Math.random() * rows) >> 0;
    c = 1 + (Math.random() * cols) >> 0;
    console.log(r, c, grid[r][c]);
  } while (grid[r][c].classList.contains('bomb'));
  i = grid[r][c];
  i.classList.add('bomb');
  //also increment
  //surronding square's count
  //to indicate number of adjacent
  //bombs.
  var list = getSurrounding(i)
  for (r = 0; r < list.length; r++) {
    i = list[r];
    var count = Number(i.getAttribute('data-count')) || 0;
    i.setAttribute('data-count', ++count);
    i = i.nextElementSibling;
    i.setAttribute('data-count', count);
  }
}
//locate the groups of "empty" squares
var group = 1;
//while an ungrouped empty square exists
while (i = document.querySelector('.open-square:not([data-count]):not(.grouped)')) {
  //create an array of empty squares to group
  var check = [i];
  do {
    //grab a square off the check list
    i = check.pop();
    //get surrounding squares
    list = getSurrounding(i)
    for (r = 0; r < list.length; r++) {
      i = list[r];
      //if they're not part of the group
      if (!i.classList.contains('group' + group)) {
        //mark them as so
        i.classList.add('grouped');
        i.classList.add('group' + group);
        //if they're also empty
        if (!i.getAttribute('data-count')) {
          //add the m to the group check array
          check.push(i);
          //and point their label to the group master switch
          i = document.querySelector('[for="' + i.id + '"]');
          i.htmlFor = 'group' + group;
        }
      }
    }
    //repeat until all empty squares are grouped
  } while (check.length);
  //create the master switch
  i = document.createElement('input');
  i.type = 'checkbox';
  i.classList.add('group-master');
  i.hidden = true;
  i.id = 'group' + group;
  //add styles to disply all squares in the group
  //and increment the cleared counter accordingly
  style.innerHTML += '#group' + group + ':checked ~ .group' + group + ' + .square > label { display:none; }\n' + '#group' + group + ':checked ~ .group' + group + ' { counter-increment:cleared total }\n';
  game.insertBefore(i, style);
  //and move on to the next group (if any)
  group++;
}
//grabs squares around a given square, inclusive
function getSurrounding(i) {
  var rs = Math.max(i.r - 1, 1);
  var re = Math.min(i.r + 1, rows);
  var cs = Math.max(i.c - 1, 1);
  var ce = Math.min(i.c + 1, cols);
  var result = [];
  for (r = rs; r <= re; r++) {
    for (c = cs; c <= ce; c++) {
      result.push(grid[r][c]);
    }
  }
  return result;
}
</script>
 </body>
</html>

实现结果:

在这里插入图片描述

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的 HTML 扫雷游戏实现: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>扫雷游戏</title> <style> table { border-collapse: collapse; } td { width: 25px; height: 25px; border: 1px solid gray; text-align: center; vertical-align: middle; font-size: 20px; font-weight: bold; } .covered { background-color: #999; } .uncovered { background-color: #ddd; } .mine { background-color: red; } </style> </head> <body> <h1>扫雷游戏</h1> <table id="gameBoard"></table> <script> const ROWS = 10; const COLS = 10; const MINES = 10; let gameBoard = document.getElementById("gameBoard"); let board = []; function createBoard() { for (let row = 0; row < ROWS; row++) { let tr = document.createElement("tr"); let rowArr = []; for (let col = 0; col < COLS; col++) { let td = document.createElement("td"); td.classList.add("covered"); td.setAttribute("data-row", row); td.setAttribute("data-col", col); td.addEventListener("click", handleCellClick); tr.appendChild(td); rowArr.push({mine: false, covered: true, flagged: false}); } gameBoard.appendChild(tr); board.push(rowArr); } } function handleCellClick(event) { let td = event.target; let row = Number(td.getAttribute("data-row")); let col = Number(td.getAttribute("data-col")); if (board[row][col].mine) { td.classList.remove("covered"); td.classList.add("mine"); alert("游戏结束!"); } else { uncoverCell(row, col); } } function uncoverCell(row, col) { let td = gameBoard.querySelector(`[data-row="${row}"][data-col="${col}"]`); if (!td || !board[row][col].covered) { return; } td.classList.remove("covered"); td.classList.add("uncovered"); board[row][col].covered = false; let mines = countMines(row, col); if (mines > 0) { td.innerText = mines; } else { uncoverCell(row - 1, col - 1); uncoverCell(row - 1, col); uncoverCell(row - 1, col + 1); uncoverCell(row, col - 1); uncoverCell(row, col + 1); uncoverCell(row + 1, col - 1); uncoverCell(row + 1, col); uncoverCell(row + 1, col + 1); } } function countMines(row, col) { let count = 0; if (row > 0 && col > 0 && board[row - 1][col - 1].mine) { count++; } if (row > 0 && board[row - 1][col].mine) { count++; } if (row > 0 && col < COLS - 1 && board[row - 1][col + 1].mine) { count++; } if (col > 0 && board[row][col - 1].mine) { count++; } if (col < COLS - 1 && board[row][col + 1].mine) { count++; } if (row < ROWS - 1 && col > 0 && board[row + 1][col - 1].mine) { count++; } if (row < ROWS - 1 && board[row + 1][col].mine) { count++; } if (row < ROWS - 1 && col < COLS - 1 && board[row + 1][col + 1].mine) { count++; } return count; } function plantMines() { let minesPlanted = 0; while (minesPlanted < MINES) { let row = Math.floor(Math.random() * ROWS); let col = Math.floor(Math.random() * COLS); if (!board[row][col].mine) { board[row][col].mine = true; minesPlanted++; } } } createBoard(); plantMines(); </script> </body> </html> ``` 这段代码会创建一个 10x10 的游戏面板,其中包含 10 个地雷。玩家需要点击方格,如果点击到地雷,游戏结束;否则,会显示周围的地雷数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值