import React, { useState, useEffect, useCallback } from 'react'; import { Button } from '@/components/ui/button'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import SocialShare from '@/components/SocialShare'; const POWERS_OF_THREE = [2187, 729, 243, 81, 27, 9, 3, 1]; // 3^7 to 3^0 interface TernaryNumberGameProps { showSocialShare?: boolean; } const TernaryNumberGame: React.FC = ({ showSocialShare = true }) => { const [targetNumber, setTargetNumber] = useState(0); const [cardValues, setCardValues] = useState(new Array(8).fill(0)); // 0, 1, or 2 for each position const [currentSum, setCurrentSum] = useState(0); const [timer, setTimer] = useState(0); const [isGameActive, setIsGameActive] = useState(false); const [isGameWon, setIsGameWon] = useState(false); const [hasGameStarted, setHasGameStarted] = useState(false); const [highScore, setHighScore] = useState(null); // Load high score from localStorage on component mount useEffect(() => { const savedHighScore = localStorage.getItem('ternary-game-high-score'); if (savedHighScore) { setHighScore(parseInt(savedHighScore)); } }, []); // Generate a random number expressible with up to 8 ternary digits const generateRandomTarget = () => { // Generate random ternary digits (0, 1, or 2) for each position const ternaryDigits = Array.from({ length: 8 }, () => Math.floor(Math.random() * 3)); // Convert to decimal return ternaryDigits.reduce((sum, digit, index) => sum + digit * POWERS_OF_THREE[index], 0); }; // Start new game const startNewGame = useCallback(() => { const newTarget = generateRandomTarget(); setTargetNumber(newTarget); setCardValues(new Array(8).fill(0)); setCurrentSum(0); setTimer(0); setIsGameActive(true); setIsGameWon(false); setHasGameStarted(true); }, []); // Start game for the first time const startGame = () => { startNewGame(); }; // Timer effect useEffect(() => { let interval: NodeJS.Timeout; if (isGameActive && !isGameWon) { interval = setInterval(() => { setTimer(prev => prev + 0.1); }, 100); } return () => clearInterval(interval); }, [isGameActive, isGameWon]); // Check for win condition useEffect(() => { if (currentSum === targetNumber && isGameActive) { setIsGameActive(false); setIsGameWon(true); // Update high score const currentTime = Math.round(timer * 10) / 10; if (highScore === null || currentTime < highScore) { setHighScore(currentTime); localStorage.setItem('ternary-game-high-score', currentTime.toString()); } } }, [currentSum, targetNumber, isGameActive, timer, highScore]); // Calculate current sum useEffect(() => { const sum = cardValues.reduce((acc, value, index) => { return acc + value * POWERS_OF_THREE[index]; }, 0); setCurrentSum(sum); }, [cardValues]); const toggleCard = (index: number) => { if (!isGameActive || isGameWon) return; setCardValues(prev => { const newValues = [...prev]; newValues[index] = (newValues[index] + 1) % 3; // Cycle through 0, 1, 2 return newValues; }); }; // Convert number to ternary string for display const toTernary = (num: number) => { if (num === 0) return '0'; let result = ''; let n = num; while (n > 0) { result = (n % 3) + result; n = Math.floor(n / 3); } return result; }; return (

Ternary Number Representation

Click the cards to cycle through 0, 1, or 2 copies of each power of three to match the target!

{highScore !== null && ( Best Time: {highScore}s )}
{/* Cards representing powers of three */}
{POWERS_OF_THREE.map((power, index) => (
toggleCard(index)} > {cardValues[index] === 0 ? '0' : cardValues[index]} ×{power} 3^{7-index}
))}
{/* Sum display boxes */}

Current Sum

targetNumber ? "text-red-600" : "text-foreground"}`}>{currentSum}

Target Sum

{!hasGameStarted ? "🎯" : isGameWon ? toTernary(targetNumber) : targetNumber}
{/* Timer and controls */}
Time: {Math.round(timer * 10) / 10}s
{isGameWon && (
Congratulations! 🎉
Your score: {Math.round(timer * 10) / 10} seconds
{highScore === Math.round(timer * 10) / 10 && ( New High Score! 🏆 )}
)}
{showSocialShare && ( )}
); }; export default TernaryNumberGame;