🧩 Thematic Outline Puzzles

Core Source Code & AI-Powered Puzzle Generation Implementation

React 19.1+ TypeScript Gemini AI Imagen 4.0 Game Logic

🔍 About This Code Showcase

This curated code snippet demonstrates how the Thematic Outline Puzzles transforms any theme into interactive AI-generated puzzle experiences with advanced game mechanics.

Full deployment scripts, API integrations, and proprietary details are omitted for clarity and security. This showcase highlights the core puzzle generation, AI integration, and interactive gameplay algorithms.

🎮 Core Algorithm: Interactive Puzzle Game Engine

The foundation of Thematic Outline Puzzles is its ability to generate themed puzzle images using AI, create interactive puzzle pieces, and manage complex game state with smooth user interactions:

🧩 App.tsx - Main Puzzle Game Controller
import React, { useState, useCallback } from 'react'; import { PuzzleGenerator } from './components/PuzzleGenerator'; import { PuzzleBoard } from './components/PuzzleBoard'; import { generatePuzzleImage } from './services/geminiService'; import { Difficulty } from './types'; type AppState = 'CONFIG' | 'LOADING' | 'PLAYING'; export default function App() { const [appState, setAppState] = useState<AppState>('CONFIG'); const [puzzleImage, setPuzzleImage] = useState<string | null>(null); const [gridSize, setGridSize] = useState<Difficulty>(Difficulty.EASY); const [theme, setTheme] = useState<string>(''); // Generate AI-powered puzzle from any theme const handleGeneratePuzzle = useCallback(async ( newTheme: string, difficulty: Difficulty ) => { setAppState('LOADING'); setError(null); setTheme(newTheme); setGridSize(difficulty); try { // Create optimized prompt for puzzle-style imagery const prompt = `A vibrant and clear, minimalist outline-style, cartoon illustration of ${newTheme}. The image should be very simple, with thick, bold outlines and distinct shapes, suitable for a children's puzzle. Centered subject, plain background, square aspect ratio.`; // Generate AI image using Imagen 4.0 const imageUrl = await generatePuzzleImage(prompt); setPuzzleImage(imageUrl); setAppState('PLAYING'); } catch (err) { setError('Failed to generate image. Please try a different theme.'); setAppState('CONFIG'); console.error(err); } }, []); // Reset game state for new puzzle const handleNewPuzzle = () => { setAppState('CONFIG'); setPuzzleImage(null); setError(null); }; // Dynamic content rendering based on game state const renderContent = () => { switch (appState) { case 'LOADING': return <Spinner message={`Creating a puzzle about "${theme}"...`} />; case 'PLAYING': if (puzzleImage) { return ( <PuzzleBoard imageSrc={puzzleImage} gridSize={gridSize} onNewPuzzle={handleNewPuzzle} theme={theme} /> ); } // Fallback to config if image is missing return <PuzzleGenerator onGenerate={handleGeneratePuzzle} error={error} />; case 'CONFIG': default: return <PuzzleGenerator onGenerate={handleGeneratePuzzle} error={error} />; } }; return ( <div className="min-h-screen bg-slate-900 text-slate-100 flex flex-col"> <header className="w-full max-w-4xl text-center mb-8"> <h1 className="text-4xl md:text-5xl font-bold gradient-text"> Thematic Outline Puzzles </h1> <p className="text-slate-400 text-lg"> Turn any theme into a fun, interactive puzzle. </p> </header> <main>{renderContent()}</main> </div> ); }

🤖 AI Image Generation Service

The AI service leverages Imagen 4.0 to create puzzle-optimized illustrations with specific prompting strategies for educational content:

🎨 geminiService.ts - AI Image Generation Pipeline
import { GoogleGenAI } from "@google/genai"; if (!process.env.API_KEY) { throw new Error("API_KEY environment variable not set"); } const ai = new GoogleGenAI({ apiKey: process.env.API_KEY }); // Generate puzzle-optimized images using Imagen 4.0 export async function generatePuzzleImage(prompt: string): Promise<string> { try { // Call Imagen 4.0 with puzzle-specific configuration const response = await ai.models.generateImages({ model: 'imagen-4.0-generate-001', prompt: prompt, config: { numberOfImages: 1, outputMimeType: 'image/png', aspectRatio: '1:1', // Square format for optimal puzzle pieces safetyFilterLevel: 'BLOCK_MOST', // Child-safe content }, }); // Validate response and extract image data if (response.generatedImages && response.generatedImages.length > 0) { const base64ImageBytes: string = response.generatedImages[0].image.imageBytes; // Return base64 data URL for immediate canvas use return `data:image/png;base64,${base64ImageBytes}`; } else { throw new Error("No images were generated by the API."); } } catch (error) { console.error("Error generating image with Gemini AI:", error); throw new Error("Failed to generate puzzle image."); } } // Advanced prompt engineering for puzzle optimization export function createPuzzlePrompt(theme: string, difficulty: Difficulty): string { const basePrompt = `A vibrant and clear, minimalist outline-style, cartoon illustration of ${theme}`; const stylePrompts = { [Difficulty.EASY]: "very simple with extra thick, bold outlines (4-5px), large shapes, minimal detail, perfect for toddlers", [Difficulty.MEDIUM]: "simple with clear, thick outlines (2-3px), moderate detail, suitable for children", [Difficulty.HARD]: "detailed with fine outlines (1-2px), intricate patterns, suitable for adults" }; return `${basePrompt}. The image should be ${stylePrompts[difficulty]}. Centered subject, plain white background, square aspect ratio. Black and white line art style, no shading or color fills.`; }

🧩 Advanced Puzzle Board Logic

The puzzle board implements sophisticated piece management, drag-and-drop mechanics, and real-time solution detection:

🎯 PuzzleBoard.tsx - Interactive Game Mechanics
import React, { useState, useEffect, useCallback } from 'react'; import { PuzzlePiece as PuzzlePieceType } from '../types'; interface PuzzleBoardProps { imageSrc: string; gridSize: number; theme: string; onNewPuzzle: () => void; } export function PuzzleBoard({ imageSrc, gridSize, theme, onNewPuzzle }: PuzzleBoardProps) { const [pieces, setPieces] = useState<PuzzlePieceType[]>([]); const [isSolved, setIsSolved] = useState(false); const [draggedItem, setDraggedItem] = useState<PuzzlePieceType | null>(null); // Fisher-Yates shuffle algorithm for fair randomization const shufflePieces = useCallback((arr: PuzzlePieceType[]) => { const shuffled = [...arr]; for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); // Swap current indices to randomize positions [shuffled[i].currentIndex, shuffled[j].currentIndex] = [shuffled[j].currentIndex, shuffled[i].currentIndex]; } return shuffled; }, []); // Initialize puzzle with proper CSS background positioning const initializePuzzle = useCallback(() => { const newPieces: PuzzlePieceType[] = []; for (let i = 0; i < gridSize * gridSize; i++) { const row = Math.floor(i / gridSize); const col = i % gridSize; // Calculate CSS background-position for seamless image display newPieces.push({ id: i, originalIndex: i, currentIndex: i, style: { backgroundPosition: `${(col * 100) / (gridSize - 1)}% ${(row * 100) / (gridSize - 1)}%`, backgroundSize: `${gridSize * 100}% ${gridSize * 100}%`, }, }); } // Apply smart shuffling and reset game state setPieces(shufflePieces(newPieces)); setIsSolved(false); }, [gridSize, shufflePieces]); // Real-time solution detection with O(n) efficiency useEffect(() => { const checkSolved = () => { if (pieces.length === 0) return false; return pieces.every(p => p.currentIndex === p.originalIndex); }; if (checkSolved()) { setIsSolved(true); // Trigger celebration animation setTimeout(() => { alert(`🎉 Congratulations! You solved the "${theme}" puzzle!`); }, 500); } }, [pieces, theme]); // Advanced drag-and-drop with touch support const handleDragStart = (piece: PuzzlePieceType) => { setDraggedItem(piece); }; const handleDrop = (targetPiece: PuzzlePieceType) => { if (!draggedItem || draggedItem.id === targetPiece.id) return; // Swap pieces with smooth state transition setPieces(currentPieces => { const newPieces = [...currentPieces]; const draggedIndex = newPieces.findIndex(p => p.id === draggedItem.id); const targetIndex = newPieces.findIndex(p => p.id === targetPiece.id); // Swap current positions [newPieces[draggedIndex].currentIndex, newPieces[targetIndex].currentIndex] = [newPieces[targetIndex].currentIndex, newPieces[draggedIndex].currentIndex]; return newPieces; }); setDraggedItem(null); }; // Initialize puzzle on component mount and image change useEffect(() => { initializePuzzle(); }, [initializePuzzle]); return ( <div className="puzzle-container"> <div className={`puzzle-grid grid-${gridSize}`} style={{ gridTemplateColumns: `repeat(${gridSize}, 1fr)`, gridTemplateRows: `repeat(${gridSize}, 1fr)` }} > {pieces .sort((a, b) => a.currentIndex - b.currentIndex) .map(piece => ( <PuzzlePiece key={piece.id} piece={piece} imageSrc={imageSrc} onDragStart={handleDragStart} onDrop={handleDrop} isDragging={draggedItem?.id === piece.id} /> ))} </div> {isSolved && ( <div className="celebration-overlay"> <h2>🎉 Puzzle Complete! 🎉</h2> <button onClick={onNewPuzzle}>Create New Puzzle</button> </div> )} </div> ); }

⚙️ Technical Implementation Notes

Key Algorithms & Innovations

Why This Approach Works