diff --git a/games/Number-Sliding-Puzzle/Number-Sliding-Puzzle.py b/games/Number-Sliding-Puzzle/Number-Sliding-Puzzle.py index e1a389a4..85b9d943 100644 --- a/games/Number-Sliding-Puzzle/Number-Sliding-Puzzle.py +++ b/games/Number-Sliding-Puzzle/Number-Sliding-Puzzle.py @@ -1,5 +1,12 @@ +import sys +import os + +# Point Python to the root directory so it can find the utils folder +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) +from utils.validation import get_int, get_yes_no import random + print("🧩 Emoji Sliding Puzzle Game 🧩") while True: @@ -37,14 +44,7 @@ print("\nšŸŽ‰ Congratulations! You solved the puzzle!") break - try: - choice_str = input("\nšŸŽÆ Enter number to move: ").strip() - if not choice_str: - continue - choice = int(choice_str) - except ValueError: - print("āŒ Please enter a valid number!") - continue + choice = get_int("\nšŸŽÆ Enter number to move: ", min_value=1, max_value=8) empty_row = 0 empty_col = 0 @@ -75,10 +75,6 @@ print("\nšŸ‘‹ Thanks for playing Emoji Sliding Puzzle!\n") - while True: - replay = input("šŸ”„ Play again? (y/n): ").strip().lower() - if replay in ['y', 'yes', 'n', 'no']: - break - print("āš ļø Invalid input. Enter 'y' or 'n'.") - if replay in ['n', 'no']: + # get_yes_no loops automatically and returns True for 'y' and False for 'n' + if not get_yes_no("\nšŸ”„ Play again? (y/n): "): break \ No newline at end of file diff --git a/web-app/js/projects.js b/web-app/js/projects.js index 65e8486c..539371d1 100644 --- a/web-app/js/projects.js +++ b/web-app/js/projects.js @@ -2,74 +2,105 @@ // Each project's HTML and logic lives in its own file under js/projects/ const projectInstructions = { - // Project instructions moved to modular files under js/projects/ + // Project instructions moved to modular files under js/projects/ }; - function toPascalCase(slug) { - return slug.split(/[^a-zA-Z0-9]+/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(''); + return slug + .split(/[^a-zA-Z0-9]+/) + .map((s) => s.charAt(0).toUpperCase() + s.slice(1)) + .join(""); } function getProjectHTML(projectName) { - const fnName = 'get' + toPascalCase(projectName) + 'HTML'; - if (typeof window[fnName] === 'function') return window[fnName](); - return `

Project '${projectName}' content not available.

`; + const fnName = "get" + toPascalCase(projectName) + "HTML"; + + try { + // 1. Check if the project module actually loaded + if (typeof window[fnName] === "function") { + return window[fnName](); + } else { + // Throw an error so the catch block handles the missing module + throw new Error(`Module ${fnName} is missing or failed to initialize.`); + } + } catch (error) { + // 2. Log it for the developers + console.warn(`[Project Loader] Failed to load ${projectName}:`, error); + + // 3. Return a user-friendly UI error state for the user + return ` +
+
āš ļø
+

+ SYSTEM ERROR: PROJECT OFFLINE +

+

+ We couldn't initialize the interactive environment for ${projectName}. The underlying module may be missing or corrupted. +

+ +
+ `; + } } function getProjectInstructions(projectName) { - // Modules may provide richer instructions; fall back to a simple hint. - const fnName = 'get' + toPascalCase(projectName) + 'Instructions'; - if (typeof window[fnName] === 'function') return window[fnName](); - return { title: projectName, steps: ['Open the project and follow on-screen instructions.'] }; + // Modules may provide richer instructions; fall back to a simple hint. + const fnName = "get" + toPascalCase(projectName) + "Instructions"; + if (typeof window[fnName] === "function") return window[fnName](); + return { + title: projectName, + steps: ["Open the project and follow on-screen instructions."], + }; } - function initializeProject(projectName) { + const initializers = { + "tic-tac-toe": "initTicTacToe", + "rock-paper-scissor": "initRockPaperScissor", + "dice-rolling": "initDiceRolling", + "coin-flip": "initCoinFlip", + "blackjack-21": "initBlackjack", + "number-guessing": "initNumberGuessing", + hangman: "initHangman", + "word-scramble": "initWordScramble", + flames: "initFlames", + "dots-boxes": "initDotsBoxes", + "emoji-memory": "initEmojiMemoryGame", + fibonacci: "initFibonacci", + "binary-search": "initBinarySearch", + "bubble-sort": "initBubbleSort", + "progression-recognizer": "initProgressionRecognizer", + "pascal-triangle": "initPascalTriangle", + armstrong: "initArmstrong", + calculator: "initCalculator", + collatz: "initCollatz", + "prime-analyzer": "initPrimeAnalyzer", + "projectile-motion": "initProjectileMotion", + "coordinate-polar-transform": "initCoordinatePolarTransform", + "derivative-calculator": "initDerivativeCalculator", + "morse-code": "initMorseCode", + "tower-of-hanoi": "initTowerOfHanoi", + "number-converter": "initNumberConverter", + "typing-speed-tester": "initTypingSpeedTester", + "snake-game": "initSnakeGame", + "password-forge": "initPasswordForge", + "spot-the-difference": "initSpotTheDifference", + "whack-a-mole": "initWhackaMole", + "flappy-game": "initFlappyGame", + "productive-pet": "initProductivePet", + "simon-says": "initSimonSays", + "2048-game": "init2048Game", + "color-palette": "initColorPalette", + "math-quiz": "initMathQuiz", + "resume-analyzer": "initAIResumeAnalyzer", + "caesar-cipher": "initCaesarCipher", + }; - const initializers = { - 'tic-tac-toe': 'initTicTacToe', - 'rock-paper-scissor': 'initRockPaperScissor', - 'dice-rolling': 'initDiceRolling', - 'coin-flip': 'initCoinFlip', - 'blackjack-21': 'initBlackjack', - 'number-guessing': 'initNumberGuessing', - 'hangman': 'initHangman', - 'word-scramble': 'initWordScramble', - 'flames': 'initFlames', - 'dots-boxes': 'initDotsBoxes', - 'emoji-memory': 'initEmojiMemoryGame', - 'fibonacci': 'initFibonacci', - 'binary-search': 'initBinarySearch', - 'bubble-sort': 'initBubbleSort', - 'progression-recognizer': 'initProgressionRecognizer', - 'pascal-triangle': 'initPascalTriangle', - 'armstrong': 'initArmstrong', - 'calculator': 'initCalculator', - 'collatz': 'initCollatz', - 'prime-analyzer': 'initPrimeAnalyzer', - 'projectile-motion': 'initProjectileMotion', - 'coordinate-polar-transform': 'initCoordinatePolarTransform', - 'derivative-calculator': 'initDerivativeCalculator', - 'morse-code': 'initMorseCode', - 'tower-of-hanoi': 'initTowerOfHanoi', - 'number-converter': 'initNumberConverter', - 'typing-speed-tester': 'initTypingSpeedTester', - 'snake-game': 'initSnakeGame', - 'password-forge': 'initPasswordForge', - 'spot-the-difference': 'initSpotTheDifference', - 'whack-a-mole': 'initWhackaMole', - 'flappy-game': 'initFlappyGame', - 'productive-pet': 'initProductivePet', - 'simon-says': 'initSimonSays', - '2048-game': 'init2048Game', - 'color-palette': 'initColorPalette', - 'math-quiz': 'initMathQuiz', - 'resume-analyzer': 'initAIResumeAnalyzer', - 'caesar-cipher': 'initCaesarCipher' - }; - - const initializerName = initializers[projectName]; - if (initializerName && typeof window[initializerName] === 'function') { - window[initializerName](); - } + const initializerName = initializers[projectName]; + if (initializerName && typeof window[initializerName] === "function") { + window[initializerName](); + } }