Minesweeper Implementation using P5.js
Originally Written on:- 14th January, 2019
Img Source:- Wikipedia |
P5.js
p5.js is
a JavaScript library that starts with the original goal of Processing—to make
coding accessible for artists, designers, educators, and beginners—and
reinterprets this for today's web.
Using the
original metaphor of a software sketchbook, p5.js has a full set of drawing
functionality. However, you're not limited to your drawing canvas, you can
think of your whole browser page as your sketch! For this, p5.js has addon
libraries that make it easy to interact with other HTML5 objects, including
text, input, video, webcam, and sound.
Please see the page
for instructions for setting up your editing environment and project.
Full
source code is in my Github
Getting
into the implementation
We want
to build a game using the P5.js library to make the famous game :
minesweeper. Now, it has been a long time since I have played minesweeper but I
think I remember how it works. Minesweeper is a single-player puzzle video
game. The objective of the game is to clear a rectangular board containing
hidden "mines" or bombs without detonating any of them, with help
from clues about the number of neighbouring mines in each field. The game
originates from the 1960s, and has been written for many computing platforms in
use today. The player is initially presented with a grid of undifferentiated
squares. Some randomly selected squares, unknown to the player, are designated
to contain mines.
We want
to create a grid in this case and we want to make sure that we keep a few
things in mind.
|
||||
1) Cell
state
2) We also need to see that whether a mine
is in a cell or not
3) Coordinates that represent the cell:- x,
y, w, h.
4) We also need to find out whether the cell
is revealed or not.
In
the game itself, we are going to click on a cell. When we click on a
cell, it will either be a number, or have a bunch of neighboring cells
with no mine. Or we, can click on a cell and find a mine in it, in that case
the game will be over.
Therefore,
it is either going to be a mine, a number or a number and a bunch of empty
cells.
Create
two windows:- cell.js and sketch.js. Cell.js will be used as separate
JavaScript file. There are too many functions and just to access the two in
your html file add cell.js .
We need
to store the cells in a data structure. We can make a 2D array for that-> to
store the rows and the columns . Another important thing to note here is that
each of the cells in the grid has a pixel size of 10x10. We can create a 2D
array and it creates the whole array for us and then we can just return it. So
under sketch.js
function make2DArray(cols, rows) {
var arr = new Array(cols);
for (var i = 0; i < arr.length; i++) {
arr[i] = new Array(rows);
}
return arr;
}
Next, in
sketch.js we need to make the Game board.
function setup() {
createCanvas(401, 401);
cols = floor(width / w);
rows = floor(height / w);
grid = make2DArray(cols, rows);
for (var i = 0; i < cols; i++) {
for (var j = 0; j < rows; j++) {
grid[i][j] = new Cell(i, j, w);
}
}
In the
above piece of code, w is a global variable through
which we can control the size of the pixel value. That is why for the rows and
the columns, we divide it by the width and height. We use floor, so that we get
round numbers. Suppose if the grid is 400 x 400 . Then we will have 40 rows x
40 columns.
Attach
functions to a prototype: here it is show. We need to attach the functions to
the prototype. We have to use constructor function to create every object and
every object will have a set of methods. Therefore, in cell.js
Cell.prototype.show = function() {
stroke(0);
noFill();
rect(this.x, this.y, this.w, this.w);
if (this.revealed) {
if (this.bee) {
fill(127);
ellipse(this.x + this.w * 0.5, this.y +
this.w * 0.5, this.w * 0.5);
} else {
fill(200);
rect(this.x, this.y, this.w, this.w);
if (this.neighborCount > 0) {
textAlign(CENTER);
fill(0);
text(this.neighborCount,
this.x + this.w * 0.5, this.y + this.w - 6);
We need
to make the mines visible. In this case, we are considering the mines as bees.
We are filling the unnecessary cells and moving the pixels back and forth to
fill up the blank neighboring cells. We have also tried to fit the mines in the
middle of the cell
Next up,
we are also counting the number of neighbors, so as to avoid looking into those
that are either already revealed, yet to be revealed or have mines in them. For
this reason, we are going to use the floodfill algorithm Here . Code after the previous
snippet:
Cell.prototype.countBees = function() {
if (this.bee) {
this.neighborCount = -1;
return;
}
var total = 0;
for (var xoff = -1; xoff <= 1; xoff++) {
var i = this.i + xoff;
if (i < 0 || i >= cols) continue;
for (var yoff = -1; yoff <= 1; yoff++) {
var j = this.j + yoff;
if (j < 0 || j >= rows) continue;
var neighbor = grid[i][j];
if (neighbor.bee) {
total++;
}
}
}
this.neighborCount = total;
}Cell.prototype.contains = function(x, y) {
return (x > this.x && x < this.x + this.w
&& y > this.y && y < this.y + this.w);
}
Cell.prototype.reveal = function() {
this.revealed = true;
if (this.neighborCount == 0) {
// flood fill time
this.floodFill();
}
}Cell.prototype.floodFill = function() {
for (var xoff = -1; xoff <= 1; xoff++) {
var i = this.i + xoff;
if (i < 0 || i >= cols) continue;
for (var yoff = -1; yoff <= 1; yoff++) {
var j = this.j + yoff;
if (j < 0 || j >= rows) continue;
var neighbor = grid[i][j];
// Note the neighbor.bee check was not
required
if (!neighbor.revealed) {
neighbor.reveal();
}
}
}
}
We also
want to know how many mines are neighbouring the cells. We use Xoffset
and Yoffset. After we create the neighbours, we want to check all of it. We
count the neighbours, but we do not wank to count ourselves. We need to take
care of the edges as well. After we are done, we need to delete that
spot, so that it no longer is an option.
After
adding a few other P5.js for interactivity, we would be done. For more
information on this game watch the video by Daniel Shiffman here.
My
Results
Credits
Go to Daniel Shiffman. I followed his tutorial and used his code.
Comments
Post a Comment