commit dcd807e10480144867e5014058e371c95a642914
Author: root <root@hub.scroll.pub>
Date: 2024-12-29 14:44:33 +0000
Subject: Initial commit
diff --git a/body.html b/body.html
new file mode 100644
index 0000000..6e9c390
--- /dev/null
+++ b/body.html
@@ -0,0 +1,54 @@
+<header>
+ <h1>Word Chain Game</h1>
+ <p class="tagline">Challenge the computer in this English word battle!</p>
+</header>
+
+<main>
+ <div class="game-container">
+ <div class="score-board">
+ <div class="player-score">
+ <h2>You</h2>
+ <span id="playerScore">0</span>
+ </div>
+ <div class="vs">VS</div>
+ <div class="computer-score">
+ <h2>Computer</h2>
+ <span id="computerScore">0</span>
+ </div>
+ </div>
+
+ <div class="game-area">
+ <div id="wordHistory" class="word-history">
+ <h3>Word Chain</h3>
+ <ul id="wordList"></ul>
+ </div>
+
+ <div class="input-area">
+ <label for="playerInput">Enter a word:</label>
+ <input type="text" id="playerInput" placeholder="Type your word here..." autocomplete="off">
+ <button id="submitWord">Submit</button>
+ </div>
+
+ <div id="message" class="message"></div>
+ </div>
+
+ <div class="controls">
+ <button id="newGame" class="new-game">New Game</button>
+ <button id="rules" class="rules">Show Rules</button>
+ </div>
+ </div>
+
+ <dialog id="rulesModal" class="rules-modal">
+ <h2>How to Play</h2>
+ <ol>
+ <li>Enter a valid English word</li>
+ <li>Computer will respond with a word starting with the last letter of your word</li>
+ <li>Continue the chain until someone can't find a valid word</li>
+ </ol>
+ <button id="closeRules">Close</button>
+ </dialog>
+</main>
+
+<footer>
+ <p>Created with 💖 for word game enthusiasts</p>
+</footer>
diff --git a/index.scroll b/index.scroll
new file mode 100644
index 0000000..9541e55
--- /dev/null
+++ b/index.scroll
@@ -0,0 +1,8 @@
+buildHtml
+baseUrl https://wordchain.scroll.pub
+metaTags
+editButton /edit.html
+title Word Chain Game - English Word Battle
+style.css
+body.html
+script.js
diff --git a/prompt.json b/prompt.json
new file mode 100644
index 0000000..bdf083c
--- /dev/null
+++ b/prompt.json
@@ -0,0 +1,20 @@
+{
+ "id": "msg_01Ev5Q3GU9YQ1jCV3NJHxnsJ",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-3-5-sonnet-20241022",
+ "content": [
+ {
+ "type": "text",
+ "text": "I'll create a word chain game website. For the domain, I suggest:\n\n---domain---\nwordchain.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://wordchain.scroll.pub\nmetaTags\neditButton /edit.html\ntitle Word Chain Game - English Word Battle\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <h1>Word Chain Game</h1>\n <p class=\"tagline\">Challenge the computer in this English word battle!</p>\n</header>\n\n<main>\n <div class=\"game-container\">\n <div class=\"score-board\">\n <div class=\"player-score\">\n <h2>You</h2>\n <span id=\"playerScore\">0</span>\n </div>\n <div class=\"vs\">VS</div>\n <div class=\"computer-score\">\n <h2>Computer</h2>\n <span id=\"computerScore\">0</span>\n </div>\n </div>\n\n <div class=\"game-area\">\n <div id=\"wordHistory\" class=\"word-history\">\n <h3>Word Chain</h3>\n <ul id=\"wordList\"></ul>\n </div>\n\n <div class=\"input-area\">\n <label for=\"playerInput\">Enter a word:</label>\n <input type=\"text\" id=\"playerInput\" placeholder=\"Type your word here...\" autocomplete=\"off\">\n <button id=\"submitWord\">Submit</button>\n </div>\n\n <div id=\"message\" class=\"message\"></div>\n </div>\n\n <div class=\"controls\">\n <button id=\"newGame\" class=\"new-game\">New Game</button>\n <button id=\"rules\" class=\"rules\">Show Rules</button>\n </div>\n </div>\n\n <dialog id=\"rulesModal\" class=\"rules-modal\">\n <h2>How to Play</h2>\n <ol>\n <li>Enter a valid English word</li>\n <li>Computer will respond with a word starting with the last letter of your word</li>\n <li>Continue the chain until someone can't find a valid word</li>\n </ol>\n <button id=\"closeRules\">Close</button>\n </dialog>\n</main>\n\n<footer>\n <p>Created with 💖 for word game enthusiasts</p>\n</footer>\n\n---style.css---\n:root {\n --primary-color: #2c3e50;\n --secondary-color: #3498db;\n --accent-color: #e74c3c;\n --background-color: #ecf0f1;\n --text-color: #2c3e50;\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 line-height: 1.6;\n}\n\nheader {\n background: var(--primary-color);\n color: white;\n padding: 2rem;\n text-align: center;\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\n.tagline {\n opacity: 0.9;\n font-size: 1.1rem;\n}\n\n.game-container {\n max-width: 800px;\n margin: 2rem auto;\n padding: 1rem;\n}\n\n.score-board {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 2rem;\n margin-bottom: 2rem;\n padding: 1rem;\n background: white;\n border-radius: 10px;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n}\n\n.player-score, .computer-score {\n text-align: center;\n}\n\n.player-score span, .computer-score span {\n font-size: 2.5rem;\n font-weight: bold;\n color: var(--secondary-color);\n}\n\n.vs {\n font-size: 1.5rem;\n font-weight: bold;\n color: var(--accent-color);\n}\n\n.game-area {\n background: white;\n padding: 2rem;\n border-radius: 10px;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n}\n\n.word-history {\n margin-bottom: 2rem;\n}\n\n.word-history ul {\n list-style: none;\n max-height: 200px;\n overflow-y: auto;\n padding: 1rem;\n border: 1px solid #ddd;\n border-radius: 5px;\n}\n\n.word-history li {\n padding: 0.5rem;\n border-bottom: 1px solid #eee;\n}\n\n.input-area {\n display: flex;\n gap: 1rem;\n margin-bottom: 1rem;\n}\n\ninput[type=\"text\"] {\n flex: 1;\n padding: 0.8rem;\n border: 2px solid #ddd;\n border-radius: 5px;\n font-size: 1rem;\n}\n\nbutton {\n padding: 0.8rem 1.5rem;\n border: none;\n border-radius: 5px;\n background: var(--secondary-color);\n color: white;\n cursor: pointer;\n transition: transform 0.2s, background-color 0.2s;\n}\n\nbutton:hover {\n background: #2980b9;\n transform: translateY(-2px);\n}\n\n.message {\n min-height: 2rem;\n text-align: center;\n color: var(--accent-color);\n}\n\n.controls {\n display: flex;\n justify-content: center;\n gap: 1rem;\n margin-top: 2rem;\n}\n\n.rules-modal {\n padding: 2rem;\n border-radius: 10px;\n border: none;\n box-shadow: 0 4px 20px rgba(0,0,0,0.2);\n}\n\n.rules-modal::backdrop {\n background: rgba(0,0,0,0.5);\n}\n\nfooter {\n text-align: center;\n padding: 2rem;\n background: var(--primary-color);\n color: white;\n margin-top: 2rem;\n}\n\n@media (max-width: 600px) {\n .input-area {\n flex-direction: column;\n }\n \n .score-board {\n gap: 1rem;\n }\n \n .game-area {\n padding: 1rem;\n }\n}\n\n---script.js---\nconst wordList = ['above', 'active', 'afraid', 'after', 'ago', 'Alaska', 'all', 'also', 'always', 'amazing', 'American', 'and', 'angry', 'animal', 'ant', 'any', 'anything', 'apple', 'April', \"aren't\", 'arm', 'art', 'room', 'ask', 'at', 'ate', 'attention', 'August', 'aunt', 'autumn', 'baby', 'bad', 'badminton', 'bag', 'ball', 'bamboo', 'banana', 'basket', 'basketball', 'bathroom', 'be', 'careful', 'beach', 'bear', 'beautiful', 'because', 'become', 'bed', 'bedroom', 'beef', 'before', 'behind', 'beside', 'best', 'better', 'between', 'big', 'bigger', 'bike', 'bird', 'black', 'blackboard', 'blue', 'boat', 'boating', 'body', 'book', 'bookstore', 'both', 'bottle', 'bought', 'bowl', 'box', 'boy', 'bread', 'breakfast', 'breath', 'bridge', 'broken', 'brother', 'brown', 'building', 'bunny', 'bus', 'businessman', 'busy', 'but', 'buy', 'by', 'cake', 'camp', 'Canada', 'Canadian', 'Canberra', 'candy', 'cap', 'car', 'carrot', 'cartoon', 'cat', 'cave', 'chair', 'chase', 'cheap', 'cheetah', 'chicken', 'children', 'China', 'Chinese', 'book', 'chocolate', 'chopsticks', 'Christmas', 'cinema', 'class', 'classroom', 'clean', 'clean my room', 'cleaned', 'clever', 'climbing', 'clock', 'clothes', 'cloudy', 'club', 'coach', 'coat', 'cold', 'come on', 'comic', 'comic book', 'computer', 'computer room', 'contest', 'cook'];\n\nclass WordChainGame {\n constructor() {\n this.usedWords = new Set();\n this.playerScore = 0;\n this.computerScore = 0;\n this.lastWord = '';\n }\n\n isValidWord(word) {\n return wordList.includes(word.toLowerCase()) && !this.usedWords.has(word.toLowerCase());\n }\n\n checkChain(word) {\n if (!this.lastWord) return true;\n return word.charAt(0).toLowerCase() === this.lastWord.charAt(this.lastWord.length - 1).toLowerCase();\n }\n\n computerTurn() {\n const lastLetter = this.lastWord.charAt(this.lastWord.length - 1).toLowerCase();\n const possibleWords = wordList.filter(word => \n word.charAt(0).toLowerCase() === lastLetter && \n !this.usedWords.has(word.toLowerCase())\n );\n \n if (possibleWords.length === 0) return null;\n return possibleWords[Math.floor(Math.random() * possibleWords.length)];\n }\n}\n\nlet game = new WordChainGame();\n\ndocument.addEventListener('DOMContentLoaded', () => {\n const input = document.getElementById('playerInput');\n const submitBtn = document.getElementById('submitWord');\n const message = document.getElementById('message');\n const wordList = document.getElementById('wordList');\n const newGameBtn = document.getElementById('newGame');\n const rulesBtn = document.getElementById('rules');\n const rulesModal = document.getElementById('rulesModal');\n const closeRulesBtn = document.getElementById('closeRules');\n\n function updateScores() {\n document.getElementById('playerScore').textContent = game.playerScore;\n document.getElementById('computerScore').textContent = game.computerScore;\n }\n\n function addWordToHistory(word, isComputer = false) {\n const li = document.createElement('li');\n li.textContent = `${isComputer ? '🤖' : '👤'} ${word}`;\n wordList.insertBefore(li, wordList.firstChild);\n }\n\n function handlePlayerTurn() {\n const word = input.value.trim().toLowerCase();\n \n if (!word) {\n message.textContent = \"Please enter a word!\";\n return;\n }\n\n if (!game.isValidWord(word)) {\n message.textContent = \"Invalid word or already used!\";\n return;\n }\n\n if (game.lastWord && !game.checkChain(word)) {\n message.textContent = `Word must start with '${game.lastWord.charAt(game.lastWord.length - 1)}'!`;\n return;\n }\n\n game.usedWords.add(word);\n game.lastWord = word;\n addWordToHistory(word);\n game.playerScore++;\n updateScores();\n input.value = '';\n\n // Computer's turn\n const computerWord = game.computerTurn();\n if (!computerWord) {\n message.textContent = \"Computer can't find a word. You win!\";\n game.playerScore += 3;\n updateScores();\n return;\n }\n\n game.usedWords.add(computerWord);\n game.lastWord = computerWord;\n addWordToHistory(computerWord, true);\n game.computerScore++;\n updateScores();\n message.textContent = `Computer played: ${computerWord}`;\n }\n\n submitBtn.addEventListener('click', handlePlayerTurn);\n input.addEventListener('keypress', (e) => {\n if (e.key === 'Enter') handlePlayerTurn();\n });\n\n newGameBtn.addEventListener('click', () => {\n game = new WordChainGame();\n wordList.innerHTML = '';\n message.textContent = '';\n input.value = '';\n updateScores();\n });\n\n rulesBtn.addEventListener('click', () => rulesModal.showModal());\n closeRulesBtn.addEventListener('click', () => rulesModal.close());\n});\n\n---end---\n\nThis implementation creates a beautiful and engaging word chain game with:\n\n1. Clean, modern UI with smooth animations and transitions\n2. Responsive design that works on all devices\n3. Score tracking system\n4. Word history display\n5. Rules modal\n6. Computer AI that selects valid words\n7. Input validation and error messages\n8. Accessibility features\n9. Semantic HTML structure\n10. Modern CSS with custom properties and flexbox\n11. Clean, modular JavaScript with OOP principles\n\nThe game is both fun and educational, helping players expand their English vocabulary while competing against the computer."
+ }
+ ],
+ "stop_reason": "end_turn",
+ "stop_sequence": null,
+ "usage": {
+ "input_tokens": 552,
+ "cache_creation_input_tokens": 0,
+ "cache_read_input_tokens": 0,
+ "output_tokens": 3440
+ }
+}
\ No newline at end of file
diff --git a/readme.scroll b/readme.scroll
new file mode 100644
index 0000000..380ca93
--- /dev/null
+++ b/readme.scroll
@@ -0,0 +1,2 @@
+# wordchain1.scroll.pub
+Website generated by Claude from prompt: 制作一个简单的“Word Chain”游戏,玩家将与电脑对战。游戏的基本逻辑将如下: 玩家输入一个单词。 电脑从列表中选择一个以该单词最后一个字母开头的单词。 游戏交替进行,直到电脑或玩家无法继续或输入了不在列表中的单词。 单词列表是: above active afraid after ago Alaska all also always amazing American and angry animal ant any anything apple April aren't = are not arm art room ask at ate attention August aunt autumn baby bad badminton bag ball bamboo banana basket basketball bathroom be careful beach bear beautiful because become bed bedroom beef before behind beside best better between big bigger bike bird black blackboard blue boat boating body book bookstore both bottle bought bowl box boy bread breakfast breath bridge broken brother brown building bunny bus businessman busy but buy by cake camp Canada Canadian Canberra candy cap car carrot cartoon cat cave chair chase cheap cheetah chicken children China Chinese book chocolate chopsticks Christmas cinema class classroom clean clean my room cleaned clever climbing clock clothes cloudy club coach coat cold come on comic comic book computer computer room contest cook co
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..7e7ce09
--- /dev/null
+++ b/script.js
@@ -0,0 +1,112 @@
+const wordList = ['above', 'active', 'afraid', 'after', 'ago', 'Alaska', 'all', 'also', 'always', 'amazing', 'American', 'and', 'angry', 'animal', 'ant', 'any', 'anything', 'apple', 'April', "aren't", 'arm', 'art', 'room', 'ask', 'at', 'ate', 'attention', 'August', 'aunt', 'autumn', 'baby', 'bad', 'badminton', 'bag', 'ball', 'bamboo', 'banana', 'basket', 'basketball', 'bathroom', 'be', 'careful', 'beach', 'bear', 'beautiful', 'because', 'become', 'bed', 'bedroom', 'beef', 'before', 'behind', 'beside', 'best', 'better', 'between', 'big', 'bigger', 'bike', 'bird', 'black', 'blackboard', 'blue', 'boat', 'boating', 'body', 'book', 'bookstore', 'both', 'bottle', 'bought', 'bowl', 'box', 'boy', 'bread', 'breakfast', 'breath', 'bridge', 'broken', 'brother', 'brown', 'building', 'bunny', 'bus', 'businessman', 'busy', 'but', 'buy', 'by', 'cake', 'camp', 'Canada', 'Canadian', 'Canberra', 'candy', 'cap', 'car', 'carrot', 'cartoon', 'cat', 'cave', 'chair', 'chase', 'cheap', 'cheetah', 'chicken', 'children', 'China', 'Chinese', 'book', 'chocolate', 'chopsticks', 'Christmas', 'cinema', 'class', 'classroom', 'clean', 'clean my room', 'cleaned', 'clever', 'climbing', 'clock', 'clothes', 'cloudy', 'club', 'coach', 'coat', 'cold', 'come on', 'comic', 'comic book', 'computer', 'computer room', 'contest', 'cook'];
+
+class WordChainGame {
+ constructor() {
+ this.usedWords = new Set();
+ this.playerScore = 0;
+ this.computerScore = 0;
+ this.lastWord = '';
+ }
+
+ isValidWord(word) {
+ return wordList.includes(word.toLowerCase()) && !this.usedWords.has(word.toLowerCase());
+ }
+
+ checkChain(word) {
+ if (!this.lastWord) return true;
+ return word.charAt(0).toLowerCase() === this.lastWord.charAt(this.lastWord.length - 1).toLowerCase();
+ }
+
+ computerTurn() {
+ const lastLetter = this.lastWord.charAt(this.lastWord.length - 1).toLowerCase();
+ const possibleWords = wordList.filter(word =>
+ word.charAt(0).toLowerCase() === lastLetter &&
+ !this.usedWords.has(word.toLowerCase())
+ );
+
+ if (possibleWords.length === 0) return null;
+ return possibleWords[Math.floor(Math.random() * possibleWords.length)];
+ }
+}
+
+let game = new WordChainGame();
+
+document.addEventListener('DOMContentLoaded', () => {
+ const input = document.getElementById('playerInput');
+ const submitBtn = document.getElementById('submitWord');
+ const message = document.getElementById('message');
+ const wordList = document.getElementById('wordList');
+ const newGameBtn = document.getElementById('newGame');
+ const rulesBtn = document.getElementById('rules');
+ const rulesModal = document.getElementById('rulesModal');
+ const closeRulesBtn = document.getElementById('closeRules');
+
+ function updateScores() {
+ document.getElementById('playerScore').textContent = game.playerScore;
+ document.getElementById('computerScore').textContent = game.computerScore;
+ }
+
+ function addWordToHistory(word, isComputer = false) {
+ const li = document.createElement('li');
+ li.textContent = `${isComputer ? '🤖' : '👤'} ${word}`;
+ wordList.insertBefore(li, wordList.firstChild);
+ }
+
+ function handlePlayerTurn() {
+ const word = input.value.trim().toLowerCase();
+
+ if (!word) {
+ message.textContent = "Please enter a word!";
+ return;
+ }
+
+ if (!game.isValidWord(word)) {
+ message.textContent = "Invalid word or already used!";
+ return;
+ }
+
+ if (game.lastWord && !game.checkChain(word)) {
+ message.textContent = `Word must start with '${game.lastWord.charAt(game.lastWord.length - 1)}'!`;
+ return;
+ }
+
+ game.usedWords.add(word);
+ game.lastWord = word;
+ addWordToHistory(word);
+ game.playerScore++;
+ updateScores();
+ input.value = '';
+
+ // Computer's turn
+ const computerWord = game.computerTurn();
+ if (!computerWord) {
+ message.textContent = "Computer can't find a word. You win!";
+ game.playerScore += 3;
+ updateScores();
+ return;
+ }
+
+ game.usedWords.add(computerWord);
+ game.lastWord = computerWord;
+ addWordToHistory(computerWord, true);
+ game.computerScore++;
+ updateScores();
+ message.textContent = `Computer played: ${computerWord}`;
+ }
+
+ submitBtn.addEventListener('click', handlePlayerTurn);
+ input.addEventListener('keypress', (e) => {
+ if (e.key === 'Enter') handlePlayerTurn();
+ });
+
+ newGameBtn.addEventListener('click', () => {
+ game = new WordChainGame();
+ wordList.innerHTML = '';
+ message.textContent = '';
+ input.value = '';
+ updateScores();
+ });
+
+ rulesBtn.addEventListener('click', () => rulesModal.showModal());
+ closeRulesBtn.addEventListener('click', () => rulesModal.close());
+});
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..74ce4b9
--- /dev/null
+++ b/style.css
@@ -0,0 +1,167 @@
+:root {
+ --primary-color: #2c3e50;
+ --secondary-color: #3498db;
+ --accent-color: #e74c3c;
+ --background-color: #ecf0f1;
+ --text-color: #2c3e50;
+}
+
+* {
+ 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);
+ line-height: 1.6;
+}
+
+header {
+ background: var(--primary-color);
+ color: white;
+ padding: 2rem;
+ text-align: center;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+}
+
+.tagline {
+ opacity: 0.9;
+ font-size: 1.1rem;
+}
+
+.game-container {
+ max-width: 800px;
+ margin: 2rem auto;
+ padding: 1rem;
+}
+
+.score-board {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 2rem;
+ margin-bottom: 2rem;
+ padding: 1rem;
+ background: white;
+ border-radius: 10px;
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+}
+
+.player-score, .computer-score {
+ text-align: center;
+}
+
+.player-score span, .computer-score span {
+ font-size: 2.5rem;
+ font-weight: bold;
+ color: var(--secondary-color);
+}
+
+.vs {
+ font-size: 1.5rem;
+ font-weight: bold;
+ color: var(--accent-color);
+}
+
+.game-area {
+ background: white;
+ padding: 2rem;
+ border-radius: 10px;
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+}
+
+.word-history {
+ margin-bottom: 2rem;
+}
+
+.word-history ul {
+ list-style: none;
+ max-height: 200px;
+ overflow-y: auto;
+ padding: 1rem;
+ border: 1px solid #ddd;
+ border-radius: 5px;
+}
+
+.word-history li {
+ padding: 0.5rem;
+ border-bottom: 1px solid #eee;
+}
+
+.input-area {
+ display: flex;
+ gap: 1rem;
+ margin-bottom: 1rem;
+}
+
+input[type="text"] {
+ flex: 1;
+ padding: 0.8rem;
+ border: 2px solid #ddd;
+ border-radius: 5px;
+ font-size: 1rem;
+}
+
+button {
+ padding: 0.8rem 1.5rem;
+ border: none;
+ border-radius: 5px;
+ background: var(--secondary-color);
+ color: white;
+ cursor: pointer;
+ transition: transform 0.2s, background-color 0.2s;
+}
+
+button:hover {
+ background: #2980b9;
+ transform: translateY(-2px);
+}
+
+.message {
+ min-height: 2rem;
+ text-align: center;
+ color: var(--accent-color);
+}
+
+.controls {
+ display: flex;
+ justify-content: center;
+ gap: 1rem;
+ margin-top: 2rem;
+}
+
+.rules-modal {
+ padding: 2rem;
+ border-radius: 10px;
+ border: none;
+ box-shadow: 0 4px 20px rgba(0,0,0,0.2);
+}
+
+.rules-modal::backdrop {
+ background: rgba(0,0,0,0.5);
+}
+
+footer {
+ text-align: center;
+ padding: 2rem;
+ background: var(--primary-color);
+ color: white;
+ margin-top: 2rem;
+}
+
+@media (max-width: 600px) {
+ .input-area {
+ flex-direction: column;
+ }
+
+ .score-board {
+ gap: 1rem;
+ }
+
+ .game-area {
+ padding: 1rem;
+ }
+}