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; + } +}