Skip to content

Instantly share code, notes, and snippets.

@skeeto
Created November 4, 2012 03:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skeeto/4010068 to your computer and use it in GitHub Desktop.
Save skeeto/4010068 to your computer and use it in GitHub Desktop.
Minesweeper Game
function Minefield(width, height, mines) {
this.width = width;
this.height = height;
this.grid = Minefield.make2dArray(width, height, 0);
this.seen = Minefield.make2dArray(width, height, false);
this.marked = Minefield.make2dArray(width, height, false);
var rand = function(n) {
return Math.floor(Math.random() * n);
};
while(mines > 0) {
if (this.placeMine(rand(width), rand(height))) mines--;
}
}
Minefield.MINE = "*";
Minefield.make2dArray = function(width, height, init) {
var a = new Array(width);
for (var x = 0; x < width; x++) {
a[x] = [];
for (var y = 0; y < height; y++) {
a[x][y] = init;
}
}
return a;
};
Minefield.prototype.isInBounds = function(x, y) {
return x >= 0 && x < this.width && y >= 0 && y < this.height;
};
Minefield.prototype.isMine = function(x, y) {
return this.grid[x][y] === Minefield.MINE;
};
Minefield.prototype.placeMine = function(x, y) {
if (!this.isMine(x, y)) {
this.grid[x][y] = Minefield.MINE;
for (var yy = y - 1; yy <= y + 1; yy++) {
for (var xx = x - 1; xx <= x + 1; xx++) {
if (this.isInBounds(xx, yy) &&
typeof this.grid[xx][yy] === "number") {
this.grid[xx][yy]++;
}
}
}
return true;
}
return false;
};
Minefield.prototype.toString = function() {
var build = [];
for (var y = 0; y < this.height; y++) {
for (var x = 0; x < this.width; x++) {
build.push(this.grid[x][y]);
}
build.push("\n");
}
build.pop();
return build.join('');
};
Minefield.prototype.draw = function(ctx) {
var w = ctx.canvas.width, h = ctx.canvas.height;
var sx = w / this.width, sy = h / this.height;
ctx.strokeStyle = "black";
ctx.font = (sx / 1.75) + "px sans";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (var y = 0; y < this.height; y++) {
for (var x = 0; x < this.width; x++) {
if (this.marked[x][y]) {
ctx.fillStyle = "yellow";
} else if (this.seen[x][y]) {
ctx.fillStyle = "lightgray";
} else {
ctx.fillStyle = "gray";
}
ctx.fillRect(x * sx, y * sy, sx, sy);
ctx.strokeRect(x * sx, y * sy, sx, sy);
if (this.seen[x][y] && this.grid[x][y] !== 0) {
ctx.fillStyle = "black";
ctx.fillText(this.grid[x][y],
(x + 0.5) * sx, (y + 0.5) * sy + sy / 20);
}
}
}
};
Minefield.prototype.probe = function(x, y) {
if (this.isInBounds(x, y) && !this.marked[x][y] && !this.seen[x][y]) {
this.seen[x][y] = true;
if (this.grid[x][y] === 0) {
this.probeAround(x, y);
}
}
};
Minefield.prototype.probeAround = function(x, y) {
for (var yy = y - 1; yy <= y + 1; yy++) {
for (var xx = x - 1; xx <= x + 1; xx++) {
this.probe(xx, yy);
}
}
};
Minefield.prototype.mark = function(x, y) {
if (this.isInBounds(x, y)) {
this.marked[x][y] = !this.marked[x][y] && !this.seen[x][y];
}
};
Minefield.prototype.makeListener = function(ctx) {
var that = this;
return function(e) {
var w = ctx.canvas.width, h = ctx.canvas.height;
var sx = w / that.width, sy = h / that.height;
var x = Math.floor((e.offsetX || e.clientX) / sx);
var y = Math.floor((e.offsetY || e.clientY) / sy);
if (e.ctrlKey) {
that.mark(x, y);
} else if (e.button === 0) { // left
that.probe(x, y);
} else if (e.button === 1) { // center
that.probeAround(x, y);
}
that.draw(ctx);
};
};
$('document').ready(function() {
var ctx = $('#canvas').get(0).getContext("2d");
var mf = new Minefield(16, 16, 40);
mf.draw(ctx);
ctx.canvas.addEventListener('click', mf.makeListener(ctx));
$('#canvas').css("positon: float;");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment