Skip to content

Instantly share code, notes, and snippets.

@frzi
Last active August 23, 2023 14:07
Show Gist options
  • Save frzi/5c397d396db3b94c281d57e803227db8 to your computer and use it in GitHub Desktop.
Save frzi/5c397d396db3b94c281d57e803227db8 to your computer and use it in GitHub Desktop.
Generate Minesweeper for Discord
// https://gist.github.com/frzi/5c397d396db3b94c281d57e803227db8
const MINE = -1
function generateSpaces(width = 9, height = 9, mines = 15) {
const totalSpaces = width * height
mines = Math.min(totalSpaces - 1, Math.abs(mines))
let spaces = new Array(totalSpaces).fill(0)
let openSpaces = spaces.map((_, index) => index)
// Generate the mines.
while (mines > 0 && openSpaces.length) {
const randomIndex = Math.floor(Math.random() * openSpaces.length)
const space = openSpaces.splice(randomIndex, 1)
spaces[space] = MINE
mines--
}
// Utils.
const indexToXY = index => [index % width, Math.floor(index / height)]
const xyToIndex = ([x, y]) => y * width + x
// Generate the numbers.
const kernel = [
[-1, -1], [0, -1], [1, -1],
[-1, 0], [1, 0],
[-1, 1], [0, 1], [1, 1],
]
function trace(index) {
if (spaces[index] == -1) {
return
}
let mineCount = 0
for (const [offsetX, offsetY] of kernel) {
let [x, y] = indexToXY(index)
x += offsetX
y += offsetY
if (x < 0 || x >= width || y < 0 || y >= height) {
continue
}
const offsetIndex = xyToIndex([x, y])
if (spaces[offsetIndex] == MINE) {
mineCount++
}
}
spaces[index] = mineCount
}
spaces.forEach((_, index) => trace(index))
return spaces
}
function createDiscordString(spaces, width = 9) {
const nonMineIndices = spaces.map((space, index) => space != MINE ? index : null).filter(p => p !== null)
const openSpaceIndices = spaces.map((space, index) => space == 0 ? index : null).filter(p => p !== null)
// Find a random index to reveal.
const revealIndex = (() => {
if (openSpaceIndices.length > 0) {
return openSpaceIndices[Math.floor(Math.random() * openSpaceIndices.length)]
}
else {
return nonMineIndices[Math.floor(Math.random() * nonMineIndices.length)]
}
})()
const emojis = [
'white_large_square', 'one', 'two', 'three',
'four', 'five', 'six', 'seven', 'eight',
]
emojis[MINE] = 'boom'
let revealed = false
let string = ''
let parsedOpenSpaces = 0
for (let a = 0; a < spaces.length; a++) {
const emoji = emojis[spaces[a]]
parsedOpenSpaces += spaces[a] == 0
if (a == revealIndex) {
string += `:${emoji}:`
}
else {
string += `||:${emoji}:||`
}
if ((a + 1) % width == 0) {
string += '\n'
}
}
return string
}
function generate() {
const field = generateSpaces(iwidth.value, iheight.value, imines.value)
const string = createDiscordString(field, iwidth.value)
pre.textContent = string
warning.style.display = string.length > 2000 ? 'block' : 'none'
}
iwidth.oninput = iheight.oninput = imines.oninput = generate
generate()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment