Created
November 18, 2014 21:14
-
-
Save 3ki5tj/f8e932a413efe6a715e7 to your computer and use it in GitHub Desktop.
Minesweep
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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 = "●" | |
var symflag = "⚑"; | |
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 = "▲"; | |
// 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 = " " | |
// 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>†</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