Initial commit - Kinderspiele

This commit is contained in:
OpenClaw
2026-04-26 09:44:19 +02:00
commit 35817527c8
29 changed files with 10949 additions and 0 deletions
+305
View File
@@ -0,0 +1,305 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Puzzle - KinderWelt</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; user-select: none; }
body {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
min-height: 100vh; display: flex; flex-direction: column; align-items: center;
font-family: 'Comic Sans MS', cursive, sans-serif; padding: 10px;
}
h1 { color: white; margin-bottom: 10px; font-size: 24px; }
.level-select { display: flex; gap: 10px; margin-bottom: 15px; }
.level-btn {
background: rgba(255,255,255,0.2); border: 2px solid white; border-radius: 10px;
padding: 8px 15px; color: white; font-size: 14px; cursor: pointer; font-family: inherit;
}
.level-btn.active { background: white; color: #f5576c; }
.image-select { display: flex; gap: 10px; margin-bottom: 15px; flex-wrap: wrap; justify-content: center; }
.img-btn {
background: white; border: 3px solid transparent; border-radius: 10px;
padding: 5px; cursor: pointer; font-size: 30px;
}
.img-btn.active { border-color: #4ade80; }
.puzzle-container {
display: grid; gap: 2px; background: rgba(0,0,0,0.2); padding: 5px;
border-radius: 10px; touch-action: none;
}
.puzzle-piece {
background-size: 300px 300px; cursor: pointer; border-radius: 5px;
transition: all 0.2s; position: relative;
}
.puzzle-piece:hover { transform: scale(1.02); }
.puzzle-piece.selected { box-shadow: 0 0 10px #4ade80; z-index: 10; }
.puzzle-piece.correct {
animation: pulse 0.5s;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.preview {
background: white; border-radius: 10px; padding: 10px; margin: 10px 0;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.preview-img { font-size: 80px; }
.controls { display: flex; gap: 15px; margin-top: 15px; flex-wrap: wrap; justify-content: center; }
.btn {
background: white; border: none; border-radius: 10px; padding: 12px 25px;
font-size: 16px; cursor: pointer; font-family: inherit; font-weight: bold;
}
.btn-back { background: #ff6b6b; color: white; text-decoration: none; }
.status { color: white; font-size: 18px; margin: 10px 0; }
</style>
</head>
<body>
<h1>🧩 Puzzle</h1>
<div class="level-select">
<button class="level-btn" onclick="setLevel(2)" id="l2">2×2 (Leicht)</button>
<button class="level-btn active" onclick="setLevel(3)" id="l3">3×3 (Mittel)</button>
<button class="level-btn" onclick="setLevel(4)" id="l4">4×4 (Schwer)</button>
</div>
<div class="image-select" id="imageSelect"></div>
<div class="preview">
<div class="preview-img" id="previewImg">🐶</div>
<p style="color:#666;font-size:12px">So soll es aussehen!</p>
</div>
<div class="status" id="status">Klicke zwei Teile zum Tauschen!</div>
<div class="puzzle-container" id="puzzleContainer"></div>
<div class="controls">
<button class="btn" onclick="shufflePuzzle()">🔀 Mischen</button>
<button class="btn" onclick="showHint()">💡 Tipp</button>
<a href="../index.html" class="btn btn-back">⬅️ Zurück</a>
</div>
<script>
const emojis = ['🐶','🐱','🐭','🐹','🐰','🦊','🐻','🐼','🐨','🐯','🦁','🐷','🐸','🐵','🐔'];
let gridSize = 3;
let selectedPiece = null;
let pieces = [];
let currentEmoji = '🐶';
let solved = false;
function init() {
// Bildauswahl
const imgSelect = document.getElementById('imageSelect');
emojis.slice(0, 8).forEach((emoji, i) => {
const btn = document.createElement('button');
btn.className = 'img-btn' + (i === 0 ? ' active' : '');
btn.textContent = emoji;
btn.onclick = () => selectImage(emoji, btn);
imgSelect.appendChild(btn);
});
createPuzzle();
}
function setLevel(n) {
gridSize = n;
document.querySelectorAll('.level-btn').forEach(b => b.classList.remove('active'));
document.getElementById('l' + n).classList.add('active');
createPuzzle();
}
function selectImage(emoji, btn) {
currentEmoji = emoji;
document.getElementById('previewImg').textContent = emoji;
document.querySelectorAll('.img-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
createPuzzle();
}
function createPuzzle() {
const container = document.getElementById('puzzleContainer');
container.innerHTML = '';
container.style.gridTemplateColumns = `repeat(${gridSize}, 80px)`;
pieces = [];
const totalPieces = gridSize * gridSize;
// Canvas für Emoji-Bild
const canvas = document.createElement('canvas');
canvas.width = 300;
canvas.height = 300;
const ctx = canvas.getContext('2d');
// Emoji zeichnen
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, 300, 300);
ctx.font = '200px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(currentEmoji, 150, 150);
const imageData = canvas.toDataURL();
// Teile erstellen
for (let i = 0; i < totalPieces; i++) {
const correctPos = i;
const piece = {
id: i,
correctPos: correctPos,
currentPos: i
};
pieces.push(piece);
}
// Rendern
renderPuzzle(imageData);
// Kurz warten dann mischen
setTimeout(shufflePuzzle, 500);
}
function renderPuzzle(imageData) {
const container = document.getElementById('puzzleContainer');
container.innerHTML = '';
const pieceSize = 80;
// Nach currentPos sortieren für Anzeige
const displayPieces = [...pieces].sort((a, b) => a.currentPos - b.currentPos);
displayPieces.forEach((piece, index) => {
const div = document.createElement('div');
div.className = 'puzzle-piece';
div.style.width = pieceSize + 'px';
div.style.height = pieceSize + 'px';
div.style.backgroundImage = `url(${imageData})`;
// Hintergrund-Position basierend auf correctPos
const row = Math.floor(piece.correctPos / gridSize);
const col = piece.correctPos % gridSize;
div.style.backgroundPosition = `-${col * pieceSize}px -${row * pieceSize}px`;
div.style.backgroundSize = `${gridSize * pieceSize}px ${gridSize * pieceSize}px`;
div.onclick = () => selectPiece(piece);
container.appendChild(div);
});
checkWin();
}
function selectPiece(piece) {
if (solved) return;
const container = document.getElementById('puzzleContainer');
const divs = container.querySelectorAll('.puzzle-piece');
// Index in display order finden
const displayIndex = pieces.findIndex(p => p.id === piece.id);
if (!selectedPiece) {
selectedPiece = piece;
divs[displayIndex].classList.add('selected');
document.getElementById('status').textContent = 'Wähle ein anderes Teil zum Tauschen!';
} else if (selectedPiece.id === piece.id) {
// Gleiches Teil = abwählen
selectedPiece = null;
divs[displayIndex].classList.remove('selected');
document.getElementById('status').textContent = 'Klicke zwei Teile zum Tauschen!';
} else {
// Tauschen
const tempPos = selectedPiece.currentPos;
selectedPiece.currentPos = piece.currentPos;
piece.currentPos = tempPos;
selectedPiece = null;
// Neu rendern
const canvas = document.createElement('canvas');
canvas.width = 300; canvas.height = 300;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, 300, 300);
ctx.font = '200px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(currentEmoji, 150, 150);
renderPuzzle(canvas.toDataURL());
}
}
function shufflePuzzle() {
if (solved) solved = false;
// Fisher-Yates Shuffle für currentPos
for (let i = pieces.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const temp = pieces[i].currentPos;
pieces[i].currentPos = pieces[j].currentPos;
pieces[j].currentPos = temp;
}
// Neu rendern
const canvas = document.createElement('canvas');
canvas.width = 300; canvas.height = 300;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, 300, 300);
ctx.font = '200px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(currentEmoji, 150, 150);
renderPuzzle(canvas.toDataURL());
document.getElementById('status').textContent = 'Klicke zwei Teile zum Tauschen!';
}
function checkWin() {
const isSolved = pieces.every(p => p.currentPos === p.correctPos);
if (isSolved && !solved) {
solved = true;
document.getElementById('status').textContent = '🎉 Super! Puzzle gelöst!';
// Alle Teile grün blinken
const divs = document.querySelectorAll('.puzzle-piece');
divs.forEach(div => {
div.style.boxShadow = '0 0 20px #4ade80';
});
if ('speechSynthesis' in window) {
const utterance = new SpeechSynthesisUtterance('Super! Du hast das Puzzle gelöst!');
utterance.lang = 'de-DE';
speechSynthesis.speak(utterance);
}
}
}
function showHint() {
// Zeige für 2 Sekunden die richtige Position an
const container = document.getElementById('puzzleContainer');
const divs = container.querySelectorAll('.puzzle-piece');
divs.forEach((div, index) => {
const piece = pieces.find(p => p.currentPos === index);
if (piece && piece.correctPos === index) {
div.style.boxShadow = '0 0 10px #4ade80';
}
});
setTimeout(() => {
divs.forEach(div => {
div.style.boxShadow = '';
});
}, 2000);
document.getElementById('status').textContent = '💡 Grün markierte Teile sind richtig!';
}
// Init
init();
</script>
</body>
</html>