diff --git a/Hangman/Hangman.js b/Hangman/Hangman.js index 9686b87..d18ec17 100644 --- a/Hangman/Hangman.js +++ b/Hangman/Hangman.js @@ -1,140 +1,178 @@ +const readline = require("readline/promises"); + class Colors { constructor() { - this.red = 91 - this.green = 92 - this.blue = 34 - this.cian = 96 - this.yellow = 93 + this.red = 91; + this.green = 92; + this.blue = 34; + this.cian = 96; + this.yellow = 93; } } class Game { constructor(word, colors, availChars) { - this.word = word - this.colors = colors - this.availChars = availChars - this.lives = 8 - this.toGuess = 0 - this.playedChars = new Set() + this.word = word; + this.colors = colors; + this.availChars = availChars; + this.lives = 8; + this.toGuess = 0; + this.playedChars = new Set(); } } class Hangman { constructor(args) { - this.db = args.locale - this.words = args.words.words - this.pics = args.pics - this.colors = args.colors - this.input = args.input - this.output = args.output + this.db = args.locale; + this.words = args.words.words; + this.pics = args.pics; + this.colors = args.colors; + this.rl = args.rl; } - play() { - const availChars = this.getUniqueChars(this.words) - const randWord = () => this.words[Math.floor(Math.random() * this.words.length)] - this.game = new Game(randWord().split(""), this.colors, availChars) + async play() { + const availChars = this.getUniqueChars(this.words); + const word = this.getRandomWord(); + this.game = new Game(word.split(""), this.colors, availChars); - this.output.write(this.clr(`\n ${this.db.hangman}\n`, this.game.colors.green)) + this.write(this.clr(`\n ${this.db.hangman}\n`, this.colors.green)); - this.game.playedChars.add(this.game.word[0]) - this.game.playedChars.add(this.game.word[this.game.word.length - 1]) + this.game.playedChars.add(this.game.word[0]); + this.game.playedChars.add(this.game.word[this.game.word.length - 1]); - this.showPrompt(this.obf(this.game.word, this.game.playedChars), this.pic()) - this.input.on('data', (data) => { - this.guess(data.trim().toLowerCase()) - }) - } + await this.showPrompt(); - rePlay() { - this.input.on('data', (data) => { - this.output.write(this.clr("\n ++++++++++++++++++++++++++++++\n", this.game.colors.blue)) - this.play() - }) + while (true) { + const guess = await this.rl.question(this.clr(`\n ${this.db.guess} `, this.colors.yellow)); + const cleaned = guess.trim().toLowerCase(); + + if (cleaned.length !== 1) { + await this.showPrompt(this.clr(`\n ${this.db.one_char}`, this.colors.red)); + continue; + } + + const status = await this.processGuess(cleaned); + if (status === "won" || status === "lost") { + await this.askReplay(); + break; + } + } } - showPrompt(obfWord, msg) { - this.output.write(this.clr("\n ++++++++++++++++++++++++++++++\n", this.game.colors.blue)) - if (msg != null) { - this.output.write(msg + "\n") + async askReplay() { + this.write(this.clr("\n ++++++++++++++++++++++++++++++\n", this.colors.blue)); + while (true) { + const choice = await this.rl.question( + this.clr(`\n ${this.db.play_again} (R) / ${this.db.quit} (Q): `, this.colors.yellow) + ); + + const trimmed = choice.trim().toUpperCase(); + if (trimmed === "R") { + return this.play(); + } else if (trimmed === "Q") { + this.write(this.clr(`\n ${this.db.goodbye}\n`, this.colors.green)); + process.exit(0); + } else { + this.write(this.clr(`\n ${this.db.invalid_choice}\n`, this.colors.red)); + } } - this.output.write(this.clr(`\n ${this.db.letters} ${Array.from(this.game.playedChars).join(", ")}\n`, this.game.colors.green)) - this.output.write(this.clr(`\n ${obfWord}\n`, this.colors.cian)) + } + + async showPrompt(message = null) { + this.write(this.clr("\n ++++++++++++++++++++++++++++++\n", this.colors.blue)); + if (message) this.write(message + "\n"); - this.output.write(this.clr(`\n ${this.db.guess} `, this.colors.yellow)) + const obfWord = this.obfuscate(this.game.word, this.game.playedChars); + this.write(this.clr(`\n ${this.db.letters} ${Array.from(this.game.playedChars).join(", ")}\n`, this.colors.green)); + this.write(this.clr(`\n ${obfWord}\n`, this.colors.cian)); + this.write(this.pic()); } getUniqueChars(arr) { - const uniqueChars = new Set() - for (const str of arr) { - for (const char of str) { - uniqueChars.add(char) + const set = new Set(); + for (const word of arr) { + for (const char of word) { + set.add(char.toLowerCase()); } } - return uniqueChars + return set; + } + + getRandomWord() { + return this.words[Math.floor(Math.random() * this.words.length)]; } clr(text, color) { - return color == null ? text : "\x1b[" + color + "m" + text + "\x1b[0m" + return color == null ? text : `\x1b[${color}m${text}\x1b[0m`; } - obf(word, playedChars) { - const output = [] - let toGuess = 0 + obfuscate(word, playedChars) { + let result = []; + let toGuess = 0; + for (const c of word) { if (playedChars.has(c)) { - output.push(c) + result.push(c); } else if (c === " ") { - output.push(c) + result.push(" "); } else { - toGuess += 1 - output.push("_") + result.push("_"); + toGuess++; } } - this.game.toGuess = toGuess - return output.join(" ") + + this.game.toGuess = toGuess; + return result.join(" "); } pic() { - return "\n" + this.pics[this.game.lives].join('\n') + return "\n" + this.pics[this.game.lives].join('\n') + "\n"; } - guess(c) { + async processGuess(c) { if (this.game.playedChars.has(c)) { - this.showPrompt(this.obf(this.game.word, this.game.playedChars), - this.clr(`\n ${this.db.played}`, this.game.colors.red)) - } else if (this.game.availChars.has(c)) { - this.game.playedChars.add(c) - if (this.game.word.includes(c)) { - const obfWord = this.obf(this.game.word, this.game.playedChars) - if (this.game.toGuess < 1) { - this.output.write(this.clr("\n ++++++++++++++++++++++++++++++\n", this.game.colors.blue)) - this.output.write(this.clr(`\n ${this.game.word.join('')}\n`, this.colors.cian)) - this.output.write(this.clr(`\n ${this.db.you_won}\n\n`, this.game.colors.green)) - // process.exit(0) - this.rePlay() - } else { - this.showPrompt(obfWord, null) - } + await this.showPrompt(this.clr(`\n ${this.db.played}`, this.colors.red)); + return; + } + + if (!this.game.availChars.has(c)) { + await this.showPrompt( + this.clr(`\n ${this.db.one_char} `, this.colors.red) + + this.clr(`\n [${Array.from(this.game.availChars).sort().join(", ")}]`, this.colors.green) + ); + return; + } + + this.game.playedChars.add(c); + + if (this.game.word.includes(c)) { + const obfWord = this.obfuscate(this.game.word, this.game.playedChars); + if (this.game.toGuess < 1) { + this.write(this.clr("\n ++++++++++++++++++++++++++++++\n", this.colors.blue)); + this.write(this.clr(`\n ${this.game.word.join("")}\n`, this.colors.cian)); + this.write(this.clr(`\n ${this.db.you_won}\n\n`, this.colors.green)); + return "won"; } else { - this.game.lives -= 1 - if (this.game.lives < 1) { - this.output.write(this.clr("\n ++++++++++++++++++++++++++++++\n", this.game.colors.blue)) - this.output.write(this.clr(`\n ${this.game.word.join('')}\n`, this.colors.cian)) - this.output.write(this.clr(`\n ${this.db.you_lose}\n\n`, this.game.colors.red)) - // process.exit(0) - this.rePlay() - } else { - this.showPrompt(this.obf(this.game.word, this.game.playedChars), this.pic()) - } + await this.showPrompt(); + return; } } else { - this.showPrompt(this.obf(this.game.word, this.game.playedChars), - this.clr(`\n ${this.db.one_char} `, this.game.colors.red) + - this.clr(`\n [${Array.from(this.game.availChars).sort().join(', ')}]`, this.colors.green)) + this.game.lives--; + if (this.game.lives < 1) { + this.write(this.clr("\n ++++++++++++++++++++++++++++++\n", this.colors.blue)); + this.write(this.clr(`\n ${this.game.word.join("")}\n`, this.colors.cian)); + this.write(this.clr(`\n ${this.db.you_lose}\n\n`, this.colors.red)); + return "lost"; + } else { + await this.showPrompt(); + return; + } } } -} -if (typeof module !== 'undefined') { - module.exports = { Hangman: Hangman, Colors: Colors } + write(str) { + process.stdout.write(str); + } } + +module.exports = { Hangman, Colors }; \ No newline at end of file diff --git a/Hangman/hangman.py b/Hangman/hangman.py index 4622513..fa370c8 100644 --- a/Hangman/hangman.py +++ b/Hangman/hangman.py @@ -1,99 +1,125 @@ -import re -import sys -from random import randint +# -*- coding: utf-8 -*- + +import os import json import pyfiglet +import re +from random import randint -language = "en" -if(len(sys.argv) > 1): - language = sys.argv[1] - -print(pyfiglet.figlet_format("Hello!")) - -with open("locales/" + language + "/locale.json") as json_file: - db = json.load(json_file) - -with open("locales/" + language + "/words/all.json") as json_file: - db_words = json.load(json_file) - -word = [] -wordl = 0 -obfWord = [] -playedLetters = [] -guessesRemaining = 8 -words = db_words["words"] - -def showLetter(data): - global word, wordl, obfWord - for i in range(len(word)): - if word[i] == data: - obfWord[i] = word[i] - wordl -= 1 - -def randWord(): - return words[randint(0, len(words))] - -def initGame(): - global word, wordl, obfWord, playedLetters - word = list(randWord()) - wordl = len(word) - obfWord = ["_"]*wordl - showLetter(word[0]) - showLetter(word[-1]) - playedLetters.append(word[0]) - playedLetters.append(word[-1]) - -def check(data): - global word, wordl, obfWord, playedLetters, guessesRemaining - if re.search("^.{1}$", data): - if data in playedLetters: - print(clr("\n " + db["played"], "red")) - else: - playedLetters.append(data) - if data in word: - showLetter(data) - if wordl < 1: - print(clr("\n " + " ".join(obfWord), "cian")) - print(clr("\n --------------------------------------------", "blue")) - print(clr("\n " + db["you_won"] + "\n", "green")) - sys.exit() - else: - guessesRemaining -= 1 - if guessesRemaining < 1: - print(clr("\n " + " ".join(obfWord) + "\n", "cian")) - print(clr("\n --------------------------------------------", "blue")) - print(clr("\n " + "".join(word), "cian")) - print(clr("\n " + db["you_lose"] + "\n", "red")) - sys.exit() - else: - print(clr("\n " + db["one_char"], "red")) - print(clr("\n " + (" ").join(obfWord) + "\n", "cian")) - print(clr(" " + str(guessesRemaining) + " " + db["remaining"], "green")) - print(clr(" " + db["letters"] + " " + (", ").join(playedLetters), "green")) - print(clr("\n --------------------------------------------\n", "blue")) - print(clr(" " + db["guess"] + " ", "yellow"), end='') - data = input() - check(data) +def choose_language(): + available_langs = [d for d in os.listdir("locales") if os.path.isdir(os.path.join("locales", d))] + print("Available languages:") + for i, lang in enumerate(available_langs): + print(f"{i+1}. {lang}") + while True: + choice = input("Choose your language (number): ").strip() + if choice.isdigit(): + idx = int(choice) - 1 + if 0 <= idx < len(available_langs): + return available_langs[idx] + print("Invalid choice. Please enter a number from the list.") def clr(text, color): - if color == "red": - return "\x1b[91m" + text + "\x1b[0m" - elif color == "green": - return "\x1b[92m" + text + "\x1b[0m" - elif color == "blue": - return "\x1b[34m" + text + "\x1b[0m" - elif color == "cian": - return "\x1b[96m" + text + "\x1b[0m" - elif color == "yellow": - return "\x1b[93m" + text + "\x1b[0m" + if color == "red": + return "\x1b[91m" + text + "\x1b[0m" + elif color == "green": + return "\x1b[92m" + text + "\x1b[0m" + elif color == "blue": + return "\x1b[34m" + text + "\x1b[0m" + elif color == "cian": + return "\x1b[96m" + text + "\x1b[0m" + elif color == "yellow": + return "\x1b[93m" + text + "\x1b[0m" + return text + +def showLetter(data, word, obfWord, wordl): + for i in range(len(word)): + if word[i] == data: + obfWord[i] = word[i] + wordl[0] -= 1 + +def randWord(words): + return words[randint(0, len(words) - 1)] + +def initGame(words): + word = list(randWord(words)) + wordl = [len(word)] + obfWord = ["_"] * wordl[0] + playedLetters = [] + guessesRemaining = [8] + + showLetter(word[0], word, obfWord, wordl) + showLetter(word[-1], word, obfWord, wordl) + playedLetters.append(word[0]) + playedLetters.append(word[-1]) + + return word, wordl, obfWord, playedLetters, guessesRemaining + +def check(data, word, wordl, obfWord, playedLetters, guessesRemaining, db): + if re.search("^.{1}$", data): + if data in playedLetters: + print(clr("\n " + db["played"], "red")) + else: + playedLetters.append(data) + if data in word: + showLetter(data, word, obfWord, wordl) + if wordl[0] < 1: + return "won" + else: + guessesRemaining[0] -= 1 + if guessesRemaining[0] < 1: + return "lost" + else: + print(clr("\n " + db["one_char"], "red")) + + print(clr("\n " + (" ").join(obfWord) + "\n", "cian")) + print(clr(" " + str(guessesRemaining[0]) + " " + db["remaining"], "green")) + print(clr(" " + db["letters"] + " " + (", ").join(playedLetters), "green")) + print(clr("\n --------------------------------------------\n", "blue")) + return "continue" + +def playGame(words, db): + word, wordl, obfWord, playedLetters, guessesRemaining = initGame(words) + print(clr(" " + " ".join(obfWord) + "\n", "cian")) + while True: + print(clr(" " + db["guess"] + " ", "yellow"), end='') + data = input().strip().lower() + result = check(data, word, wordl, obfWord, playedLetters, guessesRemaining, db) + if result == "won": + print(clr("\n " + " ".join(obfWord), "cian")) + print(clr("\n --------------------------------------------", "blue")) + print(clr("\n " + db["you_won"] + "\n", "green")) + break + elif result == "lost": + print(clr("\n " + " ".join(obfWord) + "\n", "cian")) + print(clr("\n --------------------------------------------", "blue")) + print(clr("\n " + "".join(word), "cian")) + print(clr("\n " + db["you_lose"] + "\n", "red")) + break def main(): - print(clr(" " + db["hangman"], "green")) - print(clr("\n --------------------------------------------\n", "blue")) - initGame() - print(clr(" " + " ".join(obfWord) + "\n", "cian")) - print(clr(" " + db["guess"] + " ", "yellow"), end='') - data = input() - check(data.strip().lower()) - -main() + language = choose_language() + print(pyfiglet.figlet_format("Hello!")) + + with open(f"locales/{language}/locale.json", encoding="utf-8") as json_file: + db = json.load(json_file) + + with open(f"locales/{language}/words/all.json", encoding="utf-8") as json_file: + db_words = json.load(json_file) + + print(clr(db["rules"], "yellow")) + + while True: + playGame(db_words["words"], db) + print(clr(f"{db['play_again']} (R) / {db['quit']} (Q): ", "yellow"), end='') + choice = input().strip().lower() + if choice == 'r': + continue + elif choice == 'q': + print(clr(db["goodbye"], "green")) + break + else: + print(clr(db["invalid_choice"], "red")) + +if __name__ == "__main__": + main() diff --git a/Hangman/index.js b/Hangman/index.js index a8e0ebc..f2a89cf 100755 --- a/Hangman/index.js +++ b/Hangman/index.js @@ -1,25 +1,41 @@ #!/usr/bin/env node -const {Hangman, Colors} = require("./Hangman") - -let language = "en" -let words = "all" -const argLanguage = process.argv[2] -if (argLanguage != undefined && /^[A-Za-z\-\_]{1,}$/.test(argLanguage)) { - language = argLanguage - argWords = process.argv[3] - if (argWords != undefined) { - words = argWords - } +const readline = require("readline/promises"); +const { Hangman, Colors } = require("./Hangman"); + +let language = "en"; +let words = "all"; + +const argLanguage = process.argv[2]; +if (argLanguage !== undefined && /^[A-Za-z\-\_]+$/.test(argLanguage)) { + language = argLanguage; +} + +const argWords = process.argv[3]; +if (argWords !== undefined) { + words = argWords; } -process.stdin.setEncoding('utf-8') +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); -new Hangman({ +async function main() { + const hangman = new Hangman({ locale: require(`./locales/${language}/locale.json`), words: require(`./locales/${language}/words/${words}.json`), - pics: require('./hangarts.json'), + pics: require("./hangarts.json"), colors: new Colors(), - input: process.stdin, - output: process.stdout -}).play() + rl: rl, + }); + + await hangman.play(); + rl.close(); +} + +main().catch((err) => { + console.error(err); + rl.close(); + process.exit(1); +}); diff --git a/Hangman/locales/en/locale.json b/Hangman/locales/en/locale.json index 7738335..9b43a1e 100644 --- a/Hangman/locales/en/locale.json +++ b/Hangman/locales/en/locale.json @@ -1,11 +1,15 @@ { - "language": "English", - "played": "The letter you wrote was already played!", - "you_won": "You won!", - "you_lose": "You lose!", - "one_char": "Write just one character!", + "hangman": "Hangman", + "letters": "Used letters:", + "guess": "Guess a letter:", + "you_won": "You won!", + "you_lose": "You lost.", + "played": "Letter already played.", + "one_char": "Please enter a single letter.", "remaining": "guesses remaining", - "letters": "Letters already played:", - "guess": "Guess letter:", - "hangman": "Hangman" + "play_again": "Restart", + "quit": "Quit", + "goodbye": "Thanks for playing!", + "invalid_choice": "Invalid choice. Press R to Restart or Q to Quit.", + "rules": "Welcome to Hangman!\n\nRules:\n- Guess the word by suggesting letters one at a time.\n- You start with 8 incorrect guesses allowed.\n- The first and last letters are already revealed.\n- If you guess all letters before running out of guesses, you win!\n- If you run out of guesses, you lose.\n\nGood luck!" } \ No newline at end of file diff --git a/Hangman/locales/fr/locale.json b/Hangman/locales/fr/locale.json index 1aa7a51..0f8d05a 100644 --- a/Hangman/locales/fr/locale.json +++ b/Hangman/locales/fr/locale.json @@ -1,11 +1,15 @@ { - "language": "fr", - "played": "La lettre que vous avez écrite a déjà été jouée!", - "you_won": "Vous avez gagné!", - "you_lose": "Vous avez perdu!", - "one_char": "Ecrivez un seul caractère!", - "remaining": "Essais restants:", - "letters": "Lettres déjà jouées:", - "guess": "Devinez une lettre:", - "hangman": "Pendu" -} \ No newline at end of file + "hangman": "Le Pendu", + "letters": "Lettres utilisées :", + "guess": "Devinez une lettre :", + "you_won": "Vous avez gagné !", + "you_lose": "Vous avez perdu.", + "played": "Lettre déjà jouée.", + "one_char": "Veuillez entrer une seule lettre.", + "remaining": "tentatives restantes", + "play_again": "Recommencer", + "quit": "Quitter", + "goodbye": "Merci d'avoir joué !", + "invalid_choice": "Choix invalide. Appuyez sur R pour recommencer ou Q pour quitter.", + "rules": "Bienvenue au Pendu !\n\nRègles :\n- Devinez le mot en proposant des lettres une par une.\n- Vous commencez avec 8 tentatives incorrectes autorisées.\n- La première et la dernière lettre sont déjà dévoilées.\n- Si vous trouvez toutes les lettres avant d'épuiser vos tentatives, vous gagnez !\n- Si vous n'avez plus de tentatives, vous perdez.\n\nBonne chance !" +} diff --git a/Tetris/tetris.js b/Tetris/tetris.js index 322fa77..bb038dc 100644 --- a/Tetris/tetris.js +++ b/Tetris/tetris.js @@ -114,7 +114,7 @@ function clearLines() { if (fullRows.length === 0) return; for (const i of fullRows) { - board[i] = Array(10).fill(2); // ligne à clignoter + board[i] = Array(10).fill(2); } draw(); @@ -278,4 +278,4 @@ screen.key(['r'], () => { } }); -initGame(); +initGame(); \ No newline at end of file diff --git a/gameswindows.py b/gameswindows.py new file mode 100644 index 0000000..97de7a6 --- /dev/null +++ b/gameswindows.py @@ -0,0 +1,90 @@ +import os +import subprocess +import sys +import shutil + +def is_installed(command): + return shutil.which(command) is not None + +def check_dependencies(): + dependencies = { + "python": "Python", + "node": "Node.js", + "npm": "npm" + } + + missing = [] + for cmd, name in dependencies.items(): + if not is_installed(cmd): + missing.append(name) + + if missing: + print("⚠️ Les dépendances suivantes sont manquantes :") + for m in missing: + print(f"- {m}") + print("Merci de les installer avant de continuer.") + sys.exit(1) + +def run_game(path, command): + os.chdir(path) + subprocess.call(command, shell=True) + +def main(): + check_dependencies() + + games = [ + "[1] Hangman", + "[2] MazeEscape", + "[3] RockPaperScissors", + "[4] Snake", + "[5] TextAdventure", + "[6] TicTacToe", + "[7] Tetris", + "[e] Exit" + ] + + for game in games: + print(game) + + option = input("Enter a Choice: ").strip() + current_dir = os.path.dirname(os.path.abspath(__file__)) + + if option == "1": + game = input("Python or Javascript/JS version: ").lower() + if "js" in game: + run_game(os.path.join(current_dir, "Hangman"), "node index.js") + elif "py" in game: + run_game(os.path.join(current_dir, "Hangman"), "python hangman.py") + else: + print("Not valid option") + + elif option == "2": + run_game(os.path.join(current_dir, "MazeEscape"), "npm run play") + + elif option == "3": + run_game(os.path.join(current_dir, "RockPaperScissors"), "python rockpaperscissors.py") + + elif option == "4": + run_game(os.path.join(current_dir, "Snake"), "npm run play") + + elif option == "5": + run_game(os.path.join(current_dir, "TextAdventures"), "npm run play") + + elif option == "6": + game = input("Python or Javascript/JS version: ").lower() + if "js" in game: + run_game(os.path.join(current_dir, "TicTacToe"), "node index.js") + elif "py" in game: + run_game(os.path.join(current_dir, "TicTacToe"), "python tictactoe.py") + else: + print("Not valid option") + elif option == "7": + run_game(os.path.join(current_dir, "Tetris"), "node tetris.js") + + elif option == "e": + print("Goodbye!") + else: + print("Invalid argument, just select the game by the number") + +if __name__ == "__main__": + main()