134 lines
3.4 KiB
JavaScript
134 lines
3.4 KiB
JavaScript
const SIZE = 10;
|
|
const MINES = 15;
|
|
const boardDiv = document.getElementById('board');
|
|
const statusDiv = document.getElementById('status');
|
|
const restartBtn = document.getElementById('restart-btn');
|
|
let board, revealed, flagged, gameOver, cellsRevealed;
|
|
|
|
function initGame() {
|
|
board = Array.from({length: SIZE}, () => Array(SIZE).fill(0));
|
|
revealed = Array.from({length: SIZE}, () => Array(SIZE).fill(false));
|
|
flagged = Array.from({length: SIZE}, () => Array(SIZE).fill(false));
|
|
gameOver = false;
|
|
cellsRevealed = 0;
|
|
statusDiv.textContent = 'Haz clic izquierdo para revelar, clic derecho para marcar.';
|
|
placeMines();
|
|
calculateNumbers();
|
|
renderBoard();
|
|
}
|
|
|
|
function placeMines() {
|
|
let placed = 0;
|
|
while (placed < MINES) {
|
|
const r = Math.floor(Math.random() * SIZE);
|
|
const c = Math.floor(Math.random() * SIZE);
|
|
if (board[r][c] !== 'M') {
|
|
board[r][c] = 'M';
|
|
placed++;
|
|
}
|
|
}
|
|
}
|
|
|
|
function calculateNumbers() {
|
|
for (let r = 0; r < SIZE; r++) {
|
|
for (let c = 0; c < SIZE; c++) {
|
|
if (board[r][c] === 'M') continue;
|
|
let count = 0;
|
|
for (let i = -1; i <= 1; i++) {
|
|
for (let j = -1; j <= 1; j++) {
|
|
let nr = r+i, nc = c+j;
|
|
if (nr >= 0 && nr < SIZE && nc >=0 && nc < SIZE && board[nr][nc] === 'M') count++;
|
|
}
|
|
}
|
|
board[r][c] = count;
|
|
}
|
|
}
|
|
}
|
|
|
|
function renderBoard() {
|
|
boardDiv.innerHTML = '';
|
|
for (let r = 0; r < SIZE; r++) {
|
|
for (let c = 0; c < SIZE; c++) {
|
|
const cell = document.createElement('div');
|
|
cell.classList.add('cell');
|
|
if (revealed[r][c]) {
|
|
cell.classList.add('revealed');
|
|
if (board[r][c] === 'M') {
|
|
cell.classList.add('mine');
|
|
cell.textContent = '💣';
|
|
} else if (board[r][c] > 0) {
|
|
cell.textContent = board[r][c];
|
|
} else {
|
|
cell.textContent = '';
|
|
}
|
|
} else if (flagged[r][c]) {
|
|
cell.classList.add('flag');
|
|
cell.textContent = '🚩';
|
|
} else {
|
|
cell.textContent = '';
|
|
}
|
|
// Click izquierdo
|
|
cell.onmousedown = (e) => {
|
|
if (gameOver) return;
|
|
if (e.button === 0) revealCell(r, c);
|
|
else if (e.button === 2) toggleFlag(r, c);
|
|
};
|
|
cell.oncontextmenu = (e) => e.preventDefault();
|
|
boardDiv.appendChild(cell);
|
|
}
|
|
}
|
|
}
|
|
|
|
function revealCell(r, c) {
|
|
if (revealed[r][c] || flagged[r][c]) return;
|
|
revealed[r][c] = true;
|
|
cellsRevealed++;
|
|
if (board[r][c] === 'M') {
|
|
endGame(false);
|
|
renderBoard();
|
|
return;
|
|
} else if (board[r][c] === 0) {
|
|
// Revela recursivo
|
|
for (let i = -1; i <= 1; i++) {
|
|
for (let j = -1; j <= 1; j++) {
|
|
let nr = r+i, nc = c+j;
|
|
if (nr >= 0 && nr < SIZE && nc >= 0 && nc < SIZE) {
|
|
if (!revealed[nr][nc]) revealCell(nr, nc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
checkWin();
|
|
renderBoard();
|
|
}
|
|
|
|
function toggleFlag(r, c) {
|
|
if (revealed[r][c]) return;
|
|
flagged[r][c] = !flagged[r][c];
|
|
renderBoard();
|
|
}
|
|
|
|
function checkWin() {
|
|
if (cellsRevealed === SIZE*SIZE - MINES) {
|
|
endGame(true);
|
|
}
|
|
}
|
|
|
|
function endGame(won) {
|
|
gameOver = true;
|
|
// Revela todas las minas si perdiste
|
|
if (!won) {
|
|
for (let r = 0; r < SIZE; r++) {
|
|
for (let c = 0; c < SIZE; c++) {
|
|
if (board[r][c] === 'M') revealed[r][c] = true;
|
|
}
|
|
}
|
|
statusDiv.textContent = "¡BOOM! Has perdido 💣";
|
|
} else {
|
|
statusDiv.textContent = "¡Felicidades! Has ganado 🎉";
|
|
}
|
|
}
|
|
|
|
restartBtn.onclick = initGame;
|
|
|
|
initGame(); |