Movie Hangman

For this assignment, you will be implementing a text-based version of hangman. There are many variants of the program, so follow the specifications closely. Make sure that you read through this whole handout first before getting started. We've given an overview of how to proceed and then some hints near the end.

A stick figure on a gallows, observed by a U.S. Revolutionary War-era soldier

Movies Database

For this assignment, we will use a dataset stored as a list of tuples. Our collection will be a list of movies along with information about those movies. To obtain the list of films, download the assignment 5 starter file. It will contain two files, movies.txt and movies.py. The text file is a "delimiter-separated values" file which we'll write a little bit of Python code to read into our list of tuples. Make a assignment5 folder and place movies.txt and movies.py inside of it.

Open up movies.txt and take a look at the format. Note that each line has the same number of vertical bars, and try to get a feel for the format. Our first task is to implement the get_movies function in movies.py to read in this file and load our movie database.

You can take a look at get_practice_movies to get a sense of what the Python data structures we want should look like:

    >>> practice = get_practice_movies()
    >>> practice[0]
    ('jaws', 'A big shark eats stuff', 1975)
  

Each movie should be a tuple like the ones coming out of get_practice_movies: The lowercased title, a description, and an integer year. You can use the string split and lower methods to help you out here. You may also get some use out of rstrip.

Completing get_movies is worth 4 points.

Hangman Game

Once you're happy with get_movies, it's time to implement the game itself in a new file hangman.py. The program should randomly pick a film (using Python's random module) and give the user some information about the movie to help them guess:

*** Movie Hangman ***
Year: 1997
A deranged media mogul is staging international
incidents to pit the world's superpowers
against each other. Now 007 must take on
this evil mastermind in an adrenaline-charged
battle to end his reign of terror and prevent
global pandemonium.
  

After this has been displayed, the program should then display the general hangman output:

___________________
Guessed letters:
Movie: -------- ----- ----

Guess a letter:
  

This display has two main components:

Guessed Letters
Shows the letters the player has guessed so far. The letters will be separated by a space and should be all capitalized. When the game starts, no letters have been guessed, so this area is blank. The letters should be displayed in alphabetical order.
Movie
This shows the movie that the player is trying to guess. Each dash represents a letter in the movie (we'll use dashes not underscores since it allows you to see the separate characters). The spaces between words are shown to help the person playing figure out how many words are in the movie. The movie above is three words: the first with eight letters, the second with five letters, etc. As the user plays, the correctly guessed letters will be filled in.

The following transcript shows these different situations happening as the game is being played:

___________________
Guessed letters:
Movie: - - - - - - - -   - - - - -   - - - -

Guess a letter: e

___________________
Guessed letters: E
Movie: - - - - - - - -   - E - E -   - - E -

Guess a letter: s

___________________
Guessed letters: E S
Movie: - - - - - - - -   - E - E -   - - E S

Guess a letter: a

___________________
Guessed letters: A E S
Movie: - - - - - - - -   - E - E -   - - E S

Guess a letter:
  

In the first two guesses the letter was in the movie, but in the third it was not.

The game ends when the user fills in all of the dashes in the word. The movie is displayed along with the number of guesses that it took the user. For example, here are the last two guesses and the winning output:

___________________
Guessed letters: A E I M N O R S T V
Movie: T O M O R R O -   N E V E R   - I E S

Guess a letter: w
___________________
Guessed letters: A E I M N O R S T V W
Movie: T O M O R R O W   N E V E R   - I E S

Guess a letter: d
___________________
You win!
The movie was: tomorrow never dies
You guessed it with 12 guesses
  

High-Level Implementation

Your program will be keeping track of two key pieces of information. First, the dashed version of the movie that is partially filled in. For this program, we're going to represent this as a list of strings. For example, in the transcript shown above, the list would start out as:

['-', '-', '-', '-', '-', '-', '-', '-', ' ', '-', '-', '-', '-', '-', ' ', '-', '-', '-', '-']

With each position corresponding to a letter (including spaces) in the movie TOMORROW NEVER DIES. As the user guesses correctly, this will be updated. For example, after guessing 'E' and 'A' this list would then be:

['-', '-', '-', '-', '-', '-', '-', '-', ' ', '-', 'e', '-', 'e', '-', ' ', '-', '-', 'e', '-']

Which we see displayed as:

Movie: - - - - - - - -   - E - E -   - - E -

The second piece of information that you'll need to keep track of is the list of letters that have been guessed so far. Again, we'll just use a list of strings to keep track of this. The program then revolves around:

  1. Display the current state of the game to the user and get the next letter.
  2. Check to see if the letter is in the word. If it is, update the list with the dashed representation.
  3. Repeat.

Make sure you understand the basic setup of how we're going to tackle this problem!

Implementation Requirements

http://www.cravingtech.com/best-cyanide-and-happiness-comic-strips.html

Besides following the game specification described above, your program must meet the following requirements:

  1. Your program must contain the following four functions:
    1. generate_underscore, which takes the movie (as a string) as a parameter and returns a list representing the underscored version of the word where each character in the movie is represented as a dash (`-'), except for spaces, which are kept as spaces.
      >>> generate_underscore("monsters inc")
      ['-', '-', '-', '-', '-', '-', '-', '-', ' ', '-', '-', '-']
                
    2. list_to_string, which takes a list of strings as a parameter and returns the letters in the list as a single string, with each letter capitalized and separated by a space.
      >>> monster = generate_underscore("monsters inc")
      >>> list_to_string(monster)
      '- - - - - - - -   - - -'
                
    3. insert_letter, which takes three parameters: a letter (as a string), a list of strings representing the current dashed version that the user has filled in so far and, the movie that the user is trying to guess (as a string). This function should update the current dashed version of the movie assuming the user guessed the letter AND assuming that the letter is in the movie. This function can either modify the existing dashed list (and then not return anything) or it can return a new list. Make sure you understand the difference between these two approaches and actively decide on one or the other (personally, I find the latter easier to test and reason about). Here would be the output of the function if it returned a new list:
      >>> insert_letter("k", ['-', '-', 'n', 'g', ' ', '-', '-', 'n', 'g'], "king kong")
      ['k', '-', 'n', 'g', ' ', 'k', '-', 'n', 'g']
      

      Hint: Notice that there is a direct, index-wise correspondence between the dashed version of the word and the word itself, e.g. for the example above (adding some spaces to make it line up):

      ['-', '-', 'n', 'g', ' ', '-', '-', 'n', 'g']
        0    1    2    3    4    5    6    7    8
      ' k    i    n    g         k    o    n    g'
                

      Use this correspondence to make your implementation easier!

    4. play_hangman, which takes no parameters. This function should initiate the hangman game and continue to run until the game finishes.
  2. Your program should properly use the above four functions.
  3. Your program should be able to handle upper-case or lower-case letters as input.
  4. The guessed letters shows should all be capitalized and shown in alphabetical (hint: sorted) order.

One Path to Implementation

There are many different ways to implement your program, but here is one suggestion:

  1. Write the generate_underscore function. The only tricky thing here is that you need to do something different depending on whether the letter is a space or not. Remember, we can iterate over the characters in a string using a for loop.
  2. Write the list_to_string function. This should be very similar to list functions you've written previously (or that we've looked at in class). There is a string method called upper that might be useful.
  3. Write the insert_letter function. There are many ways to do this, so think about how you'd like to approach it. The key observation here is that the movie to be guessed and the list representing the current dashed version of the movie are of the same length and there is a direct correspondence between the two, as noted above.
  4. Write play_hangman incrementally, testing each step before moving on to the next:
    1. Start by having it pick a random movie entry and then display the corresponding information. There is a function called choice in the random module that might be useful, though there are many ways to do this. Also, there is a method of the string class called title that will help your output look nicer. Note, when you're developing, feel free to print out other information (like the word you're supposed to be guessing) to help you debug your program. Just make sure to remove this information before you hand it in.
    2. Add the user input and add the letter that the user guessed into the underscored word appropriately (your functions from above should be useful).
    3. Add in functionality to keep track of the letters the user has guessed and to print out the letters guessed in sorted order.
    4. Add the functionality to make sure that the user continues to be prompted to enter a new letter as long as the letter input has already been guessed.
    5. End the game when the user gets the right answer.
    6. Print out the appropriate information for after the user finishes the game.

Here are some things to think about:

When you're done

Make sure your program is well-commented, follows naming conventions, uses good variable names, uses whitespace properly, and doesn't have overly long lines. Ensure that all your loops and conditionals are actually necessary.

FeatureValue
A different random movie is picked each time1
Movie information is displayed appropriately1
Initial underscored word shows correctly2
Each guess is inserted properly in underscored movie3
Guessed letters are correctly displayed2
Letters in the movie title are updated correctly1
Game ends when movie is guessed2
Game win output printed correctly1
Handles lower- and upper-cased letters1
Follows function specifications (autograder)11
Comments, style5
Total 28