diff --git a/src/gamesbyexample/alphabet_quiz_highscore.txt b/src/gamesbyexample/alphabet_quiz_highscore.txt new file mode 100644 index 0000000..4cf34e6 --- /dev/null +++ b/src/gamesbyexample/alphabet_quiz_highscore.txt @@ -0,0 +1,3 @@ +letters:3 +I have enhanced this code making it more interactive +"Implement Immediate Time-Out Response in Alphabetize Quiz Game" \ No newline at end of file diff --git a/src/gamesbyexample/alphabetizequiz.py b/src/gamesbyexample/alphabetizequiz.py index e8344f2..cbc2bce 100644 --- a/src/gamesbyexample/alphabetizequiz.py +++ b/src/gamesbyexample/alphabetizequiz.py @@ -1,74 +1,154 @@ -"""Alphabetize Quiz, by Al Sweigart al@inventwithpython.com -A time-based quiz game to see how fast you can alphabetize letters. -This and other games are available at https://nostarch.com/XX -Tags: short, game, word""" -__version__ = 0 +"""Alphabetize Quiz - Advanced Version +By Al Sweigart (improved by ChatGPT) + +A time-based quiz game to see how fast you can alphabetize letters, words, or numbers. +Now with multiple difficulty levels, countdown timer, and high-score saving! +""" + import random import time +import os +from colorama import Fore, Style, init -# Set up the constants: -# (!) Try changing these constants: -QUESTION_SIZE = 5 # Each question shows 5 letters to alphabetize. -QUIZ_DURATION = 30 # The quiz lasts 30 seconds. +init(autoreset=True) # For colored output +# Constants (you can tweak these) +QUESTION_SIZE = 5 +QUIZ_DURATION = 30 ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' -REVERSE_ALPHABET = 'ZYXWVUTSRQPONMLKJIHGFEDCBA' +NUMBERS = [str(i) for i in range(10)] +HIGHSCORE_FILE = "alphabet_quiz_highscore.txt" def main(): - # Fancy animation for the title: - slowPrint(ALPHABET, 0.02) # (!) Try changing 0.02 to 0.0 or 1.0. - slowPrint(' Alphabetize Quiz', 0.02) - slowPrint(REVERSE_ALPHABET, 0.02) - time.sleep(0.5) - - print('''By Al Sweigart al@inventwithpython.com - -Enter the alphabetical order of the letters shown as fast -as possible. Try to alphabetize as many as possible in {} seconds! - -Example: - P M O T Q <-- The letters. - > mopqt <-- Enter the correct alphabetical order. - '''.format(QUIZ_DURATION)) - input('Press Enter to begin...') - - startTime = time.time() # Get the current time for the start time. - numCorrect = 0 # Number of questions answered correctly. - while True: # Main game loop. - # Come up with letters for the question: - quizLetters = random.sample(ALPHABET, QUESTION_SIZE) - print(' '.join(quizLetters)) - response = input('> ').upper() - response = response.replace(' ', '') # Remove spaces. - - # Check if the quiz's time is up: - if time.time() - 30 > startTime: - print("TIME'S UP!") + showIntro() + + # Difficulty selection + difficulty = chooseDifficulty() + + # Highscore loading + highscore = loadHighScore(difficulty) + + input(Fore.CYAN + "\nPress Enter to begin the quiz...") + + startTime = time.time() + numCorrect = 0 + numAttempted = 0 + + while True: + # Check if time is up + elapsed = time.time() - startTime + if elapsed >= QUIZ_DURATION: + print(Fore.RED + "\nTIME'S UP!") break - # Check if the response is correct: + # Generate question + quizLetters = generateQuestion(difficulty) + print(Fore.YELLOW + " ".join(quizLetters)) + + # Countdown display + remaining = int(QUIZ_DURATION - elapsed) + print(Fore.MAGENTA + f"[{remaining}s left]") + + response = input("> ").upper().replace(" ", "") + numAttempted += 1 + if list(response) == sorted(quizLetters): - print(' Correct!\n') - numCorrect += 1 # Increase the score by 1. + print(Fore.GREEN + " ✅ Correct!\n") + numCorrect += 1 else: - print(' Sorry, wrong. :(\n') + print(Fore.RED + " ❌ Wrong. Answer was:", "".join(sorted(quizLetters)), "\n") + + # Final score + accuracy = (numCorrect / numAttempted * 100) if numAttempted else 0 + print(Style.BRIGHT + f"\n⏱ In {QUIZ_DURATION} seconds you attempted {numAttempted} questions.") + print(Fore.CYAN + f"✔ Correct: {numCorrect}") + print(Fore.RED + f"✘ Wrong: {numAttempted - numCorrect}") + print(Fore.YELLOW + f"🎯 Accuracy: {accuracy:.2f}%") + + # Save high score if beaten + if numCorrect > highscore: + print(Fore.GREEN + f"🏆 NEW HIGHSCORE! You beat the previous best of {highscore}.") + saveHighScore(difficulty, numCorrect) + else: + print(Fore.CYAN + f"Your highscore for {difficulty} is still {highscore}.") + + print(Fore.BLUE + "\nThanks for playing!") - # After the loop exits, the quiz is over. Show the final score: - print('In {} seconds you'.format(QUIZ_DURATION)) - print('got {} correct!'.format(numCorrect)) - print('Thanks for playing!') + +def showIntro(): + """Prints the intro animation and instructions.""" + slowPrint(ALPHABET, 0.01) + slowPrint(" Alphabetize Quiz - Advanced", 0.02) + slowPrint(ALPHABET[::-1], 0.01) + time.sleep(0.3) + + print('''\nWelcome to the Alphabetize Quiz! +Enter the correct alphabetical (or numerical) order of the shown characters. +Try to get as many correct as possible in the given time!\n''') + + +def chooseDifficulty(): + """Let the user select difficulty type.""" + print("\nChoose Difficulty:") + print("1. Letters (easy)") + print("2. Numbers (medium)") + print("3. Words (hard)") + + while True: + choice = input("> ").strip() + if choice == "1": + return "letters" + elif choice == "2": + return "numbers" + elif choice == "3": + return "words" + else: + print("Invalid choice. Enter 1, 2, or 3.") + + +def generateQuestion(difficulty): + """Generate a question based on difficulty.""" + if difficulty == "letters": + return random.sample(ALPHABET, QUESTION_SIZE) + elif difficulty == "numbers": + return random.sample(NUMBERS, QUESTION_SIZE) + elif difficulty == "words": + return random.sample( + ["CAT", "DOG", "MOON", "TREE", "PYTHON", "ZEBRA", "APPLE", "MANGO", "QUIZ", "CODE"], + QUESTION_SIZE + ) def slowPrint(text, pauseAmount=0.1): - """Slowly print out the characters in text one at a time.""" + """Slowly print out characters.""" for character in text: - # Set flush=True here so the text is immediately printed: - print(character, flush=True, end='') # end='' means no newline. - time.sleep(pauseAmount) # Pause in between each character. - print() # Print a newline. + print(character, flush=True, end="") + time.sleep(pauseAmount) + print() + + +def loadHighScore(difficulty): + """Load highscore for selected difficulty.""" + if not os.path.exists(HIGHSCORE_FILE): + return 0 + with open(HIGHSCORE_FILE, "r") as f: + scores = dict(line.strip().split(":") for line in f if ":" in line) + return int(scores.get(difficulty, 0)) + + +def saveHighScore(difficulty, score): + """Save highscore for selected difficulty.""" + scores = {} + if os.path.exists(HIGHSCORE_FILE): + with open(HIGHSCORE_FILE, "r") as f: + scores = dict(line.strip().split(":") for line in f if ":" in line) + scores[difficulty] = str(score) + with open(HIGHSCORE_FILE, "w") as f: + for k, v in scores.items(): + f.write(f"{k}:{v}\n") -# If this program was run (instead of imported), run the game: -if __name__ == '__main__': +# Run game +if __name__ == "__main__": main() diff --git a/src/gamesbyexample/clickbait.py b/src/gamesbyexample/clickbait.py index 5075628..fe9bc56 100644 --- a/src/gamesbyexample/clickbait.py +++ b/src/gamesbyexample/clickbait.py @@ -1,11 +1,8 @@ -"""Clickbait Headline Generator, by Al Sweigart al@inventwithpython.com -A clickbait headline generator for your soulless content farm website. -This code is available at https://nostarch.com/big-book-small-python-programming -Tags: large, beginner, humor, word""" -__version__ = 0 import random +import tkinter as tk +from tkinter import messagebox, scrolledtext, filedialog -# Set up the constants: +# Constants OBJECT_PRONOUNS = ['Her', 'Him', 'Them'] POSSESIVE_PRONOUNS = ['Her', 'His', 'Their'] PERSONAL_PRONOUNS = ['She', 'He', 'They'] @@ -13,119 +10,185 @@ 'Illinois', 'Ohio', 'Georgia', 'North Carolina', 'Michigan'] NOUNS = ['Athlete', 'Clown', 'Shovel', 'Paleo Diet', 'Doctor', 'Parent', 'Cat', 'Dog', 'Chicken', 'Robot', 'Video Game', 'Avocado', - 'Plastic Straw','Serial Killer', 'Telephone Psychic'] + 'Plastic Straw', 'Serial Killer', 'Telephone Psychic'] PLACES = ['House', 'Attic', 'Bank Deposit Box', 'School', 'Basement', 'Workplace', 'Donut Shop', 'Apocalypse Bunker'] WHEN = ['Soon', 'This Year', 'Later Today', 'RIGHT NOW', 'Next Week'] - - -def main(): - print('Clickbait Headline Generator') - print('By Al Sweigart al@inventwithpython.com') - print() - - print('Our website needs to trick people into looking at ads!') - while True: - print('Enter the number of clickbait headlines to generate:') - response = input('> ') - if not response.isdecimal(): - print('Please enter a number.') - else: - numberOfHeadlines = int(response) - break # Exit the loop once a valid number is entered. - - for i in range(numberOfHeadlines): - clickbaitType = random.randint(1, 8) - - if clickbaitType == 1: - headline = generateAreMillenialsKillingHeadline() - elif clickbaitType == 2: - headline = generateWhatYouDontKnowHeadline() - elif clickbaitType == 3: - headline = generateBigCompaniesHateHerHeadline() - elif clickbaitType == 4: - headline = generateYouWontBelieveHeadline() - elif clickbaitType == 5: - headline = generateDontWantYouToKnowHeadline() - elif clickbaitType == 6: - headline = generateGiftIdeaHeadline() - elif clickbaitType == 7: - headline = generateReasonsWhyHeadline() - elif clickbaitType == 8: - headline = generateJobAutomatedHeadline() - - print(headline) - print() - - website = random.choice(['wobsite', 'blag', 'Facebuuk', 'Googles', - 'Facesbook', 'Tweedie', 'Pastagram']) - when = random.choice(WHEN).lower() - print('Post these to our', website, when, 'or you\'re fired!') - - -# Each of these functions returns a different type of headline: -def generateAreMillenialsKillingHeadline(): +WEBSITES = ['wobsite', 'blag', 'Facebuuk', 'Googles', 'Facesbook', 'Tweedie', 'Pastagram'] + + +def generate_random_headline(): + clickbait_type = random.randint(1, 10) + + if clickbait_type == 1: + return generate_are_millenials_killing_headline() + elif clickbait_type == 2: + return generate_what_you_dont_know_headline() + elif clickbait_type == 3: + return generate_big_companies_hate_her_headline() + elif clickbait_type == 4: + return generate_you_wont_believe_headline() + elif clickbait_type == 5: + return generate_dont_want_you_to_know_headline() + elif clickbait_type == 6: + return generate_gift_idea_headline() + elif clickbait_type == 7: + return generate_reasons_why_headline() + elif clickbait_type == 8: + return generate_job_automated_headline() + elif clickbait_type == 9: + return generate_shocking_truth_headline() + elif clickbait_type == 10: + return generate_secret_revealed_headline() + + +# Headline generators +def generate_are_millenials_killing_headline(): noun = random.choice(NOUNS) - return 'Are Millenials Killing the {} Industry?'.format(noun) + return f"Are Millennials Killing the {noun} Industry?" -def generateWhatYouDontKnowHeadline(): +def generate_what_you_dont_know_headline(): noun = random.choice(NOUNS) - pluralNoun = random.choice(NOUNS) + 's' + plural_noun = random.choice(NOUNS) + 's' when = random.choice(WHEN) - return 'Without This {}, {} Could Kill You {}'.format(noun, pluralNoun, when) + return f"Without This {noun}, {plural_noun} Could Kill You {when}" -def generateBigCompaniesHateHerHeadline(): +def generate_big_companies_hate_her_headline(): pronoun = random.choice(OBJECT_PRONOUNS) state = random.choice(STATES) noun1 = random.choice(NOUNS) noun2 = random.choice(NOUNS) - return 'Big Companies Hate {}! See How This {} {} Invented a Cheaper {}'.format(pronoun, state, noun1, noun2) + return f"Big Companies Hate {pronoun}! See How This {state} {noun1} Invented a Cheaper {noun2}" -def generateYouWontBelieveHeadline(): +def generate_you_wont_believe_headline(): state = random.choice(STATES) noun = random.choice(NOUNS) pronoun = random.choice(POSSESIVE_PRONOUNS) place = random.choice(PLACES) - return 'You Won\'t Believe What This {} {} Found in {} {}'.format(state, noun, pronoun, place) + return f"You Won't Believe What This {state} {noun} Found in {pronoun} {place}" -def generateDontWantYouToKnowHeadline(): - pluralNoun1 = random.choice(NOUNS) + 's' - pluralNoun2 = random.choice(NOUNS) + 's' - return 'What {} Don\'t Want You To Know About {}'.format(pluralNoun1, pluralNoun2) +def generate_dont_want_you_to_know_headline(): + plural_noun1 = random.choice(NOUNS) + 's' + plural_noun2 = random.choice(NOUNS) + 's' + return f"What {plural_noun1} Don't Want You To Know About {plural_noun2}" -def generateGiftIdeaHeadline(): +def generate_gift_idea_headline(): number = random.randint(7, 15) noun = random.choice(NOUNS) state = random.choice(STATES) - return '{} Gift Ideas to Give Your {} From {}'.format(number, noun, state) + return f"{number} Gift Ideas to Give Your {noun} From {state}" -def generateReasonsWhyHeadline(): +def generate_reasons_why_headline(): number1 = random.randint(3, 19) - pluralNoun = random.choice(NOUNS) + 's' - # number2 should be no larger than number1: + plural_noun = random.choice(NOUNS) + 's' number2 = random.randint(1, number1) - return '{} Reasons Why {} Are More Interesting Than You Think (Number {} Will Surprise You!)'.format(number1, pluralNoun, number2) + return (f"{number1} Reasons Why {plural_noun} Are More Interesting Than You Think " + f"(Number {number2} Will Surprise You!)") -def generateJobAutomatedHeadline(): +def generate_job_automated_headline(): state = random.choice(STATES) noun = random.choice(NOUNS) - i = random.randint(0, 2) pronoun1 = POSSESIVE_PRONOUNS[i] pronoun2 = PERSONAL_PRONOUNS[i] + if pronoun1 == 'Their': - return 'This {} {} Didn\'t Think Robots Would Take {} Job. {} Were Wrong.'.format(state, noun, pronoun1, pronoun2) + return f"This {state} {noun} Didn't Think Robots Would Take {pronoun1} Job. {pronoun2} Were Wrong." else: - return 'This {} {} Didn\'t Think Robots Would Take {} Job. {} Was Wrong.'.format(state, noun, pronoun1, pronoun2) + return f"This {state} {noun} Didn't Think Robots Would Take {pronoun1} Job. {pronoun2} Was Wrong." + + +def generate_shocking_truth_headline(): + noun = random.choice(NOUNS) + place = random.choice(PLACES) + return f"The Shocking Truth About {noun}s Hidden in Your {place}" + + +def generate_secret_revealed_headline(): + state = random.choice(STATES) + plural_noun = random.choice(NOUNS) + 's' + return f"Secret Revealed: Why {state} {plural_noun} Are Taking Over the World" + + +class ClickbaitGUI: + def __init__(self, root): + self.root = root + self.root.title("Clickbait Headline Generator") + + # Title label + title = tk.Label(root, text="Clickbait Headline Generator", font=("Arial", 18, "bold")) + title.pack(pady=10) + + # Instruction label + instr = tk.Label(root, text="Enter the number of headlines to generate:") + instr.pack() + + # Input for number of headlines + self.num_input = tk.Entry(root, width=10, justify='center') + self.num_input.pack(pady=5) + self.num_input.insert(0, "5") # default value + + # Generate button + generate_btn = tk.Button(root, text="Generate Headlines", command=self.generate_headlines) + generate_btn.pack(pady=5) + + # ScrolledText widget for output + self.output_area = scrolledtext.ScrolledText(root, width=70, height=15, wrap=tk.WORD, font=("Helvetica", 12)) + self.output_area.pack(padx=10, pady=10) + + # Save button + save_btn = tk.Button(root, text="Save Headlines to File", command=self.save_headlines) + save_btn.pack(pady=5) + + # Quit button + quit_btn = tk.Button(root, text="Quit", command=root.quit) + quit_btn.pack(pady=5) + + def generate_headlines(self): + self.output_area.delete('1.0', tk.END) # clear previous output + num_str = self.num_input.get() + + if not num_str.isdecimal() or int(num_str) <= 0: + messagebox.showerror("Invalid Input", "Please enter a positive integer for number of headlines.") + return + + num = int(num_str) + headlines = [generate_random_headline() for _ in range(num)] + for i, hl in enumerate(headlines, start=1): + self.output_area.insert(tk.END, f"{i}. {hl}\n") + + website = random.choice(WEBSITES) + when = random.choice(WHEN).lower() + self.output_area.insert(tk.END, f"\nPost these to our {website} {when} or you’re fired!\n") + + def save_headlines(self): + content = self.output_area.get('1.0', tk.END).strip() + if not content: + messagebox.showinfo("Nothing to Save", "Please generate headlines first before saving.") + return + + file_path = filedialog.asksaveasfilename( + defaultextension=".txt", + filetypes=[("Text files", "*.txt"), ("All files", "*.*")], + title="Save Headlines As" + ) + if file_path: + try: + with open(file_path, 'w') as f: + f.write(content) + messagebox.showinfo("Saved", f"Headlines saved to:\n{file_path}") + except Exception as e: + messagebox.showerror("Error", f"Could not save file: {e}") -# If the program is run (instead of imported), run the game: if __name__ == '__main__': - main() + root = tk.Tk() + app = ClickbaitGUI(root) + root.mainloop() diff --git a/src/gamesbyexample/clickbait_headlines.txt b/src/gamesbyexample/clickbait_headlines.txt new file mode 100644 index 0000000..22ce852 --- /dev/null +++ b/src/gamesbyexample/clickbait_headlines.txt @@ -0,0 +1,4 @@ +1. Are Millennials Killing the Paleo Diet Industry? +2. What Shovels Don't Want You To Know About Clowns + +Post these to our Tweedie next week or you’re fired! \ No newline at end of file