xxxxxxxxxx
222
let grid = []
let cols, rows;
let resolution = 30
let size
let game_over = false
let first_click = true
function setup() {
createCanvas(600, 600);
reset()
}
function reset() {
current_tile_index = -1
game_over = false
first_click = false
rows = width / resolution
cols = height / resolution
// Initialize cells
for (let i = 0; i < rows * cols; i++)
grid[i] = {
is_bomb: false,
neighbours: 0,
show: false,
flagged: false,
pressed: false
}
}
function firstClick(grid, index) {
first_click = true
let ignore_index = index
// Generate bombs, ignore where first clicked
for (let i = 0; i < rows * cols; i++)
grid[i].is_bomb = i === ignore_index ? false: floor(random(8)) === 0
// Calculate neighbours
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
let i = row * cols + col
grid[i].neighbours = countNeighbours(grid, row, col)
}
}
}
function countNeighbours(grid, row, col) {
let sum = 0
for (let i = -1; i < 2; i++) {
for (let j = -1; j < 2; j++) {
let new_row = row + i
let new_col = col + j
if (new_row >= 0 && new_row < rows && new_col >= 0 && new_col < cols ) {
let index = (new_row) * rows + (new_col)
if (grid[index].is_bomb)
sum++
}
}
}
return sum
}
let current_tile_index = -1
function mousePressed() {
if (!game_over) {
let row = Math.floor( mouseY / resolution )
let col = Math.floor( mouseX /resolution )
current_tile_index = row * cols + col
grid[current_tile_index].pressed = true
}
}
function mouseDragged() {
if (current_tile_index >= 0) {
let row = Math.floor( mouseY / resolution )
let col = Math.floor( mouseX /resolution )
const new_tile_index = row * cols + col
if (new_tile_index != current_tile_index) {
grid[current_tile_index].pressed = false
current_tile_index = -1
}
}
}
function mouseReleased(e) {
if (!first_click) {
firstClick(grid, current_tile_index)
}
if (game_over) {
reset()
}
else if (current_tile_index >= 0) {
const tile = grid[current_tile_index]
tile.pressed = false
if (mouseButton === LEFT) {
if (!tile.flagged) {
if (tile.is_bomb) {
for (let t of grid) {
t.show = true
}
game_over = true
}
else if (!tile.neighbours) {
const row = Math.floor( current_tile_index / cols )
const col = Math.floor( current_tile_index % cols )
floodShow(grid, row, col)
}
else {
tile.show = true
}
}
}
else if (mouseButton === CENTER) {
if (!tile.show)
tile.flagged = !tile.flagged
}
}
current_tile_index = -1
}
function draw() {
background(220);
renderCells(grid, width/resolution, resolution)
if (game_over) {
fill(12)
textSize(width/16)
text('LOST, click to restart', width/2, height/2)
}
}
function floodShow (grid, row, col) {
if (row < 0 || row >= rows) return
if (col < 0 || col >= cols) return
let index = row * rows + col
let tile = grid[index]
if (tile.show === false && !tile.is_bomb) {
grid[index].show = true
if (grid[index].neighbours) return
floodShow(grid, row + 1, col )
floodShow(grid, row - 1, col )
floodShow(grid, row , col + 1)
floodShow(grid, row , col - 1)
}
}
function renderCells(grid, size, resolution) {
stroke(180)
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
let x = col * resolution
let y = row * resolution
let index = row * cols + col
let { is_bomb, neighbours, show, flagged, pressed } = grid[index]
let fill_col = 255
if (pressed)
fill_col = 160
if (show)
fill_col = 200
fill( fill_col )
rectMode(CORNER)
rect(x, y, resolution-1, resolution-1)
if (pressed) {
}
if (show) {
if (is_bomb) {
ellipseMode(CORNER)
fill(120)
ellipse(x+1,y+1, resolution-3, resolution-3)
}
else if (neighbours) {
fill(12)
textSize(resolution/2)
textAlign(CENTER, CENTER)
text(neighbours.toString(), x + resolution/2, y+resolution/2)
}
}
if (flagged) {
fill(12)
textSize(resolution/2)
textAlign(CENTER, CENTER)
text('F', x + resolution/2, y+resolution/2)
}
}
}
}