Changes to tictac.framehub.pro

ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated test.scroll
test.scroll
Changed around line 1
- module.exports = {JSONCONTENTS: require("fs").readFileSync("settings.json")}
+ module.exports = {JSONCONTENTS: JSON.stringify(JSON.parse(require("fs").readFileSync("settings.json")))}
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated test.scroll
test.scroll
Changed around line 1
+ buildHtml
+
+ replaceNodejs
+ module.exports = {JSONCONTENTS: require("fs").readFileSync("settings.json")}
+
+
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
created test.scroll
test.scroll
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated settings.json
settings.json
Changed around line 1
- {"version":"next","imageUrl":"https://twxdyfr6nmnvjjym.public.blob.vercel-storage.com/scoreboard/latest-v2.png","button":{"title":"Play 🏀","action":{"type":"launch_frame","name":"Bball frame","url":"https://ballframe.vercel.app/","splashImageUrl":"https://ballframe.vercel.app/splash.png","splashBackgroundColor":"#FFFFFF"}}}
+ {
+ "version": "next",
+ "imageUrl": "https://twxdyfr6nmnvjjym.public.blob.vercel-storage.com/scoreboard/latest-v2.png",
+ "button": {
+ "title": "Play 🏀",
+ "action": {
+ "type": "launch_frame",
+ "name": "Bball frame",
+ "url": "https://ballframe.vercel.app/",
+ "splashImageUrl": "https://ballframe.vercel.app/splash.png",
+ "splashBackgroundColor": "#FFFFFF"
+ }
+ }
+ }
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated settings.json
settings.json
Changed around line 1
+ {"version":"next","imageUrl":"https://twxdyfr6nmnvjjym.public.blob.vercel-storage.com/scoreboard/latest-v2.png","button":{"title":"Play 🏀","action":{"type":"launch_frame","name":"Bball frame","url":"https://ballframe.vercel.app/","splashImageUrl":"https://ballframe.vercel.app/splash.png","splashBackgroundColor":"#FFFFFF"}}}
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
created settings.json
settings.json
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 8: meta
-
- content='{"version":"next","imageUrl":"https://twxdyfr6nmnvjjym.public.blob.vercel-storage.com/scoreboard/latest-v2.png","button":{"title":"Play 🏀","action":{"type":"launch_frame","name":"Bball frame","url":"https://ballframe.vercel.app/","splashImageUrl":"https://ballframe.vercel.app/splash.png","splashBackgroundColor":"#FFFFFF"}}}'
- />
+
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 8: meta
-
+
+ content='{"version":"next","imageUrl":"https://twxdyfr6nmnvjjym.public.blob.vercel-storage.com/scoreboard/latest-v2.png","button":{"title":"Play 🏀","action":{"type":"launch_frame","name":"Bball frame","url":"https://ballframe.vercel.app/","splashImageUrl":"https://ballframe.vercel.app/splash.png","splashBackgroundColor":"#FFFFFF"}}}'
+ />
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 8: meta
-
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 7: metaTags
+
+
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 7: metaTags
- meta
- name fc:frame
- content {'version':'vNext','image':{'src':'https://tictac.framehub.pro/board.png','aspectRatio':'1:1'},'buttons':[{'label':'1','action':'post'},{'label':'2','action':'post'},{'label':'3','action':'post'},{'label':'4','action':'post'},{'label':'5','action':'post'},{'label':'6','action':'post'},{'label':'7','action':'post'},{'label':'8','action':'post'},{'label':'9','action':'post'}]}
+ Restore this version
updated head.scroll
head.scroll
Changed around line 9: meta
- content content {'version':'vNext','image':{'src':'https://tictac.framehub.pro/board.png','aspectRatio':'1:1'},'buttons':[{'label':'1','action':'post'},{'label':'2','action':'post'},{'label':'3','action':'post'},{'label':'4','action':'post'},{'label':'5','action':'post'},{'label':'6','action':'post'},{'label':'7','action':'post'},{'label':'8','action':'post'},{'label':'9','action':'post'}]}
+ content {'version':'vNext','image':{'src':'https://tictac.framehub.pro/board.png','aspectRatio':'1:1'},'buttons':[{'label':'1','action':'post'},{'label':'2','action':'post'},{'label':'3','action':'post'},{'label':'4','action':'post'},{'label':'5','action':'post'},{'label':'6','action':'post'},{'label':'7','action':'post'},{'label':'8','action':'post'},{'label':'9','action':'post'}]}
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 9: meta
- content {\"version\":\"vNext\",\"image\":{\"src\":\"https://tictac.framehub.pro/board.png\",\"aspectRatio\":\"1:1\"},\"buttons\":[{\"label\":\"1\",\"action\":\"post\"},{\"label\":\"2\",\"action\":\"post\"},{\"label\":\"3\",\"action\":\"post\"},{\"label\":\"4\",\"action\":\"post\"},{\"label\":\"5\",\"action\":\"post\"},{\"label\":\"6\",\"action\":\"post\"},{\"label\":\"7\",\"action\":\"post\"},{\"label\":\"8\",\"action\":\"post\"},{\"label\":\"9\",\"action\":\"post\"}]}"
+ content content {'version':'vNext','image':{'src':'https://tictac.framehub.pro/board.png','aspectRatio':'1:1'},'buttons':[{'label':'1','action':'post'},{'label':'2','action':'post'},{'label':'3','action':'post'},{'label':'4','action':'post'},{'label':'5','action':'post'},{'label':'6','action':'post'},{'label':'7','action':'post'},{'label':'8','action':'post'},{'label':'9','action':'post'}]}
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 1
+ importOnly
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 1
+ buildHtml
+ baseUrl https://tictac.framehub.pro
+ title Tic Tac Toe Frame
+ description Play Tic Tac Toe on Farcaster! Challenge your friends to a game of X's and O's.
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated index.scroll
index.scroll
Changed around line 1
- buildHtml
- baseUrl https://tictac.framehub.pro
- title Tic Tac Toe Frame
- description Play Tic Tac Toe on Farcaster! Challenge your friends to a game of X's and O's.
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated index.scroll
index.scroll
Changed around line 1
- import head.scroll
+ head.scroll
- head.scroll
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated index.scroll
index.scroll
Changed around line 4: import head.scroll
+ head.scroll
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 10: meta
- content https://tictacframehub.pro/api/frame
+ content https://tictac.framehub.pro/api/frame
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 7: meta
- content https://tictacframehub.pro/board.png
+ content https://tictac.framehub.pro/board.png
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated head.scroll
head.scroll
Changed around line 4: meta
- content {\"version\":\"vNext\",\"image\":{\"src\":\"https://tictacframehub.pro/board.png\",\"aspectRatio\":\"1:1\"},\"buttons\":[{\"label\":\"1\",\"action\":\"post\"},{\"label\":\"2\",\"action\":\"post\"},{\"label\":\"3\",\"action\":\"post\"},{\"label\":\"4\",\"action\":\"post\"},{\"label\":\"5\",\"action\":\"post\"},{\"label\":\"6\",\"action\":\"post\"},{\"label\":\"7\",\"action\":\"post\"},{\"label\":\"8\",\"action\":\"post\"},{\"label\":\"9\",\"action\":\"post\"}]}"
+ content {\"version\":\"vNext\",\"image\":{\"src\":\"https://tictac.framehub.pro/board.png\",\"aspectRatio\":\"1:1\"},\"buttons\":[{\"label\":\"1\",\"action\":\"post\"},{\"label\":\"2\",\"action\":\"post\"},{\"label\":\"3\",\"action\":\"post\"},{\"label\":\"4\",\"action\":\"post\"},{\"label\":\"5\",\"action\":\"post\"},{\"label\":\"6\",\"action\":\"post\"},{\"label\":\"7\",\"action\":\"post\"},{\"label\":\"8\",\"action\":\"post\"},{\"label\":\"9\",\"action\":\"post\"}]}"
ffff:207.243.92.34
ffff:207.243.92.34
5 days ago
updated index.scroll
index.scroll
Changed around line 1
- baseUrl https://tictacframehub.pro
+ baseUrl https://tictac.framehub.pro
root
root
5 days ago
Initial commit
api/frame.js
Changed around line 1
+ export default async function handler(req, res) {
+ if (req.method !== 'POST') {
+ return res.status(405).json({ error: 'Method not allowed' });
+ }
+
+ try {
+ const { untrustedData } = req.body;
+ const buttonIndex = untrustedData.buttonIndex - 1;
+
+ // Get current game state from database (implementation needed)
+ let gameState = await getGameState();
+
+ if (!gameState.board[buttonIndex] && !gameState.winner) {
+ gameState.board[buttonIndex] = gameState.currentPlayer;
+
+ // Check for winner
+ const winner = checkWinner(gameState.board);
+
+ // Update game state
+ if (winner) {
+ gameState.winner = winner;
+ } else {
+ gameState.currentPlayer = gameState.currentPlayer === 'X' ? 'O' : 'X';
+ }
+
+ // Save updated game state (implementation needed)
+ await saveGameState(gameState);
+ }
+
+ // Generate new board image (implementation needed)
+ const boardImageUrl = await generateBoardImage(gameState);
+
+ return res.status(200).json({
+ version: 'vNext',
+ image: {
+ src: boardImageUrl,
+ aspectRatio: '1:1'
+ },
+ buttons: [
+ { label: '1', action: 'post' },
+ { label: '2', action: 'post' },
+ { label: '3', action: 'post' },
+ { label: '4', action: 'post' },
+ { label: '5', action: 'post' },
+ { label: '6', action: 'post' },
+ { label: '7', action: 'post' },
+ { label: '8', action: 'post' },
+ { label: '9', action: 'post' }
+ ]
+ });
+ } catch (error) {
+ console.error('Frame API error:', error);
+ return res.status(500).json({ error: 'Internal server error' });
+ }
+ }
frame.scroll
Changed around line 1
+ main
+ class frameContainer
+ div
+ class frameContent
+ h1 Tic Tac Toe Frame
+ class frameTitle
+ div
+ class gameBoard
+ div
+ class cell
+ data-index 0
+ div
+ class cell
+ data-index 1
+ div
+ class cell
+ data-index 2
+ div
+ class cell
+ data-index 3
+ div
+ class cell
+ data-index 4
+ div
+ class cell
+ data-index 5
+ div
+ class cell
+ data-index 6
+ div
+ class cell
+ data-index 7
+ div
+ class cell
+ data-index 8
+ p
+ class gameStatus
+ Your turn! Select a cell (1-9)
head.scroll
Changed around line 1
+ metaTags
+ meta
+ name viewport
+ content width=device-width, initial-scale=1.0
+ meta
+ name fc:frame
+ content {\"version\":\"vNext\",\"image\":{\"src\":\"https://tictacframehub.pro/board.png\",\"aspectRatio\":\"1:1\"},\"buttons\":[{\"label\":\"1\",\"action\":\"post\"},{\"label\":\"2\",\"action\":\"post\"},{\"label\":\"3\",\"action\":\"post\"},{\"label\":\"4\",\"action\":\"post\"},{\"label\":\"5\",\"action\":\"post\"},{\"label\":\"6\",\"action\":\"post\"},{\"label\":\"7\",\"action\":\"post\"},{\"label\":\"8\",\"action\":\"post\"},{\"label\":\"9\",\"action\":\"post\"}]}"
+ meta
+ name fc:frame:image
+ content https://tictacframehub.pro/board.png
+ meta
+ name fc:frame:post_url
+ content https://tictacframehub.pro/api/frame
index.scroll
Changed around line 1
+ buildHtml
+ baseUrl https://tictacframehub.pro
+ import head.scroll
+ title Tic Tac Toe Frame
+ description Play Tic Tac Toe on Farcaster! Challenge your friends to a game of X's and O's.
+ style.css
+ frame.scroll
+ script.js
manifest.json
Changed around line 1
+ {
+ "version": "vNext",
+ "name": "Tic Tac Toe Frame",
+ "description": "Play Tic Tac Toe on Farcaster! Challenge your friends to a game of X's and O's.",
+ "image": {
+ "src": "https://tictacframehub.pro/board.png",
+ "aspectRatio": "1:1"
+ },
+ "buttons": [
+ { "label": "1", "action": "post" },
+ { "label": "2", "action": "post" },
+ { "label": "3", "action": "post" },
+ { "label": "4", "action": "post" },
+ { "label": "5", "action": "post" },
+ { "label": "6", "action": "post" },
+ { "label": "7", "action": "post" },
+ { "label": "8", "action": "post" },
+ { "label": "9", "action": "post" }
+ ],
+ "postUrl": "https://tictacframehub.pro/api/frame"
+ }
prompt.json
Changed around line 1
+ {
+ "id": "msg_018R34brjB2UaFBabm1VWSPB",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-3-5-sonnet-20241022",
+ "content": [
+ {
+ "type": "text",
+ "text": "I'll help you create a Tic Tac Toe Frame game. Here's a suggested domain and the implementation:\n\n---domain---\ntictacframehub.pro\n\n---index.scroll---\nbuildHtml\nbaseUrl https://tictacframehub.pro\nimport head.scroll\ntitle Tic Tac Toe Frame\ndescription Play Tic Tac Toe on Farcaster! Challenge your friends to a game of X's and O's.\nstyle.css\nframe.scroll\nscript.js\n\n---head.scroll---\nmetaTags\nmeta\n name viewport\n content width=device-width, initial-scale=1.0\nmeta\n name fc:frame\n content {\\\"version\\\":\\\"vNext\\\",\\\"image\\\":{\\\"src\\\":\\\"https://tictacframehub.pro/board.png\\\",\\\"aspectRatio\\\":\\\"1:1\\\"},\\\"buttons\\\":[{\\\"label\\\":\\\"1\\\",\\\"action\\\":\\\"post\\\"},{\\\"label\\\":\\\"2\\\",\\\"action\\\":\\\"post\\\"},{\\\"label\\\":\\\"3\\\",\\\"action\\\":\\\"post\\\"},{\\\"label\\\":\\\"4\\\",\\\"action\\\":\\\"post\\\"},{\\\"label\\\":\\\"5\\\",\\\"action\\\":\\\"post\\\"},{\\\"label\\\":\\\"6\\\",\\\"action\\\":\\\"post\\\"},{\\\"label\\\":\\\"7\\\",\\\"action\\\":\\\"post\\\"},{\\\"label\\\":\\\"8\\\",\\\"action\\\":\\\"post\\\"},{\\\"label\\\":\\\"9\\\",\\\"action\\\":\\\"post\\\"}]}\"\nmeta\n name fc:frame:image\n content https://tictacframehub.pro/board.png\nmeta\n name fc:frame:post_url\n content https://tictacframehub.pro/api/frame\n\n---frame.scroll---\nmain\n class frameContainer\n div\n class frameContent\n h1 Tic Tac Toe Frame\n class frameTitle\n div\n class gameBoard\n div\n class cell\n data-index 0\n div\n class cell\n data-index 1\n div\n class cell\n data-index 2\n div\n class cell\n data-index 3\n div\n class cell\n data-index 4\n div\n class cell\n data-index 5\n div\n class cell\n data-index 6\n div\n class cell\n data-index 7\n div\n class cell\n data-index 8\n p\n class gameStatus\n Your turn! Select a cell (1-9)\n\n---style.css---\n:root {\n --frame-bg: #1a1b26;\n --frame-text: #a9b1d6;\n --frame-accent: #7aa2f7;\n --frame-grid: #414868;\n --cell-hover: #565f89;\n --x-color: #f7768e;\n --o-color: #9ece6a;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: var(--frame-bg);\n color: var(--frame-text);\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\n.frameContainer {\n width: 100%;\n max-width: 600px;\n margin: 0 auto;\n padding: 20px;\n}\n\n.frameContent {\n background: rgba(255, 255, 255, 0.03);\n border-radius: 16px;\n padding: 24px;\n backdrop-filter: blur(10px);\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);\n}\n\n.frameTitle {\n font-size: 28px;\n font-weight: 700;\n margin-bottom: 24px;\n text-align: center;\n color: var(--frame-accent);\n text-shadow: 0 0 10px rgba(122, 162, 247, 0.3);\n}\n\n.gameBoard {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 8px;\n margin: 24px 0;\n background: var(--frame-grid);\n padding: 8px;\n border-radius: 12px;\n}\n\n.cell {\n aspect-ratio: 1;\n background: rgba(255, 255, 255, 0.05);\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n font-weight: bold;\n transition: all 0.2s ease;\n}\n\n.cell:hover {\n background: var(--cell-hover);\n transform: scale(0.98);\n}\n\n.cell.x {\n color: var(--x-color);\n}\n\n.cell.o {\n color: var(--o-color);\n}\n\n.gameStatus {\n text-align: center;\n font-size: 18px;\n margin-top: 16px;\n color: var(--frame-text);\n}\n\n@media (max-width: 480px) {\n .frameContainer {\n padding: 16px;\n }\n \n .frameTitle {\n font-size: 24px;\n }\n \n .cell {\n font-size: 28px;\n }\n}\n\n---script.js---\nlet gameState = {\n board: Array(9).fill(null),\n currentPlayer: 'X',\n winner: null\n};\n\nconst winPatterns = [\n [0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows\n [0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns\n [0, 4, 8], [2, 4, 6] // Diagonals\n];\n\nconst checkWinner = (board) => {\n for (const pattern of winPatterns) {\n const [a, b, c] = pattern;\n if (board[a] && board[a] === board[b] && board[a] === board[c]) {\n return board[a];\n }\n }\n return null;\n};\n\nconst handleCellClick = async (index) => {\n if (gameState.board[index] || gameState.winner) return;\n \n gameState.board[index] = gameState.currentPlayer;\n const cell = document.querySelector(`[data-index=\"${index}\"]`);\n cell.textContent = gameState.currentPlayer;\n cell.classList.add(gameState.currentPlayer.toLowerCase());\n \n const winner = checkWinner(gameState.board);\n if (winner) {\n gameState.winner = winner;\n document.querySelector('.gameStatus').textContent = `Player ${winner} wins!`;\n } else if (!gameState.board.includes(null)) {\n document.querySelector('.gameStatus').textContent = \"It's a draw!\";\n } else {\n gameState.currentPlayer = gameState.currentPlayer === 'X' ? 'O' : 'X';\n document.querySelector('.gameStatus').textContent = `Player ${gameState.currentPlayer}'s turn`;\n }\n};\n\ndocument.querySelectorAll('.cell').forEach((cell, index) => {\n cell.addEventListener('click', () => handleCellClick(index));\n});\n\ndocument.addEventListener('DOMContentLoaded', () => {\n document.querySelector('.gameStatus').textContent = `Player ${gameState.currentPlayer}'s turn`;\n});\n\n---api/frame.js---\nexport default async function handler(req, res) {\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' });\n }\n\n try {\n const { untrustedData } = req.body;\n const buttonIndex = untrustedData.buttonIndex - 1;\n \n // Get current game state from database (implementation needed)\n let gameState = await getGameState();\n \n if (!gameState.board[buttonIndex] && !gameState.winner) {\n gameState.board[buttonIndex] = gameState.currentPlayer;\n \n // Check for winner\n const winner = checkWinner(gameState.board);\n \n // Update game state\n if (winner) {\n gameState.winner = winner;\n } else {\n gameState.currentPlayer = gameState.currentPlayer === 'X' ? 'O' : 'X';\n }\n \n // Save updated game state (implementation needed)\n await saveGameState(gameState);\n }\n\n // Generate new board image (implementation needed)\n const boardImageUrl = await generateBoardImage(gameState);\n\n return res.status(200).json({\n version: 'vNext',\n image: {\n src: boardImageUrl,\n aspectRatio: '1:1'\n },\n buttons: [\n { label: '1', action: 'post' },\n { label: '2', action: 'post' },\n { label: '3', action: 'post' },\n { label: '4', action: 'post' },\n { label: '5', action: 'post' },\n { label: '6', action: 'post' },\n { label: '7', action: 'post' },\n { label: '8', action: 'post' },\n { label: '9', action: 'post' }\n ]\n });\n } catch (error) {\n console.error('Frame API error:', error);\n return res.status(500).json({ error: 'Internal server error' });\n }\n}\n\n---manifest.json---\n{\n \"version\": \"vNext\",\n \"name\": \"Tic Tac Toe Frame\",\n \"description\": \"Play Tic Tac Toe on Farcaster! Challenge your friends to a game of X's and O's.\",\n \"image\": {\n \"src\": \"https://tictacframehub.pro/board.png\",\n \"aspectRatio\": \"1:1\"\n },\n \"buttons\": [\n { \"label\": \"1\", \"action\": \"post\" },\n { \"label\": \"2\", \"action\": \"post\" },\n { \"label\": \"3\", \"action\": \"post\" },\n { \"label\": \"4\", \"action\": \"post\" },\n { \"label\": \"5\", \"action\": \"post\" },\n { \"label\": \"6\", \"action\": \"post\" },\n { \"label\": \"7\", \"action\": \"post\" },\n { \"label\": \"8\", \"action\": \"post\" },\n { \"label\": \"9\", \"action\": \"post\" }\n ],\n \"postUrl\": \"https://tictacframehub.pro/api/frame\"\n}\n\n---end---\n\nThis implementation creates a beautiful, responsive Tic Tac Toe game with a modern Tokyo Night-inspired color scheme. The game features:\n\n1. A 3x3 grid layout\n2. Smooth animations and hover effects\n3. Clear player turn indicators\n4. Win detection\n5. Responsive design for mobile devices\n6. Accessible button controls\n7. Clean, semantic HTML5 structure\n8. Modern CSS with custom properties\n9. Error handling and game state management\n\nThe frame will need additional backend implementation for:\n- Game state persistence\n- Board image generation\n- Player session management\n\nThe design uses a dark theme with carefully chosen colors for contrast and readability, with subtle animations and visual feedback for user interactions."
+ }
+ ],
+ "stop_reason": "end_turn",
+ "stop_sequence": null,
+ "usage": {
+ "input_tokens": 2191,
+ "cache_creation_input_tokens": 0,
+ "cache_read_input_tokens": 0,
+ "output_tokens": 2907
+ }
+ }
readme.scroll
Changed around line 1
+ # tictacframehub.pro.framehub.pro
+
+ frame generated by Claude from prompt: A tic tac toe frame
script.js
Changed around line 1
+ let gameState = {
+ board: Array(9).fill(null),
+ currentPlayer: 'X',
+ winner: null
+ };
+
+ const winPatterns = [
+ [0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows
+ [0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns
+ [0, 4, 8], [2, 4, 6] // Diagonals
+ ];
+
+ const checkWinner = (board) => {
+ for (const pattern of winPatterns) {
+ const [a, b, c] = pattern;
+ if (board[a] && board[a] === board[b] && board[a] === board[c]) {
+ return board[a];
+ }
+ }
+ return null;
+ };
+
+ const handleCellClick = async (index) => {
+ if (gameState.board[index] || gameState.winner) return;
+
+ gameState.board[index] = gameState.currentPlayer;
+ const cell = document.querySelector(`[data-index="${index}"]`);
+ cell.textContent = gameState.currentPlayer;
+ cell.classList.add(gameState.currentPlayer.toLowerCase());
+
+ const winner = checkWinner(gameState.board);
+ if (winner) {
+ gameState.winner = winner;
+ document.querySelector('.gameStatus').textContent = `Player ${winner} wins!`;
+ } else if (!gameState.board.includes(null)) {
+ document.querySelector('.gameStatus').textContent = "It's a draw!";
+ } else {
+ gameState.currentPlayer = gameState.currentPlayer === 'X' ? 'O' : 'X';
+ document.querySelector('.gameStatus').textContent = `Player ${gameState.currentPlayer}'s turn`;
+ }
+ };
+
+ document.querySelectorAll('.cell').forEach((cell, index) => {
+ cell.addEventListener('click', () => handleCellClick(index));
+ });
+
+ document.addEventListener('DOMContentLoaded', () => {
+ document.querySelector('.gameStatus').textContent = `Player ${gameState.currentPlayer}'s turn`;
+ });
style.css
Changed around line 1
+ :root {
+ --frame-bg: #1a1b26;
+ --frame-text: #a9b1d6;
+ --frame-accent: #7aa2f7;
+ --frame-grid: #414868;
+ --cell-hover: #565f89;
+ --x-color: #f7768e;
+ --o-color: #9ece6a;
+ }
+
+ * {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+ background: var(--frame-bg);
+ color: var(--frame-text);
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .frameContainer {
+ width: 100%;
+ max-width: 600px;
+ margin: 0 auto;
+ padding: 20px;
+ }
+
+ .frameContent {
+ background: rgba(255, 255, 255, 0.03);
+ border-radius: 16px;
+ padding: 24px;
+ backdrop-filter: blur(10px);
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+ }
+
+ .frameTitle {
+ font-size: 28px;
+ font-weight: 700;
+ margin-bottom: 24px;
+ text-align: center;
+ color: var(--frame-accent);
+ text-shadow: 0 0 10px rgba(122, 162, 247, 0.3);
+ }
+
+ .gameBoard {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 8px;
+ margin: 24px 0;
+ background: var(--frame-grid);
+ padding: 8px;
+ border-radius: 12px;
+ }
+
+ .cell {
+ aspect-ratio: 1;
+ background: rgba(255, 255, 255, 0.05);
+ border-radius: 8px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 32px;
+ font-weight: bold;
+ transition: all 0.2s ease;
+ }
+
+ .cell:hover {
+ background: var(--cell-hover);
+ transform: scale(0.98);
+ }
+
+ .cell.x {
+ color: var(--x-color);
+ }
+
+ .cell.o {
+ color: var(--o-color);
+ }
+
+ .gameStatus {
+ text-align: center;
+ font-size: 18px;
+ margin-top: 16px;
+ color: var(--frame-text);
+ }
+
+ @media (max-width: 480px) {
+ .frameContainer {
+ padding: 16px;
+ }
+
+ .frameTitle {
+ font-size: 24px;
+ }
+
+ .cell {
+ font-size: 28px;
+ }
+ }