In object-oriented programming (OOP), maximizing API use streamlines development, leading to simpler and more concise code. This clarity not only improves readability but also eases debugging. Leveraging an API effectively in OOP thus ensures a blend of simplicity, efficiency and maintainability in software development.
This demo (partially) implements the minesweeper video game using the p5.quadrille.js API to instantiate and handle two quadrilles: a board
and a mask
. The former embodies the game board, while the latter covers it. As gameplay progresses clicking on mask
cells uncovers the underlying board
.
(mouse click to play; press any key to init)
code
let board, mask;
let size = 20;
let n = size * 2;
function init() {
board = createQuadrille(size, size, n, '๐ฃ');
mask = board.clone();
visitQuadrille(board,
(row, col) => {
if (board.isEmpty(row, col)) {
let order = board.ring(row, col).order;
if (order) {
mask.fill(row, col, order.toString());
}
}
}
);
board = mask.clone();
mask.replace(color('red')).fill(color('green'));
}
function setup() {
Quadrille.cellLength = 400 / size;
createCanvas(400, 400);
init();
// suppress right-click context menu
document.oncontextmenu = () => false;
}
function draw() {
background('moccasin');
drawQuadrille(board);
drawQuadrille(mask.clone().replace(color('magenta')), {outline: (color('lime'))});
}
function mouseClicked() {
const row = board.mouseRow;
const col = board.mouseCol;
if (board.read(row, col) === '๐ฃ') {
mask = createQuadrille(size, size);
return;
}
board.isFilled(row, col) ? mask.clear(row, col) : mask.clear(row, col, true);
}
function keyPressed() {
init();
}
Init
The init
function initializes both the board
and its covering mask
:
let board, mask;
let size = 20;
let n = size * 2;
function init() {
// 1. Board instantiation
board = createQuadrille(size, size, n, '๐ฃ');
// 2. Mask instantiation
mask = board.clone();
// 3. The number of neighboring mines is determined
// on the board visited cells using the ring method
// with its order saved in the respective mask cell
visitQuadrille(board,
(row, col) => {
if (board.isEmpty(row, col)) {
let order = board.ring(row, col).order;
if (order) {
mask.fill(row, col, order.toString());
}
}
}
);
// 4. The mask is cloned into the board
board = mask.clone();
// 5. The mask filled cells are colored in red
// and the remaining ones in green
mask.replace(color('red')).fill(color('green'));
}
Upon creation, the board
and mask
should appear as follows:
(mouse click or press any key to toggle the mask drawing)
API references
- createQuadrille(width, height, order, pattern).
- clone().
- visitQuadrille(quadrille, function).
- ring(row, col).
- order.
- replace(pattern).
- fill(pattern).
Drawing
To uniformly color mask-filled cells as magenta
the clone
and the replace
quadrille methods are chained within the drawQuadrille p5.js function:
function draw() {
background('moccasin');
// 1. Draw board
drawQuadrille(board);
// 2. Color mask-filled cells in magenta
drawQuadrille(mask.clone().replace(color('magenta')), {outline: (color('lime'))});
}
API references
Interaction
The game interaction uses mouse clicks to clear single cells or multiple cells through flood fill.
function mouseClicked() {
// 1. Convert mouse screen position to quadrille row col coords
const row = board.mouseRow;
const col = board.mouseCol;
// 2. Game over when mine explodes thus revealing board
if (board.read(row, col) === '๐ฃ') {
mask = createQuadrille(size, size);
return;
}
// 3. Otherwise clear single or multiple cells
board.isFilled(row, col) ? mask.clear(row, col) : mask.clear(row, col, true);
}
API references
References
- Minesweeper wikipedia article.
- Coding train minesweeper coding challenge tutorial: