726 lines
25 KiB
HTML
726 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Minesweeper | PonyWave Tools</title>
|
|
<meta property="og:title" content="Minesweeper | PonyWave Tools">
|
|
<meta property="og:description" content="Klassisches Minesweeper-Spiel mit verschiedenen Schwierigkeitsgraden">
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:url" content="https://tools.ponywave.de/minesweeper">
|
|
<meta property="og:image" content="https://tools.ponywave.de/minesweeper/icon.png">
|
|
|
|
<!-- Favicons -->
|
|
<link rel="icon" type="image/png" href="https://tools.ponywave.de/minesweeper/icon.png">
|
|
<link rel="shortcut icon" href="https://tools.ponywave.de/minesweeper/icon.png">
|
|
<link rel="apple-touch-icon" href="https://tools.ponywave.de/minesweeper/icon.png">
|
|
<link rel="icon" sizes="192x192" href="https://tools.ponywave.de/minesweeper/icon.png">
|
|
|
|
<!-- Umami Tracking -->
|
|
<script defer src="https://stats.ponywave.de/script" data-website-id="9ef713d2-adb9-4906-9df5-708d8a8b9131" data-tag="minesweeper"></script>
|
|
|
|
<style>
|
|
:root {
|
|
--primary-color: #7F006E;
|
|
--secondary-color: #FF7FED;
|
|
--bg-gradient: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
|
|
--text-color: #2c3e50;
|
|
--cell-size: 30px;
|
|
--board-bg: #c0c0c0;
|
|
--cell-bg: #c0c0c0;
|
|
--cell-border: #808080;
|
|
--cell-revealed: #d9d9d9;
|
|
--font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
--shadow-color: rgba(0, 0, 0, 0.1);
|
|
--footer-color: rgba(255, 255, 255, 0.8);
|
|
--button-bg: #f0f0f0;
|
|
--button-hover: #e0e0e0;
|
|
--button-active: #d0d0d0;
|
|
}
|
|
|
|
.dark-mode {
|
|
--bg-gradient: linear-gradient(135deg, #4A0040 0%, #CC65B5 100%);
|
|
--text-color: #ffffff;
|
|
--board-bg: #444444;
|
|
--cell-bg: #555555;
|
|
--cell-border: #666666;
|
|
--cell-revealed: #333333;
|
|
--button-bg: #555555;
|
|
--button-hover: #666666;
|
|
--button-active: #777777;
|
|
--shadow-color: rgba(0, 0, 0, 0.3);
|
|
--footer-color: rgba(0, 0, 0, 0.8);
|
|
}
|
|
|
|
body {
|
|
font-family: var(--font-family);
|
|
background-color: var(--board-bg);
|
|
background-image: none;
|
|
color: var(--text-color);
|
|
margin: 0;
|
|
padding: 20px 20px 60px;
|
|
min-height: 100vh;
|
|
position: relative;
|
|
line-height: 1.6;
|
|
text-align: center;
|
|
}
|
|
|
|
.dark-mode body {
|
|
background-image: none;
|
|
background-color: #444444;
|
|
}
|
|
|
|
.theme-toggle {
|
|
position: fixed;
|
|
top: 20px;
|
|
right: 20px;
|
|
background: var(--button-bg);
|
|
border: none;
|
|
border-radius: 50%;
|
|
width: 40px;
|
|
height: 40px;
|
|
cursor: pointer;
|
|
box-shadow: 0 2px 4px var(--shadow-color);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 1.2em;
|
|
transition: all 0.3s ease;
|
|
z-index: 10;
|
|
}
|
|
|
|
.theme-toggle:hover {
|
|
transform: scale(1.1);
|
|
}
|
|
|
|
h1 {
|
|
margin: 20px 0;
|
|
color: var(--text-color);
|
|
text-shadow: 2px 2px 4px var(--shadow-color);
|
|
}
|
|
|
|
.game-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 20px auto;
|
|
max-width: 800px;
|
|
background: rgba(255, 255, 255, 0.9);
|
|
padding: 20px;
|
|
border-radius: 15px;
|
|
box-shadow: 0 4px 6px var(--shadow-color);
|
|
backdrop-filter: blur(5px);
|
|
overflow-x: hidden;
|
|
width: 90%;
|
|
}
|
|
|
|
.dark-mode .game-container {
|
|
background: rgba(45, 45, 45, 0.9);
|
|
}
|
|
|
|
.game-header {
|
|
display: flex;
|
|
width: 100%;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.counter {
|
|
background: #000;
|
|
color: #f00;
|
|
font-family: 'Digital', monospace;
|
|
padding: 5px 10px;
|
|
border-radius: 3px;
|
|
font-size: 1.5em;
|
|
min-width: 80px;
|
|
text-align: center;
|
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.smiley {
|
|
width: 40px;
|
|
height: 40px;
|
|
background: var(--button-bg);
|
|
border: 2px outset var(--cell-border);
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 1.5em;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
|
|
.smiley:active {
|
|
border-style: inset;
|
|
}
|
|
|
|
.difficulty {
|
|
display: flex;
|
|
gap: 10px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.difficulty button {
|
|
padding: 8px 15px;
|
|
background: var(--button-bg);
|
|
border: 1px solid var(--cell-border);
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
font-family: var(--font-family);
|
|
}
|
|
|
|
.difficulty button:hover {
|
|
background: var(--button-hover);
|
|
}
|
|
|
|
.difficulty button.active {
|
|
background: var(--primary-color);
|
|
color: white;
|
|
}
|
|
|
|
.minesweeper-board {
|
|
display: grid;
|
|
background: var(--board-bg);
|
|
border: 3px solid var(--cell-border);
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
|
margin: 0 auto;
|
|
user-select: none;
|
|
max-width: 100%;
|
|
}
|
|
|
|
.cell {
|
|
width: var(--cell-size);
|
|
height: var(--cell-size);
|
|
background: var(--cell-bg);
|
|
border: 2px outset var(--cell-border);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: bold;
|
|
font-size: 1.1em;
|
|
cursor: pointer;
|
|
transition: background-color 0.1s;
|
|
}
|
|
|
|
.cell.revealed {
|
|
background: var(--cell-revealed);
|
|
border: 1px solid var(--cell-border);
|
|
}
|
|
|
|
.cell.flagged::before {
|
|
content: "🚩";
|
|
}
|
|
|
|
.cell.mine-clicked {
|
|
background: red;
|
|
}
|
|
|
|
.cell.mine::before {
|
|
content: "💣";
|
|
}
|
|
|
|
.cell.number-1 { color: blue; }
|
|
.cell.number-2 { color: green; }
|
|
.cell.number-3 { color: red; }
|
|
.cell.number-4 { color: darkblue; }
|
|
.cell.number-5 { color: brown; }
|
|
.cell.number-6 { color: teal; }
|
|
.cell.number-7 { color: black; }
|
|
.cell.number-8 { color: gray; }
|
|
|
|
.instructions {
|
|
margin: 20px auto;
|
|
max-width: 600px;
|
|
text-align: left;
|
|
padding: 15px;
|
|
background: rgba(255, 255, 255, 0.8);
|
|
border-radius: 10px;
|
|
box-shadow: 0 2px 5px var(--shadow-color);
|
|
}
|
|
|
|
.dark-mode .instructions {
|
|
background: rgba(45, 45, 45, 0.8);
|
|
}
|
|
|
|
footer {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
padding: 15px;
|
|
text-align: center;
|
|
font-size: 0.9em;
|
|
background: var(--footer-color);
|
|
backdrop-filter: blur(5px);
|
|
z-index: 10;
|
|
}
|
|
|
|
footer a {
|
|
color: var(--primary-color);
|
|
text-decoration: none;
|
|
font-weight: 500;
|
|
transition: opacity 0.3s ease;
|
|
}
|
|
|
|
footer a:hover {
|
|
opacity: 0.8;
|
|
text-decoration: underline;
|
|
}
|
|
|
|
@media (max-width: 600px) {
|
|
:root {
|
|
--cell-size: 25px;
|
|
}
|
|
|
|
.game-container {
|
|
padding: 10px;
|
|
}
|
|
|
|
.counter {
|
|
font-size: 1.2em;
|
|
min-width: 60px;
|
|
}
|
|
|
|
.smiley {
|
|
width: 35px;
|
|
height: 35px;
|
|
}
|
|
|
|
.difficulty button {
|
|
padding: 6px 10px;
|
|
font-size: 0.9em;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 400px) {
|
|
:root {
|
|
--cell-size: 20px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<button class="theme-toggle" onclick="toggleTheme()">🌙</button>
|
|
|
|
<h1>Minesweeper</h1>
|
|
|
|
<div class="game-container">
|
|
<div class="game-header">
|
|
<div class="counter" id="mines-counter">000</div>
|
|
<div class="smiley" id="smiley">😊</div>
|
|
<div class="counter" id="timer">000</div>
|
|
</div>
|
|
|
|
<div class="difficulty">
|
|
<button data-level="beginner" class="active">Anfänger (9x9)</button>
|
|
<button data-level="intermediate">Fortgeschritten (16x16)</button>
|
|
<button data-level="expert">Experte (30x16)</button>
|
|
</div>
|
|
|
|
<div class="minesweeper-board" id="board"></div>
|
|
</div>
|
|
|
|
<div class="instructions">
|
|
<h3>Anleitung:</h3>
|
|
<p><strong>Ziel des Spiels:</strong> Finde alle Minen auf dem Spielfeld, ohne eine zu aktivieren.</p>
|
|
<p><strong>Steuerung:</strong></p>
|
|
<ul>
|
|
<li><strong>Linksklick:</strong> Feld aufdecken</li>
|
|
<li><strong>Rechtsklick:</strong> Flagge setzen/entfernen</li>
|
|
<li><strong>Doppelklick auf aufgedecktes Feld:</strong> Umgebende Felder aufdecken, wenn entsprechende Anzahl Flaggen gesetzt ist</li>
|
|
</ul>
|
|
<p><strong>Zahlen:</strong> Zeigen an, wie viele Minen in den umliegenden 8 Feldern versteckt sind.</p>
|
|
</div>
|
|
|
|
<footer>
|
|
<div>
|
|
<a href="https://tools.ponywave.de/">Zurück zur Startseite</a> |
|
|
© <span id="currentYear"></span> Akamaru |
|
|
Made with ❤️ by Claude
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
// Spielkonfiguration
|
|
const levels = {
|
|
beginner: { rows: 9, cols: 9, mines: 10 },
|
|
intermediate: { rows: 16, cols: 16, mines: 40 },
|
|
expert: { rows: 16, cols: 30, mines: 99 }
|
|
};
|
|
|
|
let currentLevel = 'beginner';
|
|
let boardData = [];
|
|
let gameOver = false;
|
|
let gameStarted = false;
|
|
let timeInterval;
|
|
let startTime;
|
|
let flagCount = 0;
|
|
|
|
// DOM-Elemente
|
|
const board = document.getElementById('board');
|
|
const smiley = document.getElementById('smiley');
|
|
const minesCounter = document.getElementById('mines-counter');
|
|
const timerElement = document.getElementById('timer');
|
|
const difficultyButtons = document.querySelectorAll('.difficulty button');
|
|
|
|
// Event-Listener
|
|
difficultyButtons.forEach(button => {
|
|
button.addEventListener('click', (e) => {
|
|
currentLevel = e.target.dataset.level;
|
|
difficultyButtons.forEach(btn => btn.classList.remove('active'));
|
|
e.target.classList.add('active');
|
|
initGame();
|
|
});
|
|
});
|
|
|
|
smiley.addEventListener('click', initGame);
|
|
|
|
// Initialisieren des Spiels
|
|
function initGame() {
|
|
clearInterval(timeInterval);
|
|
gameOver = false;
|
|
gameStarted = false;
|
|
flagCount = 0;
|
|
smiley.textContent = '😊';
|
|
timerElement.textContent = '000';
|
|
|
|
const { rows, cols, mines } = levels[currentLevel];
|
|
|
|
// Brett erstellen
|
|
board.style.gridTemplateColumns = `repeat(${cols}, var(--cell-size))`;
|
|
board.style.gridTemplateRows = `repeat(${rows}, var(--cell-size))`;
|
|
board.innerHTML = '';
|
|
|
|
// Zellengröße anpassen im Experten-Modus
|
|
if (currentLevel === 'expert') {
|
|
const gameContainer = document.querySelector('.game-container');
|
|
const containerWidth = gameContainer.clientWidth - 40; // Container-Breite abzüglich Padding
|
|
const cellSize = Math.max(15, Math.floor(containerWidth / cols)); // Minimalgröße 15px
|
|
document.documentElement.style.setProperty('--cell-size', `${cellSize}px`);
|
|
} else {
|
|
// Zurücksetzen auf Standardwert für andere Modi
|
|
document.documentElement.style.setProperty('--cell-size', '30px');
|
|
}
|
|
|
|
// Minen-Counter aktualisieren
|
|
updateMinesCounter(mines);
|
|
|
|
// Spielbrett-Daten initialisieren
|
|
boardData = Array(rows).fill().map(() =>
|
|
Array(cols).fill().map(() => ({
|
|
isMine: false,
|
|
isRevealed: false,
|
|
isFlagged: false,
|
|
neighborMines: 0
|
|
}))
|
|
);
|
|
|
|
// Zellen erstellen
|
|
for (let row = 0; row < rows; row++) {
|
|
for (let col = 0; col < cols; col++) {
|
|
const cell = document.createElement('div');
|
|
cell.className = 'cell';
|
|
cell.dataset.row = row;
|
|
cell.dataset.col = col;
|
|
|
|
cell.addEventListener('click', handleCellClick);
|
|
cell.addEventListener('contextmenu', handleRightClick);
|
|
cell.addEventListener('dblclick', handleDoubleClick);
|
|
|
|
board.appendChild(cell);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Minen platzieren
|
|
function placeMines(firstClickRow, firstClickCol) {
|
|
const { rows, cols, mines } = levels[currentLevel];
|
|
let minesPlaced = 0;
|
|
|
|
while (minesPlaced < mines) {
|
|
const row = Math.floor(Math.random() * rows);
|
|
const col = Math.floor(Math.random() * cols);
|
|
|
|
// Nicht auf die erste Klick-Position oder wo bereits eine Mine ist
|
|
if ((row !== firstClickRow || col !== firstClickCol) && !boardData[row][col].isMine) {
|
|
boardData[row][col].isMine = true;
|
|
minesPlaced++;
|
|
}
|
|
}
|
|
|
|
// Nachbarn-Minen-Zähler berechnen
|
|
for (let row = 0; row < rows; row++) {
|
|
for (let col = 0; col < cols; col++) {
|
|
if (!boardData[row][col].isMine) {
|
|
boardData[row][col].neighborMines = countNeighborMines(row, col);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Nachbarn-Minen zählen
|
|
function countNeighborMines(row, col) {
|
|
const { rows, cols } = levels[currentLevel];
|
|
let count = 0;
|
|
|
|
for (let r = Math.max(0, row - 1); r <= Math.min(rows - 1, row + 1); r++) {
|
|
for (let c = Math.max(0, col - 1); c <= Math.min(cols - 1, col + 1); c++) {
|
|
if ((r !== row || c !== col) && boardData[r][c].isMine) {
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
// Zellen-Klick behandeln
|
|
function handleCellClick(e) {
|
|
if (gameOver) return;
|
|
|
|
const row = parseInt(e.target.dataset.row);
|
|
const col = parseInt(e.target.dataset.col);
|
|
|
|
// Erster Klick initialisiert das Spiel
|
|
if (!gameStarted) {
|
|
gameStarted = true;
|
|
startTimer();
|
|
placeMines(row, col);
|
|
}
|
|
|
|
// Nicht auf eine Flagge klicken
|
|
if (boardData[row][col].isFlagged) return;
|
|
|
|
// Bei Minen-Klick Game Over
|
|
if (boardData[row][col].isMine) {
|
|
revealMines();
|
|
gameOver = true;
|
|
clearInterval(timeInterval);
|
|
smiley.textContent = '😵';
|
|
e.target.classList.add('mine-clicked');
|
|
return;
|
|
}
|
|
|
|
// Zelle aufdecken
|
|
revealCell(row, col);
|
|
|
|
// Prüfen auf Sieg
|
|
checkWin();
|
|
}
|
|
|
|
// Rechtsklick behandeln (Flagge setzen)
|
|
function handleRightClick(e) {
|
|
e.preventDefault();
|
|
if (gameOver || !gameStarted) return;
|
|
|
|
const row = parseInt(e.target.dataset.row);
|
|
const col = parseInt(e.target.dataset.col);
|
|
|
|
// Nur nicht aufgedeckte Zellen flaggen
|
|
if (boardData[row][col].isRevealed) return;
|
|
|
|
const cell = e.target;
|
|
|
|
if (boardData[row][col].isFlagged) {
|
|
// Flagge entfernen
|
|
boardData[row][col].isFlagged = false;
|
|
cell.classList.remove('flagged');
|
|
flagCount--;
|
|
} else {
|
|
// Flagge setzen
|
|
boardData[row][col].isFlagged = true;
|
|
cell.classList.add('flagged');
|
|
flagCount++;
|
|
}
|
|
|
|
// Minen-Counter aktualisieren
|
|
updateMinesCounter(levels[currentLevel].mines - flagCount);
|
|
}
|
|
|
|
// Doppelklick behandeln (Nachbarn aufdecken)
|
|
function handleDoubleClick(e) {
|
|
if (gameOver || !gameStarted) return;
|
|
|
|
const row = parseInt(e.target.dataset.row);
|
|
const col = parseInt(e.target.dataset.col);
|
|
|
|
// Nur für aufgedeckte Zellen mit Zahlen
|
|
if (!boardData[row][col].isRevealed || boardData[row][col].neighborMines === 0) return;
|
|
|
|
const { rows, cols } = levels[currentLevel];
|
|
let flagCount = 0;
|
|
|
|
// Zählen der Flaggen in der Umgebung
|
|
for (let r = Math.max(0, row - 1); r <= Math.min(rows - 1, row + 1); r++) {
|
|
for (let c = Math.max(0, col - 1); c <= Math.min(cols - 1, col + 1); c++) {
|
|
if (boardData[r][c].isFlagged) {
|
|
flagCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Wenn die Anzahl der Flaggen mit der Zahl übereinstimmt, Nachbarn aufdecken
|
|
if (flagCount === boardData[row][col].neighborMines) {
|
|
for (let r = Math.max(0, row - 1); r <= Math.min(rows - 1, row + 1); r++) {
|
|
for (let c = Math.max(0, col - 1); c <= Math.min(cols - 1, col + 1); c++) {
|
|
if (!boardData[r][c].isRevealed && !boardData[r][c].isFlagged) {
|
|
// Simuliere einen Klick auf die Zelle
|
|
const cellElement = document.querySelector(`.cell[data-row="${r}"][data-col="${c}"]`);
|
|
if (cellElement) {
|
|
cellElement.click();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Zelle aufdecken
|
|
function revealCell(row, col) {
|
|
const { rows, cols } = levels[currentLevel];
|
|
|
|
// Bereits aufgedeckt oder geflaggt überspringen
|
|
if (boardData[row][col].isRevealed || boardData[row][col].isFlagged) return;
|
|
|
|
// Zelle als aufgedeckt markieren
|
|
boardData[row][col].isRevealed = true;
|
|
|
|
// DOM aktualisieren
|
|
const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
|
|
cell.classList.add('revealed');
|
|
|
|
// Nachbarn-Anzahl anzeigen wenn > 0
|
|
if (boardData[row][col].neighborMines > 0) {
|
|
cell.textContent = boardData[row][col].neighborMines;
|
|
cell.classList.add(`number-${boardData[row][col].neighborMines}`);
|
|
} else {
|
|
// Bei 0 Nachbarn automatisch alle angrenzenden Zellen aufdecken
|
|
for (let r = Math.max(0, row - 1); r <= Math.min(rows - 1, row + 1); r++) {
|
|
for (let c = Math.max(0, col - 1); c <= Math.min(cols - 1, col + 1); c++) {
|
|
if (r !== row || c !== col) {
|
|
revealCell(r, c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Alle Minen aufdecken (bei Game Over)
|
|
function revealMines() {
|
|
const { rows, cols } = levels[currentLevel];
|
|
|
|
for (let row = 0; row < rows; row++) {
|
|
for (let col = 0; col < cols; col++) {
|
|
if (boardData[row][col].isMine) {
|
|
const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
|
|
cell.classList.add('revealed', 'mine');
|
|
} else if (boardData[row][col].isFlagged) {
|
|
// Falsch platzierte Flaggen markieren
|
|
const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
|
|
cell.classList.add('revealed');
|
|
cell.classList.add('wrong-flag');
|
|
cell.textContent = '❌';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Prüfen, ob das Spiel gewonnen wurde
|
|
function checkWin() {
|
|
const { rows, cols, mines } = levels[currentLevel];
|
|
let revealedCount = 0;
|
|
|
|
for (let row = 0; row < rows; row++) {
|
|
for (let col = 0; col < cols; col++) {
|
|
if (boardData[row][col].isRevealed) {
|
|
revealedCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Gewonnen, wenn alle Nicht-Minen-Zellen aufgedeckt sind
|
|
if (revealedCount === (rows * cols - mines)) {
|
|
gameOver = true;
|
|
clearInterval(timeInterval);
|
|
smiley.textContent = '😎';
|
|
|
|
// Alle Minen automatisch flaggen
|
|
for (let row = 0; row < rows; row++) {
|
|
for (let col = 0; col < cols; col++) {
|
|
if (boardData[row][col].isMine && !boardData[row][col].isFlagged) {
|
|
boardData[row][col].isFlagged = true;
|
|
const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
|
|
cell.classList.add('flagged');
|
|
}
|
|
}
|
|
}
|
|
|
|
// Minen-Counter auf 0 setzen
|
|
updateMinesCounter(0);
|
|
}
|
|
}
|
|
|
|
// Timer starten
|
|
function startTimer() {
|
|
startTime = Date.now();
|
|
timeInterval = setInterval(() => {
|
|
const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000);
|
|
// Maximale Anzeige: 999 Sekunden
|
|
const displayTime = Math.min(elapsedSeconds, 999);
|
|
timerElement.textContent = displayTime.toString().padStart(3, '0');
|
|
}, 1000);
|
|
}
|
|
|
|
// Minen-Counter aktualisieren
|
|
function updateMinesCounter(count) {
|
|
minesCounter.textContent = count.toString().padStart(3, '0');
|
|
}
|
|
|
|
// Dark Mode
|
|
function toggleTheme() {
|
|
document.body.classList.toggle('dark-mode');
|
|
const btn = document.querySelector('.theme-toggle');
|
|
btn.textContent = document.body.classList.contains('dark-mode') ? '☀️' : '🌙';
|
|
|
|
// Speichern der Präferenz
|
|
const isDark = document.body.classList.contains('dark-mode');
|
|
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
|
}
|
|
|
|
// Theme initialisieren
|
|
function initTheme() {
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
const savedTheme = localStorage.getItem('theme');
|
|
|
|
if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
|
|
document.body.classList.add('dark-mode');
|
|
document.querySelector('.theme-toggle').textContent = '☀️';
|
|
}
|
|
|
|
// Jahr aktualisieren
|
|
document.getElementById('currentYear').textContent = new Date().getFullYear();
|
|
}
|
|
|
|
// Kontextmenü für rechte Maustaste verhindern
|
|
board.addEventListener('contextmenu', e => e.preventDefault());
|
|
|
|
// Beim Laden ausführen
|
|
initTheme();
|
|
initGame();
|
|
|
|
// Bei Resize Fenster die Zellengröße anpassen
|
|
window.addEventListener('resize', () => {
|
|
if (currentLevel === 'expert') {
|
|
const gameContainer = document.querySelector('.game-container');
|
|
const containerWidth = gameContainer.clientWidth - 40;
|
|
const cellSize = Math.max(15, Math.floor(containerWidth / levels.expert.cols)); // Minimalgröße 15px
|
|
document.documentElement.style.setProperty('--cell-size', `${cellSize}px`);
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |