deepsite / index.html
DarkDuckDock's picture
Add 2 files
1b2ce87 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Classic Minesweeper</title>
<style>
:root {
--cell-size: 40px;
--cell-bg: #c0c0c0;
--cell-border-light: #f0f0f0;
--cell-border-dark: #808080;
--cell-revealed: #b8b8b8;
--mine-counter: #ff0000;
--primary-color: #4682b4;
--button-hover: #5f9ea0;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
background-color: #f5f5f5;
padding: 20px;
}
.game-container {
background-color: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
padding: 20px;
text-align: center;
}
h1 {
color: var(--primary-color);
margin-bottom: 20px;
font-size: 2.5rem;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
}
.game-info {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
background-color: var(--primary-color);
color: white;
padding: 10px 20px;
border-radius: 5px;
font-weight: bold;
}
.counter, .timer {
font-family: 'Courier New', monospace;
font-size: 1.5rem;
letter-spacing: 2px;
}
.board {
display: grid;
grid-template-columns: repeat(9, var(--cell-size));
grid-gap: 2px;
margin: 0 auto 20px;
border: 4px solid var(--cell-border-dark);
border-radius: 5px;
background-color: var(--cell-border-dark);
}
.cell {
width: var(--cell-size);
height: var(--cell-size);
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 1.2rem;
background-color: var(--cell-bg);
border-top: 3px solid var(--cell-border-light);
border-left: 3px solid var(--cell-border-light);
border-right: 3px solid var(--cell-border-dark);
border-bottom: 3px solid var(--cell-border-dark);
cursor: pointer;
user-select: none;
transition: all 0.1s ease;
}
.cell.revealed {
background-color: var(--cell-revealed);
border: 1px solid var(--cell-border-dark);
}
.cell.flagged::after {
content: '🚩';
font-size: 0.8em;
}
.cell.mine::after {
content: '💣';
}
.cell.mine.revealed {
background-color: #ffcccc;
}
.cell:hover:not(.revealed):not(.flagged) {
background-color: #d8d8d8;
}
.number-1 { color: blue; }
.number-2 { color: green; }
.number-3 { color: red; }
.number-4 { color: darkblue; }
.number-5 { color: brown; }
.number-6 { color: teal; }
.number-7 { color: black; }
.number-8 { color: gray; }
.controls {
margin-top: 10px;
}
button {
background-color: var(--primary-color);
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 1rem;
font-weight: bold;
transition: background-color 0.2s;
}
button:hover {
background-color: var(--button-hover);
}
.message {
margin-top: 15px;
min-height: 24px;
font-weight: bold;
color: var(--primary-color);
}
@media (max-width: 500px) {
:root {
--cell-size: 30px;
}
h1 {
font-size: 1.8rem;
}
}
</style>
</head>
<body>
<div class="game-container">
<h1>Minesweeper</h1>
<div class="game-info">
<div class="counter">💣 <span id="mines-count">10</span></div>
<div class="timer"><span id="time">0</span>s</div>
</div>
<div class="board" id="board"></div>
<div class="controls">
<button id="reset-btn">New Game</button>
</div>
<div class="message" id="message"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const SIZE = 9;
const MINES_COUNT = 10;
const board = document.getElementById('board');
const minesCountElement = document.getElementById('mines-count');
const timerElement = document.getElementById('time');
const resetBtn = document.getElementById('reset-btn');
const messageElement = document.getElementById('message');
let cells = [];
let mines = [];
let revealed = 0;
let flagged = 0;
let gameOver = false;
let firstClick = true;
let timer;
let seconds = 0;
function initGame() {
// Reset game state
board.innerHTML = '';
cells = [];
mines = [];
revealed = 0;
flagged = 0;
gameOver = false;
firstClick = true;
clearInterval(timer);
seconds = 0;
timerElement.textContent = '0';
minesCountElement.textContent = MINES_COUNT;
messageElement.textContent = '';
// Create cells
for (let row = 0; row < SIZE; row++) {
cells[row] = [];
for (let col = 0; col < SIZE; col++) {
const cell = document.createElement('div');
cell.className = 'cell';
cell.dataset.row = row;
cell.dataset.col = col;
cell.addEventListener('click', () => handleCellClick(row, col));
cell.addEventListener('contextmenu', (e) => {
e.preventDefault();
handleRightClick(row, col);
});
board.appendChild(cell);
cells[row][col] = {
element: cell,
mine: false,
revealed: false,
flagged: false,
neighborMines: 0
};
}
}
}
function startTimer() {
clearInterval(timer);
timer = setInterval(() => {
seconds++;
timerElement.textContent = seconds;
}, 1000);
}
function placeMines(firstRow, firstCol) {
let minesPlaced = 0;
while (minesPlaced < MINES_COUNT) {
const row = Math.floor(Math.random() * SIZE);
const col = Math.floor(Math.random() * SIZE);
// Don't place mine on first click cell or its neighbors
const isFirstClickOrAdjacent =
(row === firstRow && col === firstCol) ||
(Math.abs(row - firstRow) <= 1 && Math.abs(col - firstCol) <= 1);
if (!cells[row][col].mine && !isFirstClickOrAdjacent) {
cells[row][col].mine = true;
mines.push({row, col});
minesPlaced++;
}
}
// Calculate neighbor mines for each cell
for (let row = 0; row < SIZE; row++) {
for (let col = 0; col < SIZE; col++) {
if (!cells[row][col].mine) {
cells[row][col].neighborMines = countNeighborMines(row, col);
}
}
}
}
function countNeighborMines(row, col) {
let count = 0;
for (let r = Math.max(0, row - 1); r <= Math.min(SIZE - 1, row + 1); r++) {
for (let c = Math.max(0, col - 1); c <= Math.min(SIZE - 1, col + 1); c++) {
if (cells[r][c].mine) {
count++;
}
}
}
return count;
}
function handleCellClick(row, col) {
if (gameOver || cells[row][col].flagged || cells[row][col].revealed) {
return;
}
if (firstClick) {
firstClick = false;
placeMines(row, col);
startTimer();
}
revealCell(row, col);
if (cells[row][col].mine) {
gameOver = true;
revealAllMines();
clearInterval(timer);
messageElement.textContent = 'Game Over! You hit a mine.';
} else if (revealed === SIZE * SIZE - MINES_COUNT) {
gameOver = true;
flagAllMines();
clearInterval(timer);
messageElement.textContent = 'Congratulations! You won!';
}
}
function revealCell(row, col) {
if (row < 0 || row >= SIZE || col < 0 || col >= SIZE ||
cells[row][col].revealed || cells[row][col].flagged) {
return;
}
cells[row][col].revealed = true;
cells[row][col].element.classList.add('revealed');
revealed++;
if (cells[row][col].neighborMines > 0) {
cells[row][col].element.classList.add(`number-${cells[row][col].neighborMines}`);
cells[row][col].element.textContent = cells[row][col].neighborMines;
} else {
// Reveal all adjacent cells if this is an empty cell
for (let r = row - 1; r <= row + 1; r++) {
for (let c = col - 1; c <= col + 1; c++) {
if (r === row && c === col) continue;
revealCell(r, c);
}
}
}
}
function handleRightClick(row, col) {
if (gameOver || cells[row][col].revealed) {
return;
}
if (cells[row][col].flagged) {
cells[row][col].flagged = false;
cells[row][col].element.classList.remove('flagged');
flagged--;
} else {
cells[row][col].flagged = true;
cells[row][col].element.classList.add('flagged');
flagged++;
}
minesCountElement.textContent = MINES_COUNT - flagged;
return false;
}
function revealAllMines() {
mines.forEach(mine => {
const cell = cells[mine.row][mine.col];
if (!cell.flagged) {
cell.revealed = true;
cell.element.classList.add('revealed', 'mine');
}
});
}
function flagAllMines() {
mines.forEach(mine => {
const cell = cells[mine.row][mine.col];
if (!cell.flagged) {
cell.flagged = true;
cell.element.classList.add('flagged');
}
});
}
resetBtn.addEventListener('click', initGame);
// Start the game
initGame();
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
</html>