<!doctype html><htmllang="en"><head><metacharset="UTF-8"><metaname="Generator"content="EditPlus®"><metaname="Author"content=""><metaname="Keywords"content=""><metaname="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><divid="game"><h1>Bomb CSSweeper</h1><inputtype="checkbox"id="show-bombs"hidden><inputtype="checkbox"id="flag-mode"><labelfor="flag-mode">🚩mode</label><divclass="pane"></div><divclass="score">Cleared:
<br></div><divclass="bombs">Bombs:
<br></div><divclass="message"></div><divclass="lost-game"><labelfor="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 countvar 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 sizevar 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 elementsfor(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 somefor(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" squaresvar group =1;//while an ungrouped empty square existswhile(i = document.querySelector('.open-square:not([data-count]):not(.grouped)')){//create an array of empty squares to groupvar 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 groupif(!i.classList.contains('group'+ group)){//mark them as so
i.classList.add('grouped');
i.classList.add('group'+ group);//if they're also emptyif(!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, inclusivefunctiongetSurrounding(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>