-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathminesweeper.js
127 lines (109 loc) · 2.95 KB
/
minesweeper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
export const TILE_STATUS = {
HIDDEN: 'hidden',
MINE: 'mine',
NUMBER: 'number',
FLAGGED: 'flagged',
}
export function createBoard(boardSize, numberOfMines) {
const board = []
const minePositions = getMinePositions(boardSize, numberOfMines)
for (let x = 0; x < boardSize; x++) {
const row = []
for (let y = 0; y < boardSize; y++) {
const element = document.createElement('div')
element.dataset.status = TILE_STATUS.HIDDEN
const tile = {
element,
x,
y,
mine: minePositions.some((value) => isEqual(value, { x, y })),
get status() {
return this.element.dataset.status
},
set status(value) {
this.element.dataset.status = value
},
}
row.push(tile)
}
board.push(row)
}
return board
}
export function revealTile(board, tile) {
if (tile.status !== TILE_STATUS.HIDDEN) return
if (tile.mine) {
tile.status = TILE_STATUS.MINE
return
}
tile.status = TILE_STATUS.NUMBER
const adjacentTiles = nearbyTiles(board, tile)
const mines = adjacentTiles.filter((t) => t.mine)
if (mines.length === 0) {
adjacentTiles.forEach((tile) => revealTile(board, tile))
} else {
tile.element.textContent = mines.length
}
}
export function flagTile(tile) {
if (
tile.status !== TILE_STATUS.FLAGGED &&
tile.status !== TILE_STATUS.HIDDEN
) {
return
}
const minesLeftText = document.querySelector('[data-mines-count]')
let minesLeft = minesLeftText && parseInt(minesLeftText.textContent)
if (tile.status === TILE_STATUS.FLAGGED) {
tile.status = TILE_STATUS.HIDDEN
if (minesLeftText) minesLeftText.textContent = ++minesLeft
} else {
tile.status = TILE_STATUS.FLAGGED
if (minesLeftText) minesLeftText.textContent = --minesLeft
}
}
export function checkWin(board) {
return board.every((row) => {
return row.every((tile) => {
return (
tile.status === TILE_STATUS.NUMBER ||
(tile.mine &&
(tile.status === TILE_STATUS.HIDDEN ||
tile.status === TILE_STATUS.FLAGGED))
)
})
})
}
export function checkLose(board) {
return board.some((row) => {
return row.some((tile) => {
return tile.status === TILE_STATUS.MINE
})
})
}
function getMinePositions(boardSize, numberOfMines) {
const positions = []
while (positions.length < numberOfMines) {
const newCoord = {
x: Math.floor(Math.random() * boardSize),
y: Math.floor(Math.random() * boardSize),
}
if (!positions.some((value) => isEqual(value, newCoord))) {
positions.push(newCoord)
}
}
return positions
}
function nearbyTiles(board, { x, y }) {
const tiles = []
for (let xOffset = -1; xOffset <= 1; xOffset++) {
for (let yOffset = -1; yOffset <= 1; yOffset++) {
const tile = board[x + xOffset]?.[y + yOffset]
if (tile) tiles.push(tile)
}
}
return tiles
}
function isEqual(a, b) {
return JSON.stringify(a) === JSON.stringify(b)
}