commit 0c4c999637ea932eded405097c826333b0672164
Author: root <root@hub.scroll.pub>
Date: 2024-12-28 20:48:15 +0000
Subject: Initial commit
diff --git a/body.html b/body.html
new file mode 100644
index 0000000..168b170
--- /dev/null
+++ b/body.html
@@ -0,0 +1,22 @@
+<main class="container">
+ <h1>Classic 9-Puzzle</h1>
+ <div class="game-controls">
+ <button id="resetGame" aria-label="Reset Game">New Game</button>
+ <span id="moveCounter">Moves: 0</span>
+ </div>
+ <div class="puzzle-container" id="puzzleGrid">
+ <div class="puzzle-piece" data-index="1">1</div>
+ <div class="puzzle-piece" data-index="2">2</div>
+ <div class="puzzle-piece" data-index="3">3</div>
+ <div class="puzzle-piece" data-index="4">4</div>
+ <div class="puzzle-piece" data-index="5">5</div>
+ <div class="puzzle-piece" data-index="6">6</div>
+ <div class="puzzle-piece" data-index="7">7</div>
+ <div class="puzzle-piece" data-index="8">8</div>
+ <div class="puzzle-piece empty" data-index="9"></div>
+ </div>
+ <div id="winMessage" class="win-message hidden">
+ <h2>Congratulations!</h2>
+ <p>You solved the puzzle!</p>
+ </div>
+</main>
diff --git a/index.scroll b/index.scroll
new file mode 100644
index 0000000..2910443
--- /dev/null
+++ b/index.scroll
@@ -0,0 +1,8 @@
+buildHtml
+baseUrl https://puzzle9.scroll.pub
+metaTags
+editButton /edit.html
+title Classic 9-Puzzle Game
+style.css
+body.html
+script.js
diff --git a/prompt.json b/prompt.json
new file mode 100644
index 0000000..76b316a
--- /dev/null
+++ b/prompt.json
@@ -0,0 +1,20 @@
+{
+ "id": "msg_016ZnK3Tj32ekX1KkTDihGq6",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-3-5-sonnet-20241022",
+ "content": [
+ {
+ "type": "text",
+ "text": "---domain---\npuzzle9.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://puzzle9.scroll.pub\nmetaTags\neditButton /edit.html\ntitle Classic 9-Puzzle Game\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<main class=\"container\">\n <h1>Classic 9-Puzzle</h1>\n <div class=\"game-controls\">\n <button id=\"resetGame\" aria-label=\"Reset Game\">New Game</button>\n <span id=\"moveCounter\">Moves: 0</span>\n </div>\n <div class=\"puzzle-container\" id=\"puzzleGrid\">\n <div class=\"puzzle-piece\" data-index=\"1\">1</div>\n <div class=\"puzzle-piece\" data-index=\"2\">2</div>\n <div class=\"puzzle-piece\" data-index=\"3\">3</div>\n <div class=\"puzzle-piece\" data-index=\"4\">4</div>\n <div class=\"puzzle-piece\" data-index=\"5\">5</div>\n <div class=\"puzzle-piece\" data-index=\"6\">6</div>\n <div class=\"puzzle-piece\" data-index=\"7\">7</div>\n <div class=\"puzzle-piece\" data-index=\"8\">8</div>\n <div class=\"puzzle-piece empty\" data-index=\"9\"></div>\n </div>\n <div id=\"winMessage\" class=\"win-message hidden\">\n <h2>Congratulations!</h2>\n <p>You solved the puzzle!</p>\n </div>\n</main>\n\n---style.css---\n:root {\n --primary-color: hsl(210, 80%, 50%);\n --secondary-color: hsl(240, 80%, 60%);\n --background-color: hsl(220, 20%, 95%);\n --text-color: hsl(220, 20%, 20%);\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: 'Segoe UI', system-ui, sans-serif;\n background: var(--background-color);\n color: var(--text-color);\n min-height: 100vh;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n.container {\n text-align: center;\n padding: 2rem;\n}\n\nh1 {\n font-size: 2.5rem;\n margin-bottom: 2rem;\n background: linear-gradient(var(--primary-color), var(--secondary-color));\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n}\n\n.game-controls {\n margin-bottom: 2rem;\n display: flex;\n justify-content: center;\n gap: 2rem;\n align-items: center;\n}\n\n#resetGame {\n padding: 0.8rem 1.5rem;\n font-size: 1rem;\n border: none;\n border-radius: 25px;\n background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n color: white;\n cursor: pointer;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n#resetGame:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0,0,0,0.2);\n}\n\n.puzzle-container {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 0.5rem;\n width: min(90vw, 400px);\n margin: 0 auto;\n padding: 0.5rem;\n background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n border-radius: 1rem;\n}\n\n.puzzle-piece {\n aspect-ratio: 1;\n display: flex;\n justify-content: center;\n align-items: center;\n font-size: 2rem;\n font-weight: bold;\n background: white;\n border-radius: 0.5rem;\n cursor: pointer;\n transition: transform 0.3s ease;\n user-select: none;\n}\n\n.puzzle-piece:not(.empty):hover {\n transform: scale(1.05);\n}\n\n.empty {\n background: transparent;\n cursor: default;\n}\n\n.win-message {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: white;\n padding: 2rem;\n border-radius: 1rem;\n box-shadow: 0 0 20px rgba(0,0,0,0.2);\n z-index: 10;\n}\n\n.hidden {\n display: none;\n}\n\n@media (max-width: 480px) {\n .container {\n padding: 1rem;\n }\n \n h1 {\n font-size: 2rem;\n }\n \n .puzzle-piece {\n font-size: 1.5rem;\n }\n}\n\n---script.js---\nclass PuzzleGame {\n constructor() {\n this.moves = 0;\n this.grid = document.getElementById('puzzleGrid');\n this.pieces = Array.from(document.querySelectorAll('.puzzle-piece'));\n this.emptyPiece = document.querySelector('.empty');\n this.moveCounter = document.getElementById('moveCounter');\n this.winMessage = document.getElementById('winMessage');\n this.resetButton = document.getElementById('resetGame');\n \n this.initializeGame();\n }\n\n initializeGame() {\n this.resetButton.addEventListener('click', () => this.resetGame());\n this.grid.addEventListener('click', (e) => this.handlePieceClick(e));\n this.randomizeBoard();\n }\n\n handlePieceClick(e) {\n const piece = e.target.closest('.puzzle-piece');\n if (!piece || piece.classList.contains('empty')) return;\n \n if (this.isMovable(piece)) {\n this.movePiece(piece);\n this.moves++;\n this.moveCounter.textContent = `Moves: ${this.moves}`;\n \n if (this.checkWin()) {\n this.showWinMessage();\n }\n }\n }\n\n isMovable(piece) {\n const emptyIndex = Array.from(this.grid.children).indexOf(this.emptyPiece);\n const pieceIndex = Array.from(this.grid.children).indexOf(piece);\n \n const row1 = Math.floor(emptyIndex / 3);\n const col1 = emptyIndex % 3;\n const row2 = Math.floor(pieceIndex / 3);\n const col2 = pieceIndex % 3;\n \n return Math.abs(row1 - row2) + Math.abs(col1 - col2) === 1;\n }\n\n movePiece(piece) {\n const emptyRect = this.emptyPiece.getBoundingClientRect();\n const pieceRect = piece.getBoundingClientRect();\n \n const parent = piece.parentNode;\n const placeholder = document.createElement('div');\n parent.insertBefore(placeholder, this.emptyPiece);\n parent.insertBefore(this.emptyPiece, piece);\n parent.insertBefore(piece, placeholder);\n parent.removeChild(placeholder);\n }\n\n randomizeBoard() {\n let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];\n numbers = this.shuffle(numbers);\n \n this.pieces.forEach((piece, index) => {\n piece.dataset.index = numbers[index];\n if (numbers[index] === 9) {\n piece.classList.add('empty');\n piece.textContent = '';\n } else {\n piece.classList.remove('empty');\n piece.textContent = numbers[index];\n }\n });\n \n this.moves = 0;\n this.moveCounter.textContent = 'Moves: 0';\n this.winMessage.classList.add('hidden');\n }\n\n shuffle(array) {\n let currentIndex = array.length;\n while (currentIndex !== 0) {\n const randomIndex = Math.floor(Math.random() * currentIndex);\n currentIndex--;\n [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];\n }\n return array;\n }\n\n checkWin() {\n return this.pieces.every((piece, index) => {\n return piece.dataset.index == index + 1;\n });\n }\n\n showWinMessage() {\n this.winMessage.classList.remove('hidden');\n setTimeout(() => {\n this.resetGame();\n }, 3000);\n }\n\n resetGame() {\n this.randomizeBoard();\n }\n}\n\ndocument.addEventListener('DOMContentLoaded', () => {\n new PuzzleGame();\n});\n\n---end---"
+ }
+ ],
+ "stop_reason": "end_turn",
+ "stop_sequence": null,
+ "usage": {
+ "input_tokens": 570,
+ "cache_creation_input_tokens": 0,
+ "cache_read_input_tokens": 0,
+ "output_tokens": 2339
+ }
+}
\ No newline at end of file
diff --git a/readme.scroll b/readme.scroll
new file mode 100644
index 0000000..1c2a79d
--- /dev/null
+++ b/readme.scroll
@@ -0,0 +1,2 @@
+# puzzle91.scroll.pub
+Website generated by Claude from prompt: Design a classic 9-puzzle game using HTML, CSS, and JavaScript. The game should include the following features: 1. **Game Interface**: - Use CSS Grid to create a 3x3 puzzle container. - Each puzzle piece is a div with a background color and a foreground number. - Puzzle pieces should have rounded corners, and the container should have a rounded border. 2. **Game Functionality**: - **Randomize Puzzle**: At the start of the game, the puzzle pieces should be randomized with one empty spot. - **Piece Movement Logic**: When a movable puzzle piece (adjacent to the empty spot) is clicked, it should swap places with the empty spot. - **Win Condition Check**: When the pieces are in the correct order, display a victory message. - **Reset Game Button**: When clicked, it should randomize the puzzle again. 3. **Visual Enhancements**: - Use HSL color values to create a gradient effect for the puzzle pieces. - Provide multiple color themes and randomly select one for each game session. - Ensure smooth transitions when pieces are moved. 4. **User Experience**: - Prevent puzzle pieces from being selected or dragged. - Display a celebration message upon winning and disable further moves. Please generate the complete HTML code, including the necessary CSS styles and JavaScript logic.
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..db07f61
--- /dev/null
+++ b/script.js
@@ -0,0 +1,109 @@
+class PuzzleGame {
+ constructor() {
+ this.moves = 0;
+ this.grid = document.getElementById('puzzleGrid');
+ this.pieces = Array.from(document.querySelectorAll('.puzzle-piece'));
+ this.emptyPiece = document.querySelector('.empty');
+ this.moveCounter = document.getElementById('moveCounter');
+ this.winMessage = document.getElementById('winMessage');
+ this.resetButton = document.getElementById('resetGame');
+
+ this.initializeGame();
+ }
+
+ initializeGame() {
+ this.resetButton.addEventListener('click', () => this.resetGame());
+ this.grid.addEventListener('click', (e) => this.handlePieceClick(e));
+ this.randomizeBoard();
+ }
+
+ handlePieceClick(e) {
+ const piece = e.target.closest('.puzzle-piece');
+ if (!piece || piece.classList.contains('empty')) return;
+
+ if (this.isMovable(piece)) {
+ this.movePiece(piece);
+ this.moves++;
+ this.moveCounter.textContent = `Moves: ${this.moves}`;
+
+ if (this.checkWin()) {
+ this.showWinMessage();
+ }
+ }
+ }
+
+ isMovable(piece) {
+ const emptyIndex = Array.from(this.grid.children).indexOf(this.emptyPiece);
+ const pieceIndex = Array.from(this.grid.children).indexOf(piece);
+
+ const row1 = Math.floor(emptyIndex / 3);
+ const col1 = emptyIndex % 3;
+ const row2 = Math.floor(pieceIndex / 3);
+ const col2 = pieceIndex % 3;
+
+ return Math.abs(row1 - row2) + Math.abs(col1 - col2) === 1;
+ }
+
+ movePiece(piece) {
+ const emptyRect = this.emptyPiece.getBoundingClientRect();
+ const pieceRect = piece.getBoundingClientRect();
+
+ const parent = piece.parentNode;
+ const placeholder = document.createElement('div');
+ parent.insertBefore(placeholder, this.emptyPiece);
+ parent.insertBefore(this.emptyPiece, piece);
+ parent.insertBefore(piece, placeholder);
+ parent.removeChild(placeholder);
+ }
+
+ randomizeBoard() {
+ let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+ numbers = this.shuffle(numbers);
+
+ this.pieces.forEach((piece, index) => {
+ piece.dataset.index = numbers[index];
+ if (numbers[index] === 9) {
+ piece.classList.add('empty');
+ piece.textContent = '';
+ } else {
+ piece.classList.remove('empty');
+ piece.textContent = numbers[index];
+ }
+ });
+
+ this.moves = 0;
+ this.moveCounter.textContent = 'Moves: 0';
+ this.winMessage.classList.add('hidden');
+ }
+
+ shuffle(array) {
+ let currentIndex = array.length;
+ while (currentIndex !== 0) {
+ const randomIndex = Math.floor(Math.random() * currentIndex);
+ currentIndex--;
+ [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
+ }
+ return array;
+ }
+
+ checkWin() {
+ return this.pieces.every((piece, index) => {
+ return piece.dataset.index == index + 1;
+ });
+ }
+
+ showWinMessage() {
+ this.winMessage.classList.remove('hidden');
+ setTimeout(() => {
+ this.resetGame();
+ }, 3000);
+ }
+
+ resetGame() {
+ this.randomizeBoard();
+ }
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ new PuzzleGame();
+});
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..34dd75c
--- /dev/null
+++ b/style.css
@@ -0,0 +1,124 @@
+:root {
+ --primary-color: hsl(210, 80%, 50%);
+ --secondary-color: hsl(240, 80%, 60%);
+ --background-color: hsl(220, 20%, 95%);
+ --text-color: hsl(220, 20%, 20%);
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: 'Segoe UI', system-ui, sans-serif;
+ background: var(--background-color);
+ color: var(--text-color);
+ min-height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.container {
+ text-align: center;
+ padding: 2rem;
+}
+
+h1 {
+ font-size: 2.5rem;
+ margin-bottom: 2rem;
+ background: linear-gradient(var(--primary-color), var(--secondary-color));
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+}
+
+.game-controls {
+ margin-bottom: 2rem;
+ display: flex;
+ justify-content: center;
+ gap: 2rem;
+ align-items: center;
+}
+
+#resetGame {
+ padding: 0.8rem 1.5rem;
+ font-size: 1rem;
+ border: none;
+ border-radius: 25px;
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
+ color: white;
+ cursor: pointer;
+ transition: transform 0.2s, box-shadow 0.2s;
+}
+
+#resetGame:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
+}
+
+.puzzle-container {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 0.5rem;
+ width: min(90vw, 400px);
+ margin: 0 auto;
+ padding: 0.5rem;
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
+ border-radius: 1rem;
+}
+
+.puzzle-piece {
+ aspect-ratio: 1;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 2rem;
+ font-weight: bold;
+ background: white;
+ border-radius: 0.5rem;
+ cursor: pointer;
+ transition: transform 0.3s ease;
+ user-select: none;
+}
+
+.puzzle-piece:not(.empty):hover {
+ transform: scale(1.05);
+}
+
+.empty {
+ background: transparent;
+ cursor: default;
+}
+
+.win-message {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background: white;
+ padding: 2rem;
+ border-radius: 1rem;
+ box-shadow: 0 0 20px rgba(0,0,0,0.2);
+ z-index: 10;
+}
+
+.hidden {
+ display: none;
+}
+
+@media (max-width: 480px) {
+ .container {
+ padding: 1rem;
+ }
+
+ h1 {
+ font-size: 2rem;
+ }
+
+ .puzzle-piece {
+ font-size: 1.5rem;
+ }
+}