Changes to minesweeper.scroll.pub

root
root
19 days ago
Initial commit
body.html
Changed around line 1
+
+

Minesweeper Challenge

+
+ Level: 1/30
+ Mines: 0
+ Time: 0s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Made with ❤️ for puzzle lovers

+
index.scroll
Changed around line 1
+ buildHtml
+ baseUrl https://minesweeper.scroll.pub
+ metaTags
+ editButton /edit.html
+ title Minesweeper Challenge - 30 Exciting Levels
+ style.css
+ body.html
+ script.js
prompt.json
Changed around line 1
+ {
+ "id": "msg_01Jd2QYxBwK7VGnh6K1Z8P2F",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-3-5-sonnet-20241022",
+ "content": [
+ {
+ "type": "text",
+ "text": "Let me create a minesweeper challenge game website with 30 levels.\n\n---domain---\nminesweeper.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://minesweeper.scroll.pub\nmetaTags\neditButton /edit.html\ntitle Minesweeper Challenge - 30 Exciting Levels\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n
\n

Minesweeper Challenge

\n
\n Level: 1/30\n Mines: 0\n Time: 0s\n
\n
\n\n
\n
\n
\n
\n \n \n
\n
\n \n
\n
\n

\n

\n \n
\n
\n
\n\n
\n

Made with ❤️ for puzzle lovers

\n
\n\n---style.css---\n:root {\n --primary-color: #2c3e50;\n --secondary-color: #3498db;\n --grid-color: #ecf0f1;\n --cell-size: 40px;\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: linear-gradient(135deg, #1a2a3a 0%, #2c3e50 100%);\n color: white;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\nheader {\n text-align: center;\n padding: 2rem;\n background: rgba(0, 0, 0, 0.2);\n}\n\nh1 {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);\n}\n\n.level-info {\n display: flex;\n justify-content: center;\n gap: 2rem;\n font-size: 1.2rem;\n}\n\nmain {\n flex: 1;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 2rem;\n}\n\n.game-container {\n background: rgba(255, 255, 255, 0.1);\n padding: 2rem;\n border-radius: 1rem;\n box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);\n}\n\n.grid {\n display: grid;\n gap: 2px;\n background: var(--primary-color);\n padding: 2px;\n border-radius: 4px;\n margin-bottom: 1rem;\n}\n\n.cell {\n width: var(--cell-size);\n height: var(--cell-size);\n background: var(--grid-color);\n border: none;\n display: flex;\n justify-content: center;\n align-items: center;\n font-weight: bold;\n font-size: 1.2rem;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.cell:hover {\n background: #bdc3c7;\n}\n\n.cell.revealed {\n background: #95a5a6;\n}\n\n.cell.mine {\n background: #e74c3c;\n}\n\n.cell.flagged {\n background: #f1c40f;\n}\n\n.controls {\n display: flex;\n gap: 1rem;\n justify-content: center;\n}\n\n.btn {\n padding: 0.8rem 1.5rem;\n border: none;\n border-radius: 4px;\n background: var(--secondary-color);\n color: white;\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.btn:hover {\n background: #2980b9;\n transform: translateY(-2px);\n}\n\n.modal {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.8);\n justify-content: center;\n align-items: center;\n}\n\n.modal-content {\n background: white;\n color: var(--primary-color);\n padding: 2rem;\n border-radius: 1rem;\n text-align: center;\n max-width: 90%;\n width: 400px;\n}\n\nfooter {\n text-align: center;\n padding: 1rem;\n background: rgba(0, 0, 0, 0.2);\n}\n\n@media (max-width: 768px) {\n :root {\n --cell-size: 30px;\n }\n \n .level-info {\n flex-direction: column;\n gap: 0.5rem;\n }\n \n .game-container {\n padding: 1rem;\n }\n}\n\n---script.js---\nclass MinesweeperGame {\n constructor() {\n this.level = 1;\n this.grid = [];\n this.mines = [];\n this.timer = 0;\n this.timerInterval = null;\n this.isGameOver = false;\n \n this.initializeDOM();\n this.setupEventListeners();\n this.startLevel(this.level);\n }\n\n initializeDOM() {\n this.gridElement = document.getElementById('grid');\n this.levelElement = document.getElementById('current-level');\n this.minesElement = document.getElementById('mines-count');\n this.timerElement = document.getElementById('timer');\n this.modal = document.getElementById('modal');\n this.modalTitle = document.getElementById('modal-title');\n this.modalMessage = document.getElementById('modal-message');\n this.modalButton = document.getElementById('modal-button');\n }\n\n setupEventListeners() {\n document.getElementById('restart').addEventListener('click', () => this.startLevel(this.level));\n document.getElementById('help').addEventListener('click', () => this.showHelp());\n this.modalButton.addEventListener('click', () => this.hideModal());\n }\n\n getLevelConfig(level) {\n return {\n rows: Math.min(8 + Math.floor(level / 5), 16),\n cols: Math.min(8 + Math.floor(level / 5), 16),\n mines: Math.min(10 + level * 2, 99)\n };\n }\n\n startLevel(level) {\n this.level = level;\n this.isGameOver = false;\n clearInterval(this.timerInterval);\n this.timer = 0;\n this.timerElement.textContent = '0';\n \n const config = this.getLevelConfig(level);\n this.createGrid(config);\n this.levelElement.textContent = level;\n this.minesElement.textContent = config.mines;\n \n this.timerInterval = setInterval(() => {\n this.timer++;\n this.timerElement.textContent = this.timer;\n }, 1000);\n }\n\n createGrid(config) {\n this.grid = [];\n this.mines = [];\n this.gridElement.innerHTML = '';\n this.gridElement.style.gridTemplateColumns = `repeat(${config.cols}, var(--cell-size))`;\n\n for (let i = 0; i < config.rows; i++) {\n this.grid[i] = [];\n for (let j = 0; j < config.cols; j++) {\n const cell = document.createElement('button');\n cell.className = 'cell';\n cell.dataset.row = i;\n cell.dataset.col = j;\n \n cell.addEventListener('click', (e) => this.handleClick(e));\n cell.addEventListener('contextmenu', (e) => this.handleRightClick(e));\n \n this.gridElement.appendChild(cell);\n this.grid[i][j] = {\n element: cell,\n isMine: false,\n isRevealed: false,\n isFlagged: false,\n neighborMines: 0\n };\n }\n }\n\n this.placeMines(config);\n this.calculateNeighborMines(config);\n }\n\n placeMines(config) {\n let minesToPlace = config.mines;\n while (minesToPlace > 0) {\n const row = Math.floor(Math.random() * config.rows);\n const col = Math.floor(Math.random() * config.cols);\n \n if (!this.grid[row][col].isMine) {\n this.grid[row][col].isMine = true;\n this.mines.push({row, col});\n minesToPlace--;\n }\n }\n }\n\n calculateNeighborMines(config) {\n const directions = [\n [-1,-1], [-1,0], [-1,1],\n [0,-1], [0,1],\n [1,-1], [1,0], [1,1]\n ];\n\n for (let i = 0; i < config.rows; i++) {\n for (let j = 0; j < config.cols; j++) {\n if (!this.grid[i][j].isMine) {\n let count = 0;\n for (const [dx, dy] of directions) {\n const newRow = i + dx;\n const newCol = j + dy;\n if (newRow >= 0 && newRow < config.rows &&\n newCol >= 0 && newCol < config.cols &&\n this.grid[newRow][newCol].isMine) {\n count++;\n }\n }\n this.grid[i][j].neighborMines = count;\n }\n }\n }\n }\n\n handleClick(e) {\n e.preventDefault();\n if (this.isGameOver) return;\n\n const row = parseInt(e.target.dataset.row);\n const col = parseInt(e.target.dataset.col);\n const cell = this.grid[row][col];\n\n if (cell.isFlagged) return;\n\n if (cell.isMine) {\n this.gameOver(false);\n return;\n }\n\n this.revealCell(row, col);\n this.checkWin();\n }\n\n handleRightClick(e) {\n e.preventDefault();\n if (this.isGameOver) return;\n\n const row = parseInt(e.target.dataset.row);\n const col = parseInt(e.target.dataset.col);\n const cell = this.grid[row][col];\n\n if (!cell.isRevealed) {\n cell.isFlagged = !cell.isFlagged;\n cell.element.classList.toggle('flagged');\n }\n }\n\n revealCell(row, col) {\n const cell = this.grid[row][col];\n if (cell.isRevealed || cell.isFlagged) return;\n\n cell.isRevealed = true;\n cell.element.classList.add('revealed');\n\n if (cell.neighborMines > 0) {\n cell.element.textContent = cell.neighborMines;\n } else {\n const directions = [\n [-1,-1], [-1,0], [-1,1],\n [0,-1], [0,1],\n [1,-1], [1,0], [1,1]\n ];\n\n for (const [dx, dy] of directions) {\n const newRow = row + dx;\n const newCol = col + dy;\n if (newRow >= 0 && newRow < this.grid.length &&\n newCol >= 0 && newCol < this.grid[0].length) {\n this.revealCell(newRow, newCol);\n }\n }\n }\n }\n\n checkWin() {\n const config = this.getLevelConfig(this.level);\n const totalCells = config.rows * config.cols;\n let revealedCells = 0;\n\n for (let i = 0; i < config.rows; i++) {\n for (let j = 0; j < config.cols; j++) {\n if (this.grid[i][j].isRevealed) revealedCells++;\n }\n }\n\n if (revealedCells === totalCells - config.mines) {\n this.gameOver(true);\n }\n }\n\n gameOver(won) {\n this.isGameOver = true;\n clearInterval(this.timerInterval);\n\n if (won) {\n if (this.level === 30) {\n this.showModal('Congratulations!', 'You\\'ve completed all levels!', 'Play Again');\n this.level = 1;\n } else {\n this.showModal('Level Complete!', `Ready for level ${this.level + 1}?`, 'Next Level');\n this.level++;\n }\n } else {\n this.showModal('Game Over', 'Try again?', 'Restart Level');\n this.revealMines();\n }\n }\n\n revealMines() {\n this.mines.forEach(({row, col}) => {\n const cell = this.grid[row][col];\n cell.element.classList.add('mine');\n });\n }\n\n showModal(title, message, buttonText) {\n this.modalTitle.textContent = title;\n this.modalMessage.textContent = message;\n this.modalButton.textContent = buttonText;\n this.modal.style.display = 'flex';\n }\n\n hideModal() {\n this.modal.style.display = 'none';\n this.startLevel(this.level);\n }\n\n showHelp() {\n this.showModal('How to Play', \n 'Left click to reveal cells. Right click to flag mines. Avoid all mines to complete the level!',\n 'Got it!'\n );\n }\n}\n\nwindow.addEventListener('load', () => {\n new MinesweeperGame();\n});\n\n---end---\n\nThis implementation creates a progressive minesweeper game with 30 levels of increasing difficulty. Key features include:\n\n1. Progressive difficulty scaling (larger grid and more mines as levels increase)\n2. Timer and mines counter\n3. Responsive design that works on mobile and desktop\n4. Smooth animations and modern UI\n5. Help system\n6. Right-click flag placement\n7. Level progression system\n8. Victory/defeat conditions\n9. Clean, accessible interface\n10. Modern gradient background with glass-morphism effects\n\nThe game follows standard minesweeper rules but adds the excitement of level progression. Each level becomes slightly more challenging than the last, with more mines and a larger grid (up to a maximum size)."
+ }
+ ],
+ "stop_reason": "end_turn",
+ "stop_sequence": null,
+ "usage": {
+ "input_tokens": 288,
+ "cache_creation_input_tokens": 0,
+ "cache_read_input_tokens": 0,
+ "output_tokens": 3931
+ }
+ }
readme.scroll
Changed around line 1
+ # minesweeper.scroll.pub
+ Website generated by Claude from prompt: 创建一个扫雷冲关小游戏,30关
script.js
Changed around line 1
+ class MinesweeperGame {
+ constructor() {
+ this.level = 1;
+ this.grid = [];
+ this.mines = [];
+ this.timer = 0;
+ this.timerInterval = null;
+ this.isGameOver = false;
+
+ this.initializeDOM();
+ this.setupEventListeners();
+ this.startLevel(this.level);
+ }
+
+ initializeDOM() {
+ this.gridElement = document.getElementById('grid');
+ this.levelElement = document.getElementById('current-level');
+ this.minesElement = document.getElementById('mines-count');
+ this.timerElement = document.getElementById('timer');
+ this.modal = document.getElementById('modal');
+ this.modalTitle = document.getElementById('modal-title');
+ this.modalMessage = document.getElementById('modal-message');
+ this.modalButton = document.getElementById('modal-button');
+ }
+
+ setupEventListeners() {
+ document.getElementById('restart').addEventListener('click', () => this.startLevel(this.level));
+ document.getElementById('help').addEventListener('click', () => this.showHelp());
+ this.modalButton.addEventListener('click', () => this.hideModal());
+ }
+
+ getLevelConfig(level) {
+ return {
+ rows: Math.min(8 + Math.floor(level / 5), 16),
+ cols: Math.min(8 + Math.floor(level / 5), 16),
+ mines: Math.min(10 + level * 2, 99)
+ };
+ }
+
+ startLevel(level) {
+ this.level = level;
+ this.isGameOver = false;
+ clearInterval(this.timerInterval);
+ this.timer = 0;
+ this.timerElement.textContent = '0';
+
+ const config = this.getLevelConfig(level);
+ this.createGrid(config);
+ this.levelElement.textContent = level;
+ this.minesElement.textContent = config.mines;
+
+ this.timerInterval = setInterval(() => {
+ this.timer++;
+ this.timerElement.textContent = this.timer;
+ }, 1000);
+ }
+
+ createGrid(config) {
+ this.grid = [];
+ this.mines = [];
+ this.gridElement.innerHTML = '';
+ this.gridElement.style.gridTemplateColumns = `repeat(${config.cols}, var(--cell-size))`;
+
+ for (let i = 0; i < config.rows; i++) {
+ this.grid[i] = [];
+ for (let j = 0; j < config.cols; j++) {
+ const cell = document.createElement('button');
+ cell.className = 'cell';
+ cell.dataset.row = i;
+ cell.dataset.col = j;
+
+ cell.addEventListener('click', (e) => this.handleClick(e));
+ cell.addEventListener('contextmenu', (e) => this.handleRightClick(e));
+
+ this.gridElement.appendChild(cell);
+ this.grid[i][j] = {
+ element: cell,
+ isMine: false,
+ isRevealed: false,
+ isFlagged: false,
+ neighborMines: 0
+ };
+ }
+ }
+
+ this.placeMines(config);
+ this.calculateNeighborMines(config);
+ }
+
+ placeMines(config) {
+ let minesToPlace = config.mines;
+ while (minesToPlace > 0) {
+ const row = Math.floor(Math.random() * config.rows);
+ const col = Math.floor(Math.random() * config.cols);
+
+ if (!this.grid[row][col].isMine) {
+ this.grid[row][col].isMine = true;
+ this.mines.push({row, col});
+ minesToPlace--;
+ }
+ }
+ }
+
+ calculateNeighborMines(config) {
+ const directions = [
+ [-1,-1], [-1,0], [-1,1],
+ [0,-1], [0,1],
+ [1,-1], [1,0], [1,1]
+ ];
+
+ for (let i = 0; i < config.rows; i++) {
+ for (let j = 0; j < config.cols; j++) {
+ if (!this.grid[i][j].isMine) {
+ let count = 0;
+ for (const [dx, dy] of directions) {
+ const newRow = i + dx;
+ const newCol = j + dy;
+ if (newRow >= 0 && newRow < config.rows &&
+ newCol >= 0 && newCol < config.cols &&
+ this.grid[newRow][newCol].isMine) {
+ count++;
+ }
+ }
+ this.grid[i][j].neighborMines = count;
+ }
+ }
+ }
+ }
+
+ handleClick(e) {
+ e.preventDefault();
+ if (this.isGameOver) return;
+
+ const row = parseInt(e.target.dataset.row);
+ const col = parseInt(e.target.dataset.col);
+ const cell = this.grid[row][col];
+
+ if (cell.isFlagged) return;
+
+ if (cell.isMine) {
+ this.gameOver(false);
+ return;
+ }
+
+ this.revealCell(row, col);
+ this.checkWin();
+ }
+
+ handleRightClick(e) {
+ e.preventDefault();
+ if (this.isGameOver) return;
+
+ const row = parseInt(e.target.dataset.row);
+ const col = parseInt(e.target.dataset.col);
+ const cell = this.grid[row][col];
+
+ if (!cell.isRevealed) {
+ cell.isFlagged = !cell.isFlagged;
+ cell.element.classList.toggle('flagged');
+ }
+ }
+
+ revealCell(row, col) {
+ const cell = this.grid[row][col];
+ if (cell.isRevealed || cell.isFlagged) return;
+
+ cell.isRevealed = true;
+ cell.element.classList.add('revealed');
+
+ if (cell.neighborMines > 0) {
+ cell.element.textContent = cell.neighborMines;
+ } else {
+ const directions = [
+ [-1,-1], [-1,0], [-1,1],
+ [0,-1], [0,1],
+ [1,-1], [1,0], [1,1]
+ ];
+
+ for (const [dx, dy] of directions) {
+ const newRow = row + dx;
+ const newCol = col + dy;
+ if (newRow >= 0 && newRow < this.grid.length &&
+ newCol >= 0 && newCol < this.grid[0].length) {
+ this.revealCell(newRow, newCol);
+ }
+ }
+ }
+ }
+
+ checkWin() {
+ const config = this.getLevelConfig(this.level);
+ const totalCells = config.rows * config.cols;
+ let revealedCells = 0;
+
+ for (let i = 0; i < config.rows; i++) {
+ for (let j = 0; j < config.cols; j++) {
+ if (this.grid[i][j].isRevealed) revealedCells++;
+ }
+ }
+
+ if (revealedCells === totalCells - config.mines) {
+ this.gameOver(true);
+ }
+ }
+
+ gameOver(won) {
+ this.isGameOver = true;
+ clearInterval(this.timerInterval);
+
+ if (won) {
+ if (this.level === 30) {
+ this.showModal('Congratulations!', 'You\'ve completed all levels!', 'Play Again');
+ this.level = 1;
+ } else {
+ this.showModal('Level Complete!', `Ready for level ${this.level + 1}?`, 'Next Level');
+ this.level++;
+ }
+ } else {
+ this.showModal('Game Over', 'Try again?', 'Restart Level');
+ this.revealMines();
+ }
+ }
+
+ revealMines() {
+ this.mines.forEach(({row, col}) => {
+ const cell = this.grid[row][col];
+ cell.element.classList.add('mine');
+ });
+ }
+
+ showModal(title, message, buttonText) {
+ this.modalTitle.textContent = title;
+ this.modalMessage.textContent = message;
+ this.modalButton.textContent = buttonText;
+ this.modal.style.display = 'flex';
+ }
+
+ hideModal() {
+ this.modal.style.display = 'none';
+ this.startLevel(this.level);
+ }
+
+ showHelp() {
+ this.showModal('How to Play',
+ 'Left click to reveal cells. Right click to flag mines. Avoid all mines to complete the level!',
+ 'Got it!'
+ );
+ }
+ }
+
+ window.addEventListener('load', () => {
+ new MinesweeperGame();
+ });
style.css
Changed around line 1
+ :root {
+ --primary-color: #2c3e50;
+ --secondary-color: #3498db;
+ --grid-color: #ecf0f1;
+ --cell-size: 40px;
+ }
+
+ * {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ body {
+ font-family: 'Segoe UI', system-ui, sans-serif;
+ background: linear-gradient(135deg, #1a2a3a 0%, #2c3e50 100%);
+ color: white;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ }
+
+ header {
+ text-align: center;
+ padding: 2rem;
+ background: rgba(0, 0, 0, 0.2);
+ }
+
+ h1 {
+ font-size: 2.5rem;
+ margin-bottom: 1rem;
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
+ }
+
+ .level-info {
+ display: flex;
+ justify-content: center;
+ gap: 2rem;
+ font-size: 1.2rem;
+ }
+
+ main {
+ flex: 1;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 2rem;
+ }
+
+ .game-container {
+ background: rgba(255, 255, 255, 0.1);
+ padding: 2rem;
+ border-radius: 1rem;
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
+ }
+
+ .grid {
+ display: grid;
+ gap: 2px;
+ background: var(--primary-color);
+ padding: 2px;
+ border-radius: 4px;
+ margin-bottom: 1rem;
+ }
+
+ .cell {
+ width: var(--cell-size);
+ height: var(--cell-size);
+ background: var(--grid-color);
+ border: none;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-weight: bold;
+ font-size: 1.2rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ }
+
+ .cell:hover {
+ background: #bdc3c7;
+ }
+
+ .cell.revealed {
+ background: #95a5a6;
+ }
+
+ .cell.mine {
+ background: #e74c3c;
+ }
+
+ .cell.flagged {
+ background: #f1c40f;
+ }
+
+ .controls {
+ display: flex;
+ gap: 1rem;
+ justify-content: center;
+ }
+
+ .btn {
+ padding: 0.8rem 1.5rem;
+ border: none;
+ border-radius: 4px;
+ background: var(--secondary-color);
+ color: white;
+ font-size: 1rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ }
+
+ .btn:hover {
+ background: #2980b9;
+ transform: translateY(-2px);
+ }
+
+ .modal {
+ display: none;
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.8);
+ justify-content: center;
+ align-items: center;
+ }
+
+ .modal-content {
+ background: white;
+ color: var(--primary-color);
+ padding: 2rem;
+ border-radius: 1rem;
+ text-align: center;
+ max-width: 90%;
+ width: 400px;
+ }
+
+ footer {
+ text-align: center;
+ padding: 1rem;
+ background: rgba(0, 0, 0, 0.2);
+ }
+
+ @media (max-width: 768px) {
+ :root {
+ --cell-size: 30px;
+ }
+
+ .level-info {
+ flex-direction: column;
+ gap: 0.5rem;
+ }
+
+ .game-container {
+ padding: 1rem;
+ }
+ }