Learn RxJS
Search…
Mine Sweeper Game
By adamlubek
This recipe demonstrates RxJS implementation of Mine Sweeper Game.

Example Code

Could not load image
Mine Sweeper

index.ts

1
// RxJS v6+
2
import { fromEvent, of } from 'rxjs';
3
import {
4
map,
5
tap,
6
filter,
7
pluck,
8
switchMap,
9
takeWhile,
10
finalize
11
} from 'rxjs/operators';
12
import { renderMinefield, renderScore, renderGameOver } from './html-renderer';
13
import { size, mine } from './constants';
14
import { addMines, addMarks } from './mines';
15
16
const mines$ = of(
17
Array(size)
18
.fill(0)
19
.map(e => Array(size).fill(0))
20
).pipe(map(addMines), map(addMarks), tap(renderMinefield));
21
22
const click$ = mines =>
23
fromEvent(document, 'click').pipe(
24
map(({ clientX, clientY }: MouseEvent) =>
25
document.elementFromPoint(clientX, clientY)
26
),
27
filter(elem => elem.id !== ''),
28
tap(elem =>
29
(val => (
30
renderScore(val === mine || elem.innerHTML !== '_' ? 0 : val),
31
(elem.innerHTML = val)
32
))(mines[elem.id[0]][elem.id[1]])
33
),
34
pluck('id'),
35
takeWhile(([x, y]) => mines[x][y] !== mine),
36
finalize(renderGameOver)
37
);
38
39
mines$.pipe(switchMap(click$)).subscribe();
Copied!

mines.ts

1
import { size, mine } from './constants';
2
3
const randomNumber = () => Math.floor(Math.random() * Math.floor(size));
4
5
export const addMines = arr => {
6
for (let i = 0; i < size / 2; i++) {
7
arr[randomNumber()][randomNumber()] = mine;
8
}
9
10
return arr;
11
};
12
13
const mark = (arr, x, y) =>
14
arr[x] !== undefined && arr[x][y] !== undefined
15
? (arr[x][y] += arr[x][y] === mine ? 0 : 1)
16
: () => {};
17
18
export const addMarks = arr => {
19
for (let ri = 0; ri < size; ri++) {
20
for (let ci = 0; ci < size; ci++) {
21
if (arr[ri][ci] === mine) {
22
mark(arr, ri - 1, ci + 1);
23
mark(arr, ri - 1, ci);
24
mark(arr, ri - 1, ci - 1);
25
mark(arr, ri, ci + 1);
26
mark(arr, ri, ci - 1);
27
mark(arr, ri + 1, ci + 1);
28
mark(arr, ri + 1, ci);
29
mark(arr, ri + 1, ci - 1);
30
}
31
}
32
}
33
return arr;
34
};
Copied!

constants.ts

1
export const mine = 9;
2
export const size = 10;
Copied!

html-renderer.ts

1
export const renderMinefield = arr =>
2
arr.forEach((r, ri) =>
3
(elem =>
4
r.forEach(
5
(c, ci) =>
6
(col => (
7
(col.innerText = '_'),
8
(col.id = `${ri}${ci}`),
9
elem.appendChild(document.createTextNode('\u00A0\u00A0')),
10
elem.appendChild(col)
11
))(document.createElement('span')),
12
document.body.appendChild(elem)
13
))(document.createElement('div'))
14
);
15
16
export const renderScore = val =>
17
(scoreElem => (scoreElem.innerText = parseInt(scoreElem.innerText) + val))(
18
document.getElementById('score')
19
);
20
21
export const renderGameOver = () =>
22
(document.body.innerHTML += '<br/>GAME OVER');
23
24
const addElem = decorator =>
25
(elem => (decorator(elem), document.body.appendChild(elem)))(
26
document.createElement('span')
27
);
28
29
addElem(elem => (elem.innerText = 'Score: '));
30
addElem(elem => ((elem.id = 'score'), (elem.innerText = '0')));
Copied!

Operators Used

Last modified 1yr ago