848 lines
30 KiB
HTML
848 lines
30 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>endless mines</title>
|
|
<style type="text/css">
|
|
@font-face {
|
|
font-family: Helsinki;
|
|
src: url('helsinki.eot');
|
|
src: url('helsinki.eot?#iefix') format('embedded-opentype'),
|
|
url('helsinki.woff2') format('woff2'),
|
|
url('helsinki.woff') format('woff'),
|
|
url('helsinki.ttf') format('truetype'),
|
|
url('helsinki.svg#helsinkiregular') format('svg');
|
|
font-weight: normal;
|
|
font-style: normal;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
font-family: Helsinki;
|
|
}
|
|
|
|
html {
|
|
background-color: #272822;
|
|
margin: 0;
|
|
height: 10em; /* fallback */
|
|
height: 100vh;
|
|
width: 10em; /* fallback */
|
|
width: 100vw;
|
|
overflow: hidden;
|
|
-moz-user-select: none;
|
|
-webkit-user-select: none;
|
|
-ms-user-select: none;
|
|
user-select: none;
|
|
}
|
|
|
|
body {
|
|
height: 10em; /* fallback */
|
|
height: 100vh;
|
|
margin: 0 auto;
|
|
width: 10em; /* fallback */
|
|
width: 100vmin;
|
|
}
|
|
|
|
#game {
|
|
background-color: #1b1c17;
|
|
float: left;
|
|
margin: 0 auto;
|
|
height: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
#stats {
|
|
height: 1em; /* fallback */
|
|
height: 10vmin;
|
|
width: 10em; /* fallback */
|
|
width: 100vmin;
|
|
float: left;
|
|
|
|
background: #768087;
|
|
background: -moz-linear-gradient(top, #768087 0%, #53595e 100%);
|
|
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #768087), color-stop(100%, #53595e));
|
|
background: -webkit-linear-gradient(top, #768087 0%,#53595e 100%);
|
|
background: -o-linear-gradient(top, #768087 0%,#53595e 100%);
|
|
background: -ms-linear-gradient(top, #768087 0%,#53595e 100%);
|
|
background: linear-gradient(to bottom, #768087 0%,#53595e 100%);
|
|
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#768087', endColorstr='#53595e',GradientType=0 );
|
|
}
|
|
|
|
#stats button {
|
|
margin: 0.1em; /* fallback */
|
|
margin: 1vmin;
|
|
float: right;
|
|
font-size: 0.3em; /* fallback */
|
|
font-size: 3vmin;
|
|
border-radius: 0.2em; /* fallback */
|
|
border-radius: 2vmin;
|
|
padding: 0.175em; /* fallback */
|
|
padding: 1.75vmin;
|
|
box-shadow: 0.05em 0.05em 0 #000; /* fallback */
|
|
box-shadow: 0.5vmin 0.5vmin 0 #000;
|
|
border: 0.4vmin solid #454e52;
|
|
position: relative;
|
|
top: auto;
|
|
left: auto;
|
|
}
|
|
|
|
#stats div {
|
|
float: left;
|
|
font-size: 0.54em; /* fallback */
|
|
font-size: 5.4vmin;
|
|
margin: 0.2em; /* fallback */
|
|
margin: 2vmin;
|
|
width: auto;
|
|
}
|
|
|
|
#gameOver, #setup {
|
|
position: absolute;
|
|
width: 10em; /* fallback */
|
|
width: 100vmin;
|
|
height: 10em; /* fallback */
|
|
height: 100vh;
|
|
background-color: rgba(0,0,0,0.3);
|
|
}
|
|
|
|
#setup h2 {
|
|
margin-top: 0;
|
|
}
|
|
|
|
#setup h2,
|
|
#setup label {
|
|
margin: 0.4em 0.35em; /* fallback */
|
|
margin: 4vmin 3.5vmin;
|
|
font-size: 0.6em; /* fallback */
|
|
font-size: 6vmin;
|
|
color: #fe7ac6;
|
|
text-shadow: 0.05em 0.05em 0 #a4f4b4; /* fallback */
|
|
text-shadow: 0.5vmin 0.5vmin 0 #a4f4b4; /* x y blur-radius colour */
|
|
}
|
|
|
|
#setup div.centre {
|
|
text-align: center;
|
|
margin-top: 0.2em; /* fallback */
|
|
margin-top: 2vmin;
|
|
}
|
|
|
|
input[type="radio"] {
|
|
display: none;
|
|
}
|
|
|
|
/* after checked input */
|
|
input:checked + label {
|
|
border: 0.1em dotted #a4f4b4; /* fallback */
|
|
border: 1vmin dotted #a4f4b4;
|
|
border-radius: 0.2em; /* fallback */
|
|
border-radius: 2vmin;
|
|
padding: 0.1em 0.2em; /* fallback */
|
|
padding: 1vmin 2vmin;
|
|
}
|
|
|
|
button {
|
|
font-size: 0.6em; /* fallback */
|
|
font-size: 6vmin;
|
|
border-radius: 0.2em; /* fallback */
|
|
border-radius: 2vmin;
|
|
padding: 0.2em; /* fallback */
|
|
padding: 2vmin;
|
|
margin: 0 auto;
|
|
box-shadow: 0.1em 0.1em 0 #000; /* fallback */
|
|
box-shadow: 1vmin 1vmin 0 #000;
|
|
border: none;
|
|
|
|
background: #768087;
|
|
background: -moz-linear-gradient(top, #768087 0%, #53595e 100%);
|
|
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#768087), color-stop(100%,#53595e));
|
|
background: -webkit-linear-gradient(top, #768087 0%,#53595e 100%);
|
|
background: -o-linear-gradient(top, #768087 0%,#53595e 100%);
|
|
background: -ms-linear-gradient(top, #768087 0%,#53595e 100%);
|
|
background: linear-gradient(to bottom, #768087 0%,#53595e 100%);
|
|
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#768087', endColorstr='#53595e',GradientType=0 );
|
|
}
|
|
|
|
button.cancel {
|
|
right: 2em;
|
|
right: 20vmin;
|
|
left: auto;
|
|
}
|
|
|
|
h1, h2 {
|
|
text-align: center;
|
|
}
|
|
|
|
h1 {
|
|
color: #a4f4b4;
|
|
font-size: 1.2em; /* fallback */
|
|
font-size: 12vmin;
|
|
margin-top: 0.6em; /* fallback */
|
|
margin-top: 6vmin;
|
|
margin-bottom: 0.6em; /* fallback */
|
|
margin-bottom: 6vmin;
|
|
text-shadow: 0.1em 0..1em 0 #fe7ac6; /* fallback */
|
|
text-shadow: 1vmin 1vmin 0 #fe7ac6; /* x y blur-radius colour */
|
|
}
|
|
|
|
ul {
|
|
float: left;
|
|
clear: both;
|
|
list-style-type: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
li {
|
|
color: white;
|
|
font-size: 0.8em; /* fallback */
|
|
font-size: 8vmin;
|
|
padding: 0.1em; /* fallback */
|
|
padding: 1vmin;
|
|
padding-top: 0.05em; /* fallback */
|
|
padding-top: 0.5vmin;
|
|
padding-bottom: 0.15em; /* fallback */
|
|
padding-bottom: 1.5vmin;
|
|
text-align: center;
|
|
vertical-align: middle;
|
|
float: left;
|
|
height: 1em; /* fallback */
|
|
height: 10vmin;
|
|
width: 1em; /* fallback */
|
|
width: 10vmin;
|
|
background-color: #454e52;
|
|
border-radius: 0.2em; /* fallback */
|
|
border-radius: 2vmin;
|
|
cursor: default;
|
|
}
|
|
|
|
li.revealed {
|
|
background-color: #1b1c17;
|
|
}
|
|
|
|
li:not(.revealed):hover {
|
|
background-color: #a0a9af;
|
|
}
|
|
|
|
li.flagged {
|
|
background-color: #b5fe52;
|
|
background-image: url("images/flag.png");
|
|
background-size: 100% 100%;
|
|
}
|
|
|
|
li.flagged:hover {
|
|
background-color: #c6fe7a;
|
|
}
|
|
|
|
li.mine.revealed {
|
|
background-color: #d23000;
|
|
background-image: url("images/skull.png");
|
|
background-size: 100% 100%;
|
|
}
|
|
|
|
li.mines1 {
|
|
color: #c6fe7a;
|
|
}
|
|
|
|
li.mines2 {
|
|
color: #7ac5fe;
|
|
}
|
|
|
|
li.mines3 {
|
|
color: #fe7ac6;
|
|
}
|
|
|
|
li.mines4 {
|
|
color: #b17afe;
|
|
}
|
|
|
|
li.mines5 {
|
|
color: #feb27a;
|
|
}
|
|
|
|
li.mines6 {
|
|
color: #7afeb2;
|
|
}
|
|
|
|
li.mines7 {
|
|
color: #d74600;
|
|
}
|
|
|
|
li.mines8 {
|
|
color: #8c4600;
|
|
}
|
|
|
|
p {
|
|
color: #fff;
|
|
font-size: 0.43em; /* fallback */
|
|
font-size: 4.3vmin;
|
|
padding: 0 1em; /* fallback */
|
|
padding: 0 10vmin;
|
|
}
|
|
|
|
strong {
|
|
color: #fe7ac6;
|
|
}
|
|
</style>
|
|
<script src="jquery-2.1.3.min.js"></script>
|
|
<script>
|
|
var gameBoardWidth = 10;
|
|
var gameBoardHeight = 9;
|
|
var score = 0;
|
|
var firstClick = true;
|
|
var mineChance = 0.2;
|
|
var clickholdMs = 200;
|
|
var timeout; //hold timer
|
|
var mouseHeld = false;
|
|
var viewportSizingAvailable = ($('#game').height == $(window).height()); // only run once
|
|
|
|
$(document).ready(function() {
|
|
function drawGameBoard() {
|
|
$('#game').html("");
|
|
|
|
//determine aspect ratio so as to fit the screen
|
|
gameBoardHeight = Math.floor((1 / getAspectRatio()) * 10) - 1;
|
|
|
|
if (gameBoardHeight <= 9) {
|
|
gameBoardHeight = 9;
|
|
}
|
|
|
|
for (var i = 0; i < gameBoardHeight; i++) {
|
|
$('#game').append(newRow());
|
|
}
|
|
}
|
|
|
|
function newTile() {
|
|
if (Math.random() < mineChance) {
|
|
return '<li class="mine"></li>';
|
|
} else {
|
|
return '<li></li>';
|
|
}
|
|
}
|
|
|
|
function newRow() {
|
|
var row = '<ul>';
|
|
|
|
for (var i = 0; i < gameBoardWidth; i++) {
|
|
row += newTile();
|
|
};
|
|
|
|
row += '</ul>';
|
|
|
|
return row;
|
|
}
|
|
|
|
function saveGame() {
|
|
if (typeof(Storage) == "undefined") {
|
|
return;
|
|
}
|
|
|
|
//variables
|
|
localStorage.setItem("score", score);
|
|
localStorage.setItem("mineChance", mineChance);
|
|
localStorage.setItem("firstClick", firstClick);
|
|
|
|
//game board
|
|
localStorage.setItem("gameBoard", $('#game').html());
|
|
}
|
|
|
|
function loadGame() {
|
|
//check if storage available and if saved game exists
|
|
if (typeof(Storage) == "undefined" || localStorage.getItem("gameBoard") == null) {
|
|
drawGameBoard();
|
|
return;
|
|
}
|
|
|
|
//variables
|
|
score = parseInt(localStorage.getItem("score"));
|
|
mineChance = parseFloat(localStorage.getItem("mineChance"));
|
|
firstClick = (localStorage.getItem("firstClick") == "true");
|
|
|
|
//game board
|
|
$('#game').html(localStorage.getItem("gameBoard"));
|
|
$('#setup').hide();
|
|
}
|
|
|
|
$.fn.check = function() {
|
|
//unclicked tiles
|
|
if ($(this).filter('li:not(.revealed):not(.flagged)').length > 0) {
|
|
return false;
|
|
}
|
|
|
|
//incorrectly flagged tiles
|
|
if ($(this).filter('li.flagged:not(.mine)').length > 0) {
|
|
return false;
|
|
}
|
|
|
|
//clicked mines
|
|
if ($(this).filter('li.revealed.mine').length > 0) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
$.fn.checkRow = function() {
|
|
return $(this).children().check();
|
|
}
|
|
|
|
$.fn.checkColumn = function() {
|
|
return $(this).column().check();
|
|
}
|
|
|
|
window.removeClearedRows = function() {
|
|
var rowsToRemove = $('#game ul:not(.removing)').filter(function() {
|
|
return $(this).checkRow();
|
|
});
|
|
|
|
if (rowsToRemove.length > 0) {
|
|
suddenDeath();
|
|
}
|
|
|
|
rowsToRemove.each(function() {
|
|
score += $(this).children('.mine').length;
|
|
|
|
$(this).addClass("removing");
|
|
|
|
$(this).slideUp("slow", function() {
|
|
$(this).remove();
|
|
|
|
//add new row on bottom
|
|
$('#game').append(newRow());
|
|
|
|
refreshMineCounts();
|
|
|
|
//click blank tiles
|
|
$('li.revealed:not(.mine):empty').mouseup();
|
|
});
|
|
});
|
|
}
|
|
|
|
window.removeClearedColumns = function() {
|
|
var columnsToRemove = $('ul:not(.removing):eq(0) li:not(.removing)').filter(function() {
|
|
return $(this).checkColumn();
|
|
});
|
|
|
|
if (columnsToRemove.length > 0) {
|
|
suddenDeath();
|
|
}
|
|
|
|
columnsToRemove.each(function() {
|
|
score += $(this).column().filter('.mine').length;
|
|
|
|
$(this).column().addClass("removing");
|
|
|
|
//animation for top row + deletion of column
|
|
$(this).animate({width: 0, borderRadius: 0, padding: 0}, "slow", function() {
|
|
$(this).column().remove();
|
|
$('ul').each(function() {
|
|
$(this).append(newTile());
|
|
});
|
|
|
|
refreshMineCounts();
|
|
|
|
//click blank tiles
|
|
$('li.revealed:not(.mine, .removing):empty').mouseup();
|
|
});
|
|
|
|
//then just animation for others
|
|
$(this).column().animate({width: 0, borderRadius: 0, padding: 0}, "slow");
|
|
});
|
|
}
|
|
|
|
function refreshMineCounts() {
|
|
$('ul:not(.removing) li.revealed:not(.mine, .removing)').each(function() {
|
|
var mineCount = $(this).countMinesText();
|
|
|
|
$(this).text(mineCount);
|
|
|
|
//remove "mines1" etc
|
|
$(this).attr(
|
|
'class',
|
|
$(this).attr('class').replace(
|
|
/mines[0-9]/, "mines" + mineCount
|
|
)
|
|
);
|
|
|
|
$(this).removeClass("mines mines0");
|
|
});
|
|
}
|
|
|
|
function updateScore() {
|
|
$('#score').text("Score: " + score);
|
|
}
|
|
|
|
function isGameOver() {
|
|
return $('ul').has('.mine.revealed').length == gameBoardHeight
|
|
&& $('ul').first().children().filter(function() {
|
|
return $(this).column().filter('.mine.revealed').length > 0;
|
|
}).length == gameBoardWidth;
|
|
}
|
|
|
|
function checkGameOver() {
|
|
if (isGameOver()) {
|
|
$('#gameOver').show();
|
|
}
|
|
}
|
|
|
|
function updateMinesLeft() {
|
|
//unflagged mines - revealed mines - flagged not-mines
|
|
$('#mines').text(
|
|
"Mines left: "
|
|
+ ($('.mine:not(.flagged)').length
|
|
- $('.mine.revealed').length
|
|
- $('li:not(.mine).flagged').length)
|
|
);
|
|
}
|
|
|
|
function getAspectRatio() {
|
|
return $(window).width() / $(window).height();
|
|
}
|
|
|
|
function resizeToWindow() {
|
|
if (!viewportSizingAvailable) {
|
|
$('html').css('font-size', Math.min($(window).width(), $(window).height()) / 10);
|
|
}
|
|
}
|
|
|
|
function isPortrait() {
|
|
return getAspectRatio() > 1;
|
|
}
|
|
|
|
$.fn.updateMineCount = function() {
|
|
$(this).text(
|
|
$(this).countMinesText
|
|
);
|
|
}
|
|
|
|
$.fn.rowScore = function() {
|
|
return $(this).children('.mine').length;
|
|
}
|
|
|
|
$.fn.rowAbove = function() {
|
|
return $(this).parent('ul').prev();
|
|
}
|
|
|
|
$.fn.rowBelow = function() {
|
|
return $(this).parent('ul').next();
|
|
}
|
|
|
|
$.fn.column = function() {
|
|
var x = $(this).getX();
|
|
|
|
var column = $('');
|
|
|
|
$('ul').each(function() {
|
|
column = column.add($(this).children().eq(x));
|
|
});
|
|
|
|
return column;
|
|
}
|
|
|
|
window.oneColumnLeft = function() {
|
|
return $('ul').first().children().filter(function() {
|
|
return $(this).column().filter('.mine:not(.revealed, .flagged)').length == 0;
|
|
}).length >= (gameBoardWidth - 1)
|
|
}
|
|
|
|
window.oneRowLeft = function() {
|
|
return $('ul').filter(function() {
|
|
return $(this).children('.mine:not(.revealed, .flagged)').length == 0;
|
|
}).length >= (gameBoardHeight - 1);
|
|
}
|
|
|
|
window.isSuddenDeath = function() {
|
|
return oneRowLeft() && oneColumnLeft();
|
|
}
|
|
|
|
window.suddenDeath = function() {
|
|
if (isSuddenDeath()) {
|
|
mineChance += 0.01;
|
|
|
|
//don't want the chance to get to 100% because that's completely predictable
|
|
if (mineChance > 0.8) {
|
|
mineChance = 0.8;
|
|
}
|
|
}
|
|
}
|
|
|
|
$.fn.getX = function() {
|
|
return $(this).index();
|
|
}
|
|
|
|
$.fn.getY = function() {
|
|
return $(this).parent('ul').index();
|
|
}
|
|
|
|
$.fn.isMine = function() {
|
|
return $(this).hasClass("mine");
|
|
}
|
|
|
|
$.fn.countMinesAdjacent = function() {
|
|
return $(this).getAdjacentTiles().filter('.mine').length;
|
|
}
|
|
|
|
$.fn.getAdjacentTiles = function() {
|
|
var adjacentTiles = $('');
|
|
var x = $(this).getX();
|
|
var y = $(this).getY();
|
|
|
|
if (y > 0) {
|
|
var tileAbove = $(this).rowAbove().children().eq(x);
|
|
|
|
adjacentTiles = adjacentTiles.add(tileAbove.prev());
|
|
adjacentTiles = adjacentTiles.add(tileAbove );
|
|
adjacentTiles = adjacentTiles.add(tileAbove.next());
|
|
}
|
|
|
|
adjacentTiles = adjacentTiles.add($(this).prev());
|
|
adjacentTiles = adjacentTiles.add($(this).next());
|
|
|
|
if (y < (gameBoardHeight - 1)) {
|
|
var tileBelow = $(this).rowBelow().children().eq(x);
|
|
|
|
adjacentTiles = adjacentTiles.add(tileBelow.prev());
|
|
adjacentTiles = adjacentTiles.add(tileBelow );
|
|
adjacentTiles = adjacentTiles.add(tileBelow.next());
|
|
}
|
|
|
|
return adjacentTiles;
|
|
}
|
|
|
|
$.fn.countMinesText = function() {
|
|
return $(this).countMinesAdjacent().toString().replace("0", "");
|
|
}
|
|
|
|
$('input[type="radio"]').on("change", function() {
|
|
switch ($(this).val()) {
|
|
case "easy":
|
|
mineChance = 0.13;
|
|
break;
|
|
case "normal":
|
|
mineChance = 0.2;
|
|
break;
|
|
case "hard":
|
|
mineChance = 0.285;
|
|
break;
|
|
}
|
|
});
|
|
|
|
$('#gameOver button').on("click", function() {
|
|
drawGameBoard();
|
|
|
|
$('#gameOver').hide();
|
|
$('button.cancel').hide();
|
|
$('button.start').removeAttr('style');
|
|
$('#setup').show();
|
|
});
|
|
|
|
$('button.reset').on("click", function() {
|
|
//prompt user with setup screen
|
|
$('#setup').show();
|
|
$('button.cancel').show();
|
|
$('button.start').css('left', '20vmin');
|
|
});
|
|
|
|
$('button.cancel').on("click", function() {
|
|
//prompt user with setup screen
|
|
$('#setup').hide();
|
|
$('button.cancel').hide();
|
|
$('button.start').removeAttr('style');
|
|
});
|
|
|
|
$('button.start').on("click", function() {
|
|
drawGameBoard();
|
|
|
|
//reset stats
|
|
firstClick = true;
|
|
|
|
//reset difficulty
|
|
$('input:checked').change();
|
|
|
|
score = 0;
|
|
|
|
updateScore();
|
|
updateMinesLeft();
|
|
|
|
$('#setup').hide();
|
|
});
|
|
|
|
$.fn.leftClick = function(automated) {
|
|
if (!automated) automated = false;
|
|
|
|
//don't want first click to be a mine
|
|
if (firstClick) {
|
|
var x = $(this).getX();
|
|
x = (x >= 1) ? x : 1;
|
|
x = (x <= gameBoardWidth - 2) ? x : gameBoardWidth - 2;
|
|
|
|
var y = $(this).getY();
|
|
y = (y >= 1) ? y : 1;
|
|
y = (y <= gameBoardHeight - 2) ? y : gameBoardHeight - 2;
|
|
|
|
$('ul').eq(y - 1).children().slice(x - 1).filter(':lt(3)').removeClass("mine");
|
|
$('ul').eq(y ).children().slice(x - 1).filter(':lt(3)').removeClass("mine");
|
|
$('ul').eq(y + 1).children().slice(x - 1).filter(':lt(3)').removeClass("mine");
|
|
|
|
firstClick = false;
|
|
}
|
|
|
|
if ($(this).hasClass("flagged")) {
|
|
return;
|
|
}
|
|
|
|
if ($(this).isMine()) {
|
|
$(this).addClass("revealed");
|
|
} else if (!automated && parseInt($(this).text()) === $(this).getAdjacentTiles().filter('.flagged, .revealed.mine').length) {
|
|
//already clicked; use middle click reveal functionality
|
|
|
|
//number of flags matches number of adjacent mines
|
|
$(this).getAdjacentTiles().filter(':not(.flagged, .revealed)').mouseup();
|
|
} else {
|
|
$(this).addClass("revealed");
|
|
|
|
$(this).updateMineCount();
|
|
|
|
$(this).addClass("mines" + $(this).countMinesAdjacent());
|
|
|
|
//if no mines adjacent, cascade!
|
|
if ($(this).countMinesAdjacent() == 0) {
|
|
$(this).getAdjacentTiles().filter(':not(.revealed)').mouseup();
|
|
}
|
|
}
|
|
|
|
firstClick = false;
|
|
}
|
|
|
|
$.fn.middleClick = function() {
|
|
//number of flags matches number of adjacent mines
|
|
if (parseInt($(this).text()) === $(this).getAdjacentTiles().filter('.flagged, .revealed.mine').length) {
|
|
$(this).getAdjacentTiles().filter(':not(.flagged, .revealed)').mouseup();
|
|
}
|
|
}
|
|
|
|
$.fn.rightClick = function() {
|
|
if (!$(this).hasClass("revealed")) {
|
|
$(this).toggleClass("flagged");
|
|
}
|
|
|
|
clearTimeout(timeout);
|
|
}
|
|
|
|
$(document).on("contextmenu", "body", function(event) {
|
|
event.preventDefault();
|
|
});
|
|
|
|
|
|
$(document).on("mousedown touchstart", "li", function(event) {
|
|
var x = $(this).getX();
|
|
var y = $(this).getY();
|
|
|
|
timeout = setTimeout(function() {
|
|
$('ul:eq(' + y + ') li:eq(' + x + ')').rightClick();
|
|
|
|
mouseHeld = true;
|
|
}, clickholdMs);
|
|
});
|
|
|
|
$(document).on("mouseleave", "li", function(event) {
|
|
clearTimeout(timeout);
|
|
});
|
|
|
|
$(document).on("mouseup touchend", "li", function(event) {
|
|
event.preventDefault();
|
|
|
|
clearTimeout(timeout);
|
|
|
|
if (mouseHeld) {
|
|
mouseHeld = false;
|
|
|
|
//rightClick has already been called in a callback, so nothing to do here
|
|
} else {
|
|
switch (event.which) {
|
|
case 3:
|
|
$(this).rightClick();
|
|
break;
|
|
case 2:
|
|
$(this).middleClick();
|
|
break;
|
|
case 1:
|
|
$(this).leftClick();
|
|
break;
|
|
default:
|
|
$(this).leftClick(true); //automated
|
|
break;
|
|
}
|
|
}
|
|
|
|
removeClearedRows();
|
|
removeClearedColumns();
|
|
checkGameOver();
|
|
|
|
updateScore();
|
|
updateMinesLeft();
|
|
saveGame();
|
|
});
|
|
|
|
$(window).resize(function() {
|
|
resizeToWindow();
|
|
});
|
|
|
|
resizeToWindow();
|
|
|
|
//instantiate the game
|
|
loadGame(); //loadGame will draw the game board if no saved game is found
|
|
|
|
$('#gameOver').hide();
|
|
$('button.cancel').hide();
|
|
});
|
|
</script>
|
|
<script>
|
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
|
|
|
ga('create', 'UA-60523398-1', 'auto');
|
|
ga('send', 'pageview');
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div id="stats">
|
|
<div id="score">Score: 0</div>
|
|
<div id="mines">Mines left: 0</div>
|
|
<button class="reset">reset</button>
|
|
</div>
|
|
<div id="game"></div>
|
|
<div id="gameOver">
|
|
<h1>game over</h1>
|
|
<p>a game by max bradbury</p>
|
|
<p>inspirations include minesweeper, tetris and 2048</p>
|
|
<p>tell your friends</p>
|
|
<button>reset</button>
|
|
</div>
|
|
<div id="setup">
|
|
<h1>endless mines</h1>
|
|
|
|
<p>
|
|
<strong>left click</strong> or <strong>tap</strong> to clear a tile. <br>
|
|
<strong>right click</strong> or <strong>hold</strong> to flag a mine. <br>
|
|
rows and columns with <strong>exploded mines</strong> cannot be cleared.
|
|
</p>
|
|
|
|
<h2>Difficulty</h2>
|
|
|
|
<div class="centre">
|
|
<input type="radio" name="difficulty" id="difficultyEasy" value="easy">
|
|
<label for="difficultyEasy">Easy</label>
|
|
<input type="radio" name="difficulty" id="difficultyNormal" value="normal" checked>
|
|
<label for="difficultyNormal">Normal</label>
|
|
<input type="radio" name="difficulty" id="difficultyHard" value="hard">
|
|
<label for="difficultyHard">Hard</label>
|
|
</div>
|
|
|
|
<div class="centre">
|
|
<button class="start">start</button>
|
|
<button class="cancel">cancel</button>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html> |