buscaminas/game.js

237 lines
6.5 KiB
JavaScript

const canvas = document.getElementById("tablero");
const ctx = canvas.getContext("2d");
const startButton = document.getElementById("startButton");
const banderas = document.getElementById("banderas");
const tiempo = document.getElementById("tiempo");
const FILAS = 25;
const COLUMNAS = 25;
const cellSize = 32;
const nBombas = 50;
const tilesBorde = new Image();
tilesBorde.src = './img/borde.png';
const tilesMisc = new Image();
tilesMisc.src = './img/tiles.png';
let nBanderas=nBombas;
let tiempoTranscurrido = 0;
let showBombas = false;
let cronometro;
let tablero = [];
canvas.width = COLUMNAS * cellSize;
canvas.height = FILAS * cellSize;
function handleKey(event) {
if (event.key === "1") {
showBombas=!showBombas;
} else if (event.key === "Escape") {
gameOver();
}
};
function handleClick(event) {
const { x, y } = getCellCoordinates(event);
if (!tablero[y][x].tieneFlag) levantaCelda(y, x);
}
function handleContextMenu(event) {
event.preventDefault();
const { x, y } = getCellCoordinates(event);
marcaFlagCelda(y, x);
}
function getCellCoordinates(event) {
const rect = canvas.getBoundingClientRect();
return {
x: Math.floor((event.x - rect.left) / cellSize),
y: Math.floor((event.y - rect.top) / cellSize),
};
}
function generaTablero() {
for (let y = 0; y < FILAS; y++) {
tablero[y] = [];
for (let x = 0; x < COLUMNAS; x++) {
tablero[y][x] = {
esMina: false,
abierto: false,
tieneFlag: false,
nAdyacentes: 0,
};
}
}
for (let z = 0; z < nBombas; z++) {
let x, y;
do {
y = Math.floor(Math.random() * (FILAS));
x = Math.floor(Math.random() * (COLUMNAS));
} while (tablero[y][x].esMina);
tablero[y][x].esMina = true;
for (let i = -1; i <= 1; i++) {
for (let j = -1; j <= 1; j++) {
if (y + i >= 0 && y + i < FILAS && x + j >= 0 && x + j < COLUMNAS) {
if (!tablero[y + i][x + j].esMina) {
tablero[y + i][x + j].nAdyacentes += 1;
}
}
}
}
}
}
function levantaCelda(y, x) {
if (!tablero[y][x].abierto) {
tablero[y][x].abierto = true;
if (tablero[y][x].tieneFlag){
tablero[y][x].tieneFlag = false;
nBanderas++;
}
if (tablero[y][x].nAdyacentes === 0 && !tablero[y][x].esMina) {
for (let i = -1; i <= 1; i++) {
for (let j = -1; j <= 1; j++) {
if (
y + i >= 0 &&
y + i < FILAS &&
x + j >= 0 &&
x + j < COLUMNAS &&
!(i === 0 && j === 0)
) {
levantaCelda(y + i, x + j);
}
}
}
}
if (tablero[y][x].esMina) {
gameOver();
} else if (comprobarVictoria()) {
victoria();
}
}
}
function comprobarVictoria() {
return tablero.every((row) =>
row.every((cell) => cell.abierto || cell.esMina)
);
}
function marcaFlagCelda(y, x) {
if (!tablero[y][x].abierto) {
if (tablero[y][x].tieneFlag){
tablero[y][x].tieneFlag = false;
nBanderas++;
}else if (nBanderas>0){
tablero[y][x].tieneFlag = true;
nBanderas--;
}
}
}
function dibujaTablero() {
for (let y = 0; y < FILAS; y++) {
for (let x = 0; x < COLUMNAS; x++) {
if (!tablero[y][x].abierto) {
ctx.drawImage(tilesMisc,32,0,cellSize,cellSize,x * cellSize, y * cellSize,cellSize,cellSize);
} else {
ctx.drawImage(tilesMisc,96,0,cellSize,cellSize,x * cellSize, y * cellSize,cellSize,cellSize);
if (tablero[y][x].nAdyacentes > 0) {
ctx.font = "24px Bungee Spice";
//ctx.fillStyle = "black";
const text = tablero[y][x].nAdyacentes;
const textX =
x * cellSize + cellSize / 2 - ctx.measureText(text).width / 2;
const textY = y * cellSize + cellSize / 2 + 10;
ctx.fillText(text, textX, textY);
}
}
if (showBombas && tablero[y][x].esMina){
ctx.drawImage(tilesMisc,64,0,cellSize,cellSize,x * cellSize, y * cellSize,cellSize,cellSize);
}
if (tablero[y][x].tieneFlag) {
ctx.drawImage(tilesMisc,0,0,cellSize,cellSize,x * cellSize, y * cellSize,cellSize,cellSize);
}
}
}
dibujaBordesMapa();
}
function dibujaBordesMapa(){
for (let y = 1; y < FILAS-1; y++) {
ctx.drawImage(tilesBorde,96,0,cellSize,cellSize,0,y*cellSize,cellSize,cellSize);
ctx.drawImage(tilesBorde,96,32,cellSize,cellSize,(COLUMNAS-1)*cellSize,y*cellSize,cellSize,cellSize);
}
for (let x = 1; x < COLUMNAS-1; x++) {
ctx.drawImage(tilesBorde,64,0,cellSize,cellSize,x*cellSize,0,cellSize,cellSize);
ctx.drawImage(tilesBorde,64,32,cellSize,cellSize,x*cellSize,(FILAS-1)*cellSize,cellSize,cellSize);
}
ctx.drawImage(tilesBorde,0,0,cellSize,cellSize,0,0,cellSize,cellSize);
ctx.drawImage(tilesBorde,32,0,cellSize,cellSize,(FILAS-1)*cellSize,0,cellSize,cellSize);
ctx.drawImage(tilesBorde,0,32,cellSize,cellSize,0,(COLUMNAS-1)*cellSize,cellSize,cellSize);
ctx.drawImage(tilesBorde,32,32,cellSize,cellSize,(FILAS-1)*cellSize,(COLUMNAS-1)*cellSize,cellSize,cellSize);
}
function gameLoop() {
tiempo.textContent = convertirTiempo(tiempoTranscurrido);
banderas.textContent = nBanderas;
dibujaTablero();
window.requestAnimationFrame(gameLoop);
}
function iniciarCronometro() {
tiempoTranscurrido = 0;
cronometro = setInterval(() => {
tiempoTranscurrido++;
}, 1000);
}
function detenerCronometro() {
clearInterval(cronometro);
}
function convertirTiempo(tiempoSegundos) {
const horas = Math.floor(tiempoSegundos / 3600);
const minutos = Math.floor((tiempoSegundos % 3600) / 60);
const segundos = tiempoSegundos % 60;
const horasStr = String(horas).padStart(2, "0");
const minutosStr = String(minutos).padStart(2, "0");
const segundosStr = String(segundos).padStart(2, "0");
return `${horasStr}:${minutosStr}:${segundosStr}`;
}
function iniciarPartida() {
startButton.blur();
startButton.style.visibility = "hidden";
nBanderas=nBombas;
showBombas=false;
canvas.addEventListener("click", handleClick);
canvas.addEventListener("contextmenu", handleContextMenu);
document.addEventListener("keydown", handleKey);
generaTablero();
iniciarCronometro();
gameLoop();
}
function terminarPartida() {
canvas.removeEventListener("click", handleClick);
canvas.removeEventListener("contextmenu", handleContextMenu);
document.removeEventListener("keydown", handleKey);
detenerCronometro();
startButton.style.visibility = "visible";
startButton.focus();
}
function victoria() {
terminarPartida();
}
function gameOver() {
terminarPartida();
}