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

Nicolas Seglenieks
Nicolas Seglenieks
1,048 Points

Please explain what you're actually doing Kennith.

Title.

Steven Parker
Steven Parker
172,267 Points

We will miss Kenneth, he was a fun teacher. But perhaps if you elaborate a bit more about what is confusing you, someone else may be able to help.

3 Answers

Jakob Hansen
Jakob Hansen
13,746 Points

Alright, this is a lengthy explanation, I've commented all the lines of code, I hope you or someone will find it useful :) It might be useful for you to have you own code next to this, to follow along.

Another tip: By shift clicking and using your mouse scroll wheel, you can slide left / right in this text window, as it doesn't expand apparently. Maybe a thing Treehouse could implement :)

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)
Angad Chadha
Angad Chadha
1,467 Points

Thank you very much it helped me a lot. Is it fine for now if I am not able to understand some parts of this code?

Robert Špan
Robert Špan
2,058 Points

Please explain this part in play function:

        for letter in secretWord:
            if letter not in goodGuesses:
                found = False

Let's say the secret word is lemon. The player guesses "n". The loop goes through every letter in secretWord from l to n. When it is at n, shouldn't the statement "letter not in goodGuesses:" be found as false (because letter n was indeed appended to goodGuesses a few lines above), and therefore, the "found" variable would remain True?

Steven Parker
Steven Parker
172,267 Points

You're mostly right. But at the very end, when you say 'the "found" variable would remain True', it would be more correct to say the "found" variable would remain unchanged. It may have already been set to "False" when the loop was examining one of the other letters.

When this loop finishes, "found" will be "True" only if every letter was found in "goodGuesses".

For future questions, your chances of getting more responses will be improved if you start a new question. Anything added to an old one might be seen only by people who posted to it before.

Thanks a lot for the explanation!

Robert Špan
Robert Špan
2,058 Points

Thanx Steven, I see what I missed now, the if statement only applies if the condition is True :)

Youssef Moustahib
Youssef Moustahib
7,775 Points

Hi Jacob,

Quick question, why does Kenneth "return guess"? How does this work?

Thanks