Skip to content

Instantly share code, notes, and snippets.

@3ki5tj
Created November 18, 2014 21:14
Show Gist options
  • Save 3ki5tj/f8e932a413efe6a715e7 to your computer and use it in GitHub Desktop.
Save 3ki5tj/f8e932a413efe6a715e7 to your computer and use it in GitHub Desktop.
Minesweep
<!DOCTYPE html>
<html>
<head>
<style>
body {
font: 90% "MS Trebunchet", "Lucida Grande", 'Verdana', 'Tahoma', 'Calibri', sans-serif;
width: 600px;
margin: auto;
}
h1 {
font: small-caps 160% "Constantia", "Times New Roman", serif;
}
table { border-collapse: collapse; }
div#tablewrapper {
-moz-user-select: none;
-webkit-user-select: none;
}
td {
width: 25px;
height: 25px;
text-align: center;
padding: 0px;
}
td.flag {
background-color: #d0d0d0;
border: #000000 2px ridge;
color: #d00000;
font-weight: bold;
}
td.close {
background-color: #d0d0d0;
border: #c0c0c0 2px groove;
}
td.open {
background-color: #a0a0a0;
border: #c0c0c0 2px groove;
font-weight: bold;
}
td.dead {
background-color: #ff0000;
border: #c0c0c0 2px groove;
}
</style>
<script>
/* Minesweep game */
var lx = 10, ly = 10;
var nmine = 10;
var gameover = 0;
var startplay = false;
var colors = ["#000000", "#0000ff", "#008000", "#008080", "#800000",
"#8000ff", "#ff8000", "#ff8000", "#ff0000"];
var time0;
var symmine = "&#9679;"
var symflag = "&#9873;";
var btleft = 0;
var btright = 2;
var isie = /MSIE (\d+)\.\d+;/.test(navigator.userAgent);
if (isie) isie = new Number(RegExp.$1);
var isff = /Firefox\/(\d+)\./.test(navigator.userAgent);
if (isff) isff = new Number(RegExp.$1);
var iswin = /Windows/.test(navigator.userAgent);
var islinux = /Linux/.test(navigator.userAgent);
if (isie > 0 && isie <= 8) btleft = 1;
if (iswin) symflag = "&#9650;";
// disable selection for IE
document.onselectstart = function() { return false; }
var s = null; // Grid array
// define a grid type
function Grid(i, j) {
this.i = i;
this.j = j;
this.open = false; // open or closed
this.mine = false; // is a mine or not
this.flag = false; // flagged or not
this.nb = null; // array of neighbors
this.nbmcnt = 0; // # of neighoring mines
}
function makeboard()
{
var i, j, id, n;
lx = parseInt( document.getElementById("lx").value );
if (lx < 2) lx = 2;
ly = parseInt( document.getElementById("ly").value );
if (ly < 2) ly = 2;
nmine = parseInt( document.getElementById("nmine").value );
if (nmine < 1) nmine = 1;
n = lx*ly;
s = new Array();
for (id = 0, i = 0; i < lx; i++)
for (j = 0; j < ly; j++, id++)
s[id] = new Grid(i, j);
// assign mines
for (var im = 0; im < nmine; im++) {
while (1) {
id = Math.floor(Math.random() * n);
if (!s[id].mine) break;
}
s[id].mine = true;
}
// compute neighbors
for (i = 0; i < lx; i++) {
for (j = 0; j < ly; j++) {
id = i*ly + j;
if (s[id].mine) continue;
nb = new Array();
if (i > 0) nb.push(s[(i-1)*ly + j]);
if (i > 0 && j > 0) nb.push(s[(i-1)*ly + j-1]);
if (i > 0 && j < ly - 1) nb.push(s[(i-1)*ly + j+1]);
if (j > 0) nb.push(s[i*ly + j-1]);
if (j < ly - 1) nb.push(s[i*ly + j+1]);
if (i < lx - 1) nb.push(s[(i+1)*ly + j]);
if (i < lx - 1 && j > 0) nb.push(s[(i+1)*ly + j-1]);
if (i < lx - 1 && j < ly - 1) nb.push(s[(i+1)*ly + j+1]);
s[id].nb = nb;
// coount neighboring mines
var cnt = 0;
for (k = 0; k < nb.length; k++)
if (nb[k].mine) cnt++;
s[id].nbmcnt = cnt;
}
}
}
function drawboard()
{
var i, j;
str = '<table id="board">\n';
for (j = 0; j < ly; j++) {
str += "<tr>";
for (i = 0; i < lx; i++) {
id = i*ly + j;
var sym = "&nbsp;"
// find the proper CSS style for the cell
if (s[id].open) { // an open cell
if (s[id].mine) {
cls = "class='dead' ";
sym = symmine;
} else {
cls = "class='open' ";
if (s[id].nbmcnt > 0) {
cls += 'style="color:' + colors[s[id].nbmcnt] + ';" '
sym = "" + s[id].nbmcnt;
}
}
} else { // a closed cell
if (s[id].flag) {
cls = "class='flag' ";
sym = symflag;
} else cls = "class='close' "
}
if (isff >= 4 && isff <= 6 && islinux) { // my ubuntu maps mousedown to contextmenu
str1 = ' oncontextmenu="mousedown(id, event);" ';
} else
str1 = "";
str += "<td id='" + id + "' " + cls + str1
+ ' onmousedown="mousedown(id, event)">'
+ sym + '</' + 'td>';
}
str += '</' + 'tr>\n';
}
str += '</' + 'table>\n';
document.getElementById("tablewrapper").innerHTML = str;
}
function open(id)
{
var st = new Array();
st.push(s[id]);
while (st.length > 0) {
var len = st.length;
if (!st[0].open && !st[0].flag) {
st[0].open = true;
if (!st[0].mine && st[0].nbmcnt == 0) {
var k, nb = st[0].nb;
for (k = 0; k < nb.length; k++) // put more stuff in the queue
if (!nb[k].mine && !nb[k].open)
st.push(nb[k]);
}
}
st.shift(); // remove the first grid
}
}
function check()
{
var id, s0 = 0, dead = 0, sf = 0;
for (id = 0; id < lx*ly && !dead; id++) {
if (s[id].open) {
if (s[id].mine) dead = 1;
} else if (s[id].flag) { // flag
sf++;
} else { // closed
s0++;
}
}
var delt = Math.round( ((new Date().getTime()) - time0)*0.001 );
if (dead) {
alert ("Game over in " + delt + " seconds, you lose.");
gameover = -1;
} else if (s0 == 0 && sf == nmine) {
alert ("Game over in " + delt + " seconds, you win!");
gameover = 1;
}
}
function mousedown(id, e)
{
if (gameover) return false;
if (!startplay) {
startplay = true;
time0 = new Date().getTime();
}
id = parseInt(id);
if (!e) e = window.event;
if (e.button == btright || e.shiftKey || e.ctrlKey || e.altKey) { // right-click or click with Shift
if (!s[id].open)
s[id].flag = !s[id].flag;
} else if (e.button == btleft) { // normal click
open(id);
}
drawboard();
check();
}
function initboard()
{
// disable the context menu
document.getElementById("tablewrapper").oncontextmenu = function() { return false; }
gameover = 0;
startplay = false;
makeboard();
drawboard();
}
window.onload = initboard;
</script>
</head>
<body>
<h1>Minesweep</h1>
<div id="appwrapper">
Number of rows: <input type="text" id="lx" value="10" size="4"><br>
Number of columns: <input type="text" id="ly" value="10" size="4"><br>
Number of mines: <input type="text" id="nmine" value="10" size="6"><br>
<input type="button" id="okay" value="Play" onClick="initboard()" />
<div id="tablewrapper">
</div>
<p><sup>&dagger;</sup>
In marking a mine, if right-clicking does not work,
try to left click cells with the Shift key pressed down.
</p>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment