Advertisement
Normantas

MIT 6.0001 pset2 Hangman solution

Aug 10th, 2020
1,021
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.82 KB | None | 0 0
  1. # Problem Set 2, hangman.py
  2. # Name: Normantas
  3. # Collaborators: python 3 documentation websites
  4. # Time spent: 7h~ including thinking and other things.
  5.  
  6. # Hangman Game
  7. # -----------------------------------
  8. # Helper code
  9. # You don't need to understand this helper code,
  10. # but you will have to know how to use the functions
  11. # (so be sure to read the docstrings!)
  12. import random
  13. import string
  14.  
  15. WORDLIST_FILENAME = "words.txt"
  16.  
  17.  
  18. def load_words():
  19.     """
  20.    Returns a list of valid words. Words are strings of lowercase letters.
  21.    
  22.    Depending on the size of the word list, this function may
  23.    take a while to finish.
  24.    """
  25.     print("Loading word list from file...")
  26.     # inFile: file
  27.     inFile = open(WORDLIST_FILENAME, 'r')
  28.     # line: string
  29.     line = inFile.readline()
  30.     # wordlist: list of strings
  31.     wordlist = line.split()
  32.     print("  ", len(wordlist), "words loaded.")
  33.     return wordlist
  34.  
  35.  
  36.  
  37. def choose_word(wordlist):
  38.     """
  39.    wordlist (list): list of words (strings)
  40.    
  41.    Returns a word from wordlist at random
  42.    """
  43.     return random.choice(wordlist)
  44.  
  45. # end of helper code
  46.  
  47. # -----------------------------------
  48.  
  49. # Load the list of words into the variable wordlist
  50. # so that it can be accessed from anywhere in the program
  51. wordlist = load_words()
  52.  
  53.  
  54. def is_word_guessed(secret_word, letters_guessed):
  55.     '''
  56.    secret_word: string, the word the user is guessing; assumes all letters are
  57.      lowercase
  58.    letters_guessed: list (of letters), which letters have been guessed so far;
  59.      assumes that all letters are lowercase
  60.    returns: boolean, True if all the letters of secret_word are in letters_guessed;
  61.      False otherwise
  62.    '''
  63.     for i in secret_word:
  64.         if i not in letters_guessed:
  65.             return False #letter doesn't exist in guessed words
  66.        
  67.     return True
  68.  
  69.  
  70.  
  71. def get_guessed_word(secret_word, letters_guessed):
  72.     '''
  73.    secret_word: string, the word the user is guessing
  74.    letters_guessed: list (of letters), which letters have been guessed so far
  75.    returns: string, comprised of letters, underscores (_), and spaces that represents
  76.      which letters in secret_word have been guessed so far.
  77.    '''
  78.     output = ""
  79.     for i in secret_word:
  80.         if i in letters_guessed:
  81.             output += i
  82.         else:
  83.             output += "_ "
  84.     return output
  85.  
  86.  
  87.  
  88. def get_available_letters(letters_guessed):
  89.     '''
  90.    letters_guessed: list (of letters), which letters have been guessed so far
  91.    returns: string (of letters), comprised of letters that represents which letters have not
  92.      yet been guessed.
  93.    '''
  94.     alphabet = list(string.ascii_lowercase) #gets a list of all english alphabet letters
  95.     output = sorted(list(set(alphabet) - set(letters_guessed)))
  96.     return "".join(output) #transforms list to a string
  97.    
  98. def print_dashes():
  99.     print("-------------")
  100.  
  101. def hangman(secret_word):
  102.     '''
  103.    secret_word: string, the secret word to guess.
  104.    
  105.    Starts up an interactive game of Hangman.
  106.    
  107.    * At the start of the game, let the user know how many
  108.      letters the secret_word contains and how many guesses s/he starts with.
  109.      
  110.    * The user should start with 6 guesses
  111.  
  112.    * Before each round, you should display to the user how many guesses
  113.      s/he has left and the letters that the user has not yet guessed.
  114.    
  115.    * Ask the user to supply one guess per round. Remember to make
  116.      sure that the user puts in a letter!
  117.    
  118.    * The user should receive feedback immediately after each guess
  119.      about whether their guess appears in the computer's word.
  120.  
  121.    * After each guess, you should display to the user the
  122.      partially guessed word so far.
  123.    
  124.    Follows the other limitations detailed in the problem write-up.
  125.    '''
  126.    
  127.     guesses_left, warnings_left, letters_guessed = initialize_hangman()
  128.     #For testing uncomment:
  129.     #print("!!!!FOR TESTING!!! SECRET WORD IS:",secret_word)
  130.     while(True):
  131.        
  132.         availabe_letters = print_and_get_information_at_start_of_round(guesses_left, letters_guessed)      
  133.        
  134.         #Asks for a letter till it gets a possible letter
  135.         guessed_letter = input("Please guess a letter: ").lower()
  136.        
  137.         if (guessed_letter not in availabe_letters):
  138.             guesses_left, warnings_left = give_out_warning_information(warnings_left, guesses_left, secret_word, letters_guessed, guessed_letter)
  139.             if (guesses_left <= 0):
  140.                 #The game has been lost due to warnings
  141.                 print_losing_message(secret_word)
  142.                 break
  143.             continue
  144.            
  145.         #Updates the guessed word and letters
  146.         letters_guessed.append(guessed_letter)
  147.         guessed_word = get_guessed_word(secret_word, letters_guessed)
  148.        
  149.         #Tells the user how well he did on current round, returns the amount of guesses left
  150.         guesses_left = checks_how_well_the_round_went(guesses_left, guessed_letter, secret_word, guessed_word)
  151.  
  152.         #Ends Game  
  153.         if (check_if_game_continues(guesses_left, guessed_word, secret_word)):
  154.             break
  155.            
  156.         print_dashes()
  157.        
  158.  
  159.  
  160.  
  161. # When you've completed your hangman function, scroll down to the bottom
  162. # of the file and uncomment the first two lines to test
  163. #(hint: you might want to pick your own
  164. # secret_word while you're doing your own testing)
  165.  
  166.  
  167. # -----------------------------------
  168. def initialize_hangman():
  169.     guesses_left = 6
  170.     warnings_left = 3
  171.     letters_guessed = []
  172.     print("Welcome to the game Hangman!")
  173.     print("I am thinking of a word that is {} letters long.".format(len(secret_word)))
  174.     print("You have {} warnings left".format(warnings_left))
  175.     print_dashes()
  176.     return (guesses_left, warnings_left, letters_guessed)
  177.  
  178. def print_losing_message(secret_word):
  179.     """Prints a message when the game is lost"""
  180.     print_dashes()
  181.     print("Sorry, you ran out of guesses. The word was {}.".format(secret_word))
  182.    
  183. def print_winner_message(guesses_left, secret_word):
  184.     """Prints a message when the user won the game"""
  185.     print_dashes()
  186.     print("Congratulations, you won!")
  187.     print("Your total score for this game is: {}".format(guesses_left * len(set(list(secret_word)))))
  188.    
  189. def give_out_warning_information(warnings_left, guesses_left, secret_word, letters_guessed, guessed_letter):
  190.     """Tells the reason why the guess was wrong
  191.    punishes the user"""
  192.     guessed_word = get_guessed_word(secret_word, letters_guessed)
  193.     reason = ""
  194.     if guessed_letter in letters_guessed:
  195.         reason = "You've already guessed that letter"
  196.     else:
  197.         reason = "That is not a valid letter"
  198.    
  199.     if warnings_left > 0:
  200.         warnings_left -= 1;
  201.         print("Oops! {}. You have {} warnings left: {}".format(reason, warnings_left, guessed_word))
  202.     else:
  203.         guesses_left -= 1
  204.         print(" Oops! {}. You have no warnings left so you lose one guess: {}".format(reason, guessed_word))
  205.     return (guesses_left, warnings_left)
  206.  
  207. def print_and_get_information_at_start_of_round(guesses_left, letters_guessed):
  208.     """Prints the information at the start of the round,
  209.    returns the avaialble letters"""
  210.     print("You have {} guesses left".format(guesses_left))
  211.     availabe_letters = get_available_letters(letters_guessed)
  212.     print("Available letters: {}".format(availabe_letters))
  213.     return availabe_letters
  214.        
  215. def checks_how_well_the_round_went(guesses_left, guessed_letter, secret_word, guessed_word):
  216.     """Tells the user how well he did on this round
  217.    returns the amount of guesses left"""
  218.     vowels = ['a','e','i','o','u']
  219.     if guessed_letter in list(secret_word):
  220.             print("Good Guess: {}".format(guessed_word))
  221.     else:
  222.         print("Oops! That letter is not in my word: {}".format(guessed_word))
  223.         if guessed_letter in vowels:
  224.             guesses_left -= 2
  225.         else:
  226.             guesses_left -= 1
  227.            
  228.     return guesses_left
  229.                
  230. def check_if_game_continues(guesses_left, guessed_word, secret_word):
  231.     """Checks if the guesses word is correct or there aren't
  232.    any more guesses left"""
  233.     if guesses_left <= 0:
  234.         print_losing_message(secret_word)
  235.         return True
  236.     if guessed_word == secret_word:
  237.         print_winner_message(guesses_left, secret_word)
  238.         return True
  239.     return False
  240.  
  241. def match_with_gaps(my_word, other_word):
  242.     '''
  243.    my_word: string with _ characters, current guess of secret word
  244.    other_word: string, regular English word
  245.    returns: boolean, True if all the actual letters of my_word match the
  246.        corresponding letters of other_word, or the letter is the special symbol
  247.        _ , and my_word and other_word are of the same length;
  248.        False otherwise:
  249.    '''
  250.     my_word = my_word.replace(" ", "")
  251.     if len(my_word) == len(other_word):
  252.         for i in range(len(my_word)):
  253.             letter = my_word[i]
  254.             if letter == "_":
  255.                 continue
  256.             elif letter != other_word[i]:
  257.                 return False      
  258.         #All checks were correct, plausible word
  259.         return True
  260.     else:
  261.         return False
  262.  
  263. def get_possible_matches_list(my_word):
  264.     """my word = currently possible guessable word
  265.    Get's every possible word from wordlist
  266.    implement TRIE for speed if needed"""
  267.     output = []
  268.     for word in wordlist:
  269.         if match_with_gaps(my_word, word):
  270.             output.append(word)
  271.            
  272.     return output
  273.    
  274. def print_possible_matches_from_list(possible_matches):
  275.     """Prints possible matches from the list for getting
  276.    all possible matches from a wordlist when playing
  277.    hangman with hints"""
  278.     if(any(possible_matches)):
  279.         print("Possible word matches are: ")
  280.         print(" ".join(possible_matches))
  281.     else:
  282.         print("No matches found")
  283.    
  284. def show_possible_matches(my_word):
  285.     '''
  286.    my_word: string with _ characters, current guess of secret word
  287.    returns: nothing, but should print out every word in wordlist that matches my_word
  288.             Keep in mind that in hangman when a letter is guessed, all the positions
  289.             at which that letter occurs in the secret word are revealed.
  290.             Therefore, the hidden letter(_ ) cannot be one of the letters in the word
  291.             that has already been revealed.
  292.  
  293.    '''
  294.     possible_matches_list = get_possible_matches_list(my_word)
  295.     print_possible_matches_from_list(possible_matches_list)
  296.     print_dashes()
  297.    
  298.  
  299. def hangman_with_hints(secret_word):
  300.     '''
  301.    secret_word: string, the secret word to guess.
  302.    
  303.    Starts up an interactive game of Hangman.
  304.    
  305.    * At the start of the game, let the user know how many
  306.      letters the secret_word contains and how many guesses s/he starts with.
  307.      
  308.    * The user should start with 6 guesses
  309.    
  310.    * Before each round, you should display to the user how many guesses
  311.      s/he has left and the letters that the user has not yet guessed.
  312.    
  313.    * Ask the user to supply one guess per round. Make sure to check that the user guesses a letter
  314.      
  315.    * The user should receive feedback immediately after each guess
  316.      about whether their guess appears in the computer's word.
  317.  
  318.    * After each guess, you should display to the user the
  319.      partially guessed word so far.
  320.      
  321.    * If the guess is the symbol *, print out all words in wordlist that
  322.      matches the current guessed word.
  323.    
  324.    Follows the other limitations detailed in the problem write-up.
  325.    '''
  326.     guesses_left, warnings_left, letters_guessed = initialize_hangman()
  327.     #For testing uncomment:
  328.     #print("!!!!FOR TESTING!!! SECRET WORD IS:",secret_word)
  329.     while(True):
  330.        
  331.         availabe_letters = print_and_get_information_at_start_of_round(guesses_left, letters_guessed)      
  332.        
  333.         #Asks for a letter till it gets a possible letter
  334.         guessed_letter = input("Please guess a letter: ").lower()
  335.         if guessed_letter == "*":
  336.             show_possible_matches(get_guessed_word(secret_word, letters_guessed))
  337.             continue
  338.         elif guessed_letter not in availabe_letters:
  339.             guesses_left, warnings_left = give_out_warning_information(warnings_left, guesses_left, secret_word, letters_guessed, guessed_letter)
  340.             if (guesses_left <= 0):
  341.                 #The game has been lost due to warnings
  342.                 print_losing_message(secret_word)
  343.                 break
  344.             continue
  345.            
  346.         #Updates the guessed word and letters
  347.         letters_guessed.append(guessed_letter)
  348.         guessed_word = get_guessed_word(secret_word, letters_guessed)
  349.        
  350.         #Tells the user how well he did on current round, returns the amount of guesses left
  351.         guesses_left = checks_how_well_the_round_went(guesses_left, guessed_letter, secret_word, guessed_word)
  352.  
  353.         #Ends Game  
  354.         if (check_if_game_continues(guesses_left, guessed_word, secret_word)):
  355.             break
  356.            
  357.         print_dashes()
  358.  
  359.  
  360.  
  361. # When you've completed your hangman_with_hint function, comment the two similar
  362. # lines above that were used to run the hangman function, and then uncomment
  363. # these two lines and run this file to test!
  364. # Hint: You might want to pick your own secret_word while you're testing.
  365.  
  366.  
  367. if __name__ == "__main__":
  368.     # pass
  369.  
  370.     # To test part 2, comment out the pass line above and
  371.     # uncomment the following two lines.
  372.    
  373.     secret_word = choose_word(wordlist)
  374.     #hangman(secret_word)
  375.  
  376. ###############
  377.    
  378.     # To test part 3 re-comment out the above lines and
  379.     # uncomment the following two lines.
  380.    
  381.     #secret_word = choose_word(wordlist)
  382.     hangman_with_hints(secret_word)
  383.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement