Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Python Basics (2015) Letter Game App Letter Game Introduction

marios armakolas
marios armakolas
2,147 Points

letter_game.py - good_guesses [] and bad_guesses []

Hi,

I have a stupid question but i'll do it :)

I can't understant the logic of the programm (letter_game.py) to choose and put the letters that i guess, in the bad_guesses list or the good_guesses list.

For example, if the random secret_word is "lemon" and i guess the letter a which is wrong letter. Why the programm put this letter in bad_guesses list and not in good_guesses list.

That i want to say, is how the programm understand that good_guesses list is indeed the good mine choices. From the name of the lists? (good and bad).

Thanks in advance

2 Answers

Jakob Hansen
Jakob Hansen
13,746 Points

I actually described the entire program in another topic, I will paste it here. Warning, it's a long read, but it explains every bit of the code :)

Pro tip: To scroll left / right, click inside the code window and press shift and use the mouse wheel :)

Preferably you may just copy the entire code (Click inside the window and press CTRL + a (if on windows) or CMD + A on mac and then paste it into your IDE or workspaces for better readability.

import random
import os
import sys

words = [
    'lemon',
    'apple',
    'citrus',
    'cucumber',
    'melon',
    'orange',
    'carrot',
    'squash'
]
#Create a function that once called, it will clear the console window, to make the game look better
def clear():
    #Inside the "os" module there's a variable called "os" which has an attribute called name in it, you acces
    #attribute with the dot notation syntax; os.name
    #We are just using this code to check if the user is on a windows machine, or mac / linux
    #In case of windows, the value of os.name will 'nt' so we return os.system('cls')
    #We need to check for the OS on the users PC because the commands we need to execute are different.
    #On Windows, you have the command line (cmd.exe) which if you enter "cls" will clear the screen
    #On Mac fx. we have the terminal, which if you enter "clear", it will clear the screen.
    #That's the job of this function
    if os.name == 'nt':
        os.system('cls')
    else:
        os.system('clear')

# This is the "UI" of the game ( Very primitive yes :) )
#We declare a function, which has 3 parameters (badGuesses, goodGuesses, secretWord)
def draw(badGuesses, goodGuesses, secretWord):
    # We call the function clear() we just created
    clear()
    # print some UI stuff, I'm confident you understand this :)
    print('Strikes: {}/7'.format(len(badGuesses)))
    print()

    #We iterate over each letter in badGuesses (Which is a list of letters the users have guessed wrong)
    for letter in badGuesses:
        #We print each of the letters, one at a time, on each iteration of the for loop,
        #The end=" " is also some UI stuff, if we didn't include it, the print() functions default
        #value is "\n" which means "print something and jump to the next line", but we don't want this
        #new line that python gives us by default, so we need to change the default value, in this case
        #we give it a value of a space character " "
        print(letter, end=" ")
        #Now you know that "\n" is a "New line character" :) so I'm sure you can guess what the next line
        #will print, if you said 2 new lines, you would be correct! :)
    print("\n\n")

    #We iterate over each letter in the secretWord list, which is the full word that the computer
    #pulled from our words list
    for letter in secretWord:
        #We check to see if the letter of each iteration, is inside the goodGuesses list, if it is,
        #jump inside the if condition, and print this letter and the end='' here just means, don't
        # jump to a new line after you have printed this
        if letter in goodGuesses:
            print(letter, end='')
        else:
            #This is also purely UI stuff, if   the letter was NOT inside goodGuesses list, this code will run
            #and it will print a _ , which will just make it more visually appealing I guess, the _ will
            # be replaced by a letter essentially, once the user has guessed a correct letter, and the if condition
            # above will run instead of the else condition :)
            print('_', end='')
    #Just prints a new line, UI Stuff
    print("")

# We need to get a guess from the user, and that is this functions job.

def getGuess(badGuesses, goodGuesses):

    #We use a while loop here, just to create an infinite loop
    #We do that becuase if the user enters some invalid input, they will keep being reprompted for a new input
    while True:
        #Stores the users input and the .lower() method, just changes the value of the input to lower capitalization
        #to make it easier to compare against. So we don't need to say
        """"
            if guess == "Y":
                # some code
            elif guess == "y":

        """
        #It just makes it easier.

        guess = input("Guess a letter: ").lower()

        #Here's where we check if the user entered some invalid input
        #if the length of guess, is not equal to 1, (that is if it's more than one letter)
        #Then print "You can only guess a single letter!", and then we will jump back up to the beginning of the
        #while loop, and ask for a new input
        if len(guess) != 1:
            print("You can only guess a single letter!")

        # else, if the value of guess, is already inside of badGuesses or goodGuesses,
        #That must mean the user had already guessed that.
        elif guess in badGuesses or guess in goodGuesses:
            print("You've already guess taht letter!")

        #The .isalpha() method checks if the value of guess is an alpha numerical value
        # else if the value of guess is NOT an alpha numerical value, print " You can only guess letters!"
        elif not guess.isalpha():
            print("You can only guess letters!")
        #If nothing went wrong, just return guess
        else:
            return guess


#Define a function called play which takes a parameter called done
def play(done):
    clear()
    #creates a variable called secretWord, which stores a random word from the words list we created at the top
    #Kenneth explains how the random.choice works.
    secretWord = random.choice(words)
    #Create two empty list, we will append to these lists later.
    badGuesses = []
    goodGuesses = []

    #Inifinite loop again
    while True:
        #We call the function draw() with these 3 arguements, on the first iteration of this while loop
        #they will of course be empty, the first 2 lists, so our draw() function just prints "_____" x amount of
        #"_" underscores, to represent that there goes a letter, which you need to guess and the secretWord arguement
        # , just gives the draw() function the value of secretWord, so it can do the comparisions etc. inside our
        #draw() function.

        draw(badGuesses,goodGuesses,secretWord)

        #Here we call our function to request an input from the user, and we give the function 2 arguements (badGuesses,goodGuesses)
        #so that function can do the comparisions as well inside of it :)
        guess = getGuess(badGuesses,goodGuesses)

        #Here's where we actually check if the letter the user guessed, is inside the secretWord that the computer
        #picked from our words list.
        if guess in secretWord:
            #If the letter guessed by the user IS inside the secretWord, append it to the goodGuesses list.
            goodGuesses.append(guess)
            #create a boolean variable called found, this is just a tracking variable
            #It keeps track of "where" we are in the game basically
            #Set that to true, because we have found a letter inside the secretWord
            found = True
            #Iterate over the letters in the secretWord list
            for letter in secretWord:
                #if the letter of this iteration is NOT inside the goodGuesses list set the found variable to False
                #This checks if we have found all the letters inside the secretWord list (ask if you want me to break this down)
                if letter not in goodGuesses:
                    #Set the found variable to False, because we haven't found all the letters inside the secretWord list yet.
                    found = False
            #if found is True:
            #This will get run if we have found all the letters inside of secretWord
            #because of our tracking variable found, was not changed, as the if condition inside the for loop above, was never run on this iteration.
            #The found = true above is still True
            if found:
                print("You win!")
                print("The secret word was {}".format(secretWord))
                #done is another tracking variable
                done = True
        #If the guess is not inside the secretWord list, (the letter the user guessed wasn't in the secretWords lsit)
        #run this else clause
        else:
            #append the "bad" letter to our badGuesses list
            badGuesses.append(guess)
            #If the length of our badGuesses list is equal to 7 (there's a total of 7 letters inside our list)
            #then end the game, which our done tracking variable will do for us.
            if len(badGuesses) == 7:
                draw(badGuesses,goodGuesses,secretWord)
                print("You lost, the secret word was {}".format(secretWord))
                done = True
        #if done is True;
        #prompt the user for an input, asking if he wants to play again, again lower capitalizing the letter the user gives.
        #if the input is NOT 'n" (no) meaning yes ( in my opinion it would have been cleaner to just say if playAgain == 'y'
        #but whatever.
        #then go ahead and return play(done=False) which will call our play() function with the arguement of done, which has a value of False
        #The reason it's set to False is so that we can "reset" the game, we will be given a fresh pair or lists (badGuesses and goodGuesses)
        if done:
            playAgain = input("Play again? Y/N").lower()
            if playAgain != 'n':
                return play(done=False)
            #if the user however said 'n' (no) then just call sys.exit()  which just tells Python just exit. essentially killing the game:)
            else:
                sys.exit()

#Our welcome message to the game
#prompt the user, asking if he wants to exit the game early
You should know by now what the rest means :)

def welcome():
    start = input("Press enter / return to start or Q to quit").lower()
    if start == 'q':
        print("Bye!")
        sys.exit()
    else:
        return True



print("Welcome to letter guess!")

#This sets the starting value of done to False
done = False

#Here we just call all the functions we need, to begin the game.
while True:

    clear()
    welcome()
    play(done)