Añadidos juegos
This commit is contained in:
15
buscaminas/index.html
Normal file
15
buscaminas/index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Buscaminas</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Buscaminas</h1>
|
||||
<div id="status"></div>
|
||||
<div id="board"></div>
|
||||
<button id="restart-btn">Reiniciar</button>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
134
buscaminas/script.js
Normal file
134
buscaminas/script.js
Normal file
@@ -0,0 +1,134 @@
|
||||
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();
|
149
buscaminas/styles.css
Normal file
149
buscaminas/styles.css
Normal file
@@ -0,0 +1,149 @@
|
||||
/* ===== Diseño base ===== */
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #f2f2f2;
|
||||
font-family: Arial, sans-serif;
|
||||
color: #222;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ===== Encabezado ===== */
|
||||
h1 {
|
||||
color: #d7263d;
|
||||
margin-top: 2rem;
|
||||
font-size: clamp(2rem, 4vw, 2.5rem);
|
||||
}
|
||||
|
||||
/* ===== Tablero ===== */
|
||||
#board {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(10, 1fr);
|
||||
gap: 0.7vw;
|
||||
margin: 2.5rem auto 1.7rem auto;
|
||||
background: #1565c0;
|
||||
padding: 2vw;
|
||||
border-radius: 1rem;
|
||||
width: 100%;
|
||||
max-width: 98vw;
|
||||
}
|
||||
|
||||
/* Una celda */
|
||||
.cell {
|
||||
aspect-ratio: 1 / 1;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-radius: 0.7rem;
|
||||
box-shadow: 0 2px 8px #bbb;
|
||||
font-size: clamp(1rem, 2.5vw, 1.4rem);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.15s;
|
||||
user-select: none;
|
||||
}
|
||||
.cell.revealed { background: #bbdefb; cursor: default; }
|
||||
.cell.mine { background: #d7263d; color: #fff; }
|
||||
.cell.flag { background: #ffe082; color: #d7263d; }
|
||||
|
||||
/* ===== Estado y botón ===== */
|
||||
#status {
|
||||
font-size: 1.1rem;
|
||||
min-height: 2em;
|
||||
margin: 0.5em 0 0.7em 0;
|
||||
}
|
||||
#restart-btn {
|
||||
background: #d7263d;
|
||||
color: #fff;
|
||||
font-size: clamp(1rem, 2vw, 1.3rem);
|
||||
border: none;
|
||||
border-radius: 0.7rem;
|
||||
padding: 0.5em 2em;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
margin-bottom: 1.2em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
#restart-btn:hover { background: #920c22; }
|
||||
|
||||
|
||||
/* ========================================
|
||||
===== Pantallas pequeñas (<720px) ====
|
||||
======================================== */
|
||||
@media (max-width: 720px) {
|
||||
h1 {
|
||||
margin-top: 3vw;
|
||||
font-size: clamp(1.3rem, 6vw, 2.1rem);
|
||||
}
|
||||
#board {
|
||||
/* Cambia columnas si el tablero lo permite */
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
padding: 4vw;
|
||||
border-radius: 4vw;
|
||||
gap: 2.8vw;
|
||||
margin-top: 4vw;
|
||||
margin-bottom: 6vw;
|
||||
max-width: 99vw;
|
||||
}
|
||||
.cell {
|
||||
font-size: clamp(1.2rem, 8vw, 2.5rem);
|
||||
border-radius: 3vw;
|
||||
}
|
||||
#restart-btn {
|
||||
font-size: clamp(1rem, 8vw, 2rem);
|
||||
padding: 3vw 12vw;
|
||||
border-radius: 3vw;
|
||||
margin-bottom: 6vw;
|
||||
margin-top: 3vw;
|
||||
}
|
||||
#status {
|
||||
font-size: clamp(1rem, 7vw, 1.7rem);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
===== Pantallas muy pequeñas (<400px) ==
|
||||
======================================== */
|
||||
@media (max-width: 400px) {
|
||||
#board {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
padding: 2vw;
|
||||
gap: 2vw;
|
||||
border-radius: 5vw;
|
||||
}
|
||||
.cell { font-size: clamp(1rem, 10vw, 2.2rem); }
|
||||
#restart-btn {
|
||||
padding: 3vw 4vw;
|
||||
font-size: clamp(0.9rem, 7vw, 1.5rem);
|
||||
border-radius: 5vw;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
===== Pantallas grandes (>1200px) ====
|
||||
======================================== */
|
||||
@media (min-width: 1200px) {
|
||||
#board {
|
||||
max-width: 700px;
|
||||
padding: 2rem;
|
||||
gap: 0.7rem;
|
||||
}
|
||||
h1 {
|
||||
font-size: clamp(2.5rem, 3vw, 3.5rem);
|
||||
}
|
||||
.cell {
|
||||
font-size: clamp(1.3rem, 2vw, 2rem);
|
||||
}
|
||||
}
|
||||
|
||||
/* :::::::::::::::::::::::::::::: */
|
Reference in New Issue
Block a user