Neu: Minesweeper
This commit is contained in:
parent
b5bac3f7d8
commit
477bac5f8c
@ -263,6 +263,10 @@
|
||||
<h2 class="tool-title">Banana Runner</h2>
|
||||
<p class="tool-description">Endlos-Runner Spiel mit einer springenden Banane.</p>
|
||||
</a>
|
||||
<a href="https://tools.ponywave.de/minesweeper/" class="tool-bubble">
|
||||
<h2 class="tool-title">Minesweeper</h2>
|
||||
<p class="tool-description">Klassisches Minesweeper mit verschiedenen Schwierigkeitsgraden.</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
BIN
minesweeper/icon.png
Normal file
BIN
minesweeper/icon.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 92 KiB |
726
minesweeper/index.html
Normal file
726
minesweeper/index.html
Normal file
@ -0,0 +1,726 @@
|
||||
<!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>
|
@ -23,4 +23,5 @@ https://tools.ponywave.de/emoji
|
||||
https://tools.ponywave.de/banana_run
|
||||
https://tools.ponywave.de/pokemon_quiz
|
||||
https://tools.ponywave.de/gronkh_games
|
||||
https://tools.ponywave.de/url_expander/
|
||||
https://tools.ponywave.de/url_expander/
|
||||
https://tools.ponywave.de/minesweeper/
|
Loading…
x
Reference in New Issue
Block a user