
Since there aren't very many Python tuts on the forum, I won't presume knowledge of the language, but will instead explain parts of the syntax that may be unfamiliar to most of you.
What I will presume, however, is that you have Python 3.x installed (very important lol). If you don't know how to get everything going, you can check out my other tutorial here: Getting started with Python (Coming soon)
Now that those few things are cleared out, let's get started, shall we. The goal of this tutorial will be to make a game (because I believe games are the best way to practice a language) of hangman. Of course, I won't be diving into GUIs with Python just yet, so this will be a command-line game. Still very fun, though


Launch your favourite IDE, or Notepad, if you wish, and save a file as "hangman.py". Python doesn't require you use the py extension to execute files, but some IDEs use the extension to determine which syntax to highlight... and it's just good practice anyway.
This is a small script, so there won't be much code, and only one function. First and foremost, however, we'll want to import a few modules:
Code: Select all
import random
import math
Next comes our global variables (they're global by default because they're not inside another function). We have four of there:
Code: Select all
word_list = ['programming','python','hangman','codenstuff','tutorial','potato'] #A list of words from which the script can choose
already_used = "" #Will contain the letters that have already been guessed (to prevent double-guessing a letter)
mistakes = 0 #The number of mistakes the player is at
figures = ["""\
/---| {0}
|
|
|
|
-
{1}""",
"""\
/---| {0}
| O
|
|
|
-
{1}""",
"""\
/---| {0}
| O
| |
|
|
-
{1}""",
"""\
/---| {0}
| O
| /|
|
|
-
{1}""",
"""\
/---| {0}
| O
| /|\\
|
|
-
{1}""",
"""\
/---| {0}
| O
| /|\\
| /
|
-
{1}""",
"""\
/---| {0}
| O
| /|\\
| / \\
|
-
{1}"""]
figures is another example of a list. It contains variables of type String, and as you can see, these strings span multiple lines. This is because we used the triple quote (""" or ''') to enclose each string. Make sure you get the indentations right in the Strings, or else it'll look all messed up when it's printed to the screen.
This may already be obvious to you, but everything following a pound (#) on a line is a comment.
Now that our variables are declared, the fun can begin. We'll start by declaring our first and only function for this script:
Code: Select all
def start_game():
Note: Unlike most languages, Python doesn't delimit blocks of code with brackets or closing tags, instead, each block of code is indented. And the indentations must be consistend throughout the script (in accordance with PEP8, I use four spaces per indentation). For example, the code contained in the level directly beneath our function will be indented once. Code that will be inside another structure within that same function will be indented twice (the code inside an if structure, for example).
To make it easier for you guys, I'll put a number of > "greater than" symbols corresponding to the number of spaces in front of each line. If there's nothing in front of a line, then the line requires no indentation. DO NOT copy those symbols in your code, but replace them with spaces.
We can now proceed to add two (indented) statements that will be used to reset the game once the player either wins or loses:
Code: Select all
>>>>#Variables are reset
>>>>mistakes = 0
>>>>already_used = ""
Code: Select all
>>>>#A new word is chosen and the correct figure is displayed
>>>>chosen_word = word_list[math.floor(len(word_list) * random.random())].lower()
>>>>visible_word = "_ " * len(chosen_word)
Since we want a random number, we'll multiply random.random() (which returns a number between 0 and 1 exclusively) by the length (or number of items) in word_list and get the integer part of that number with math.floor(). Also, to avoid mixing upper and lowercase characters, we'll convert the whole word to lowercase using lower().
The second statement simply affects a number of underscores followed by a space to the variable visible_word. This is so we can "hide" the word from the user until he has guessed all the letters. Notice we're using a multiplication symbol with a String. Strange, isn't it? Python allows you to do that. It basically comes back to repeating that same string ("_ ") x number of times (x being the number after the * symbol). So "_ " * 4 will give us "_ _ _ _ ".
Just to make things a little prettier, we're going to print some text, the title of the game:
Code: Select all
>>>>#Print the title (just cuz :-) )
>>>>print("----------PyMan Hangman----------\n")
Code: Select all
>>>>while True:
>>>>>>>>print(figures[mistakes].format(already_used, visible_word)+"\n")
Now, before we ask the user for input, we'll check to see if he's already won or lost. There's a simple way of doing this. If visible_word (ie, the text that is displayed to the user) contains no underscores, it means he/she has guessed all the letters in the word, therefore has won:
Code: Select all
>>>>>>>>if not "_" in visible_word:
>>>>>>>>>>>>print("Congratulations, you guessed the word",chosen_word,"correctly!")
>>>>>>>>>>>>input()
>>>>>>>>>>>>start_game()
input() would normally ask for input from the user, but since we didn't put any prompt withing the parentheses, it'll display a blank line and wait for the user to press ENTER, then call start_game() which will restart the game.
Another possibility is that the user lost. This is determined by the number of mistakes the user has made. In our case, that number is 6. So let's add another condition to our if structure.
Code: Select all
>>>>>>>>elif mistakes == 6:
>>>>>>>>>>>>print("You have lost. The word was",chosen_word,".")
>>>>>>>>>>>>input()
>>>>>>>>>>>>start_game()
Much like the winning case, the losing case will display a message, followed by the input() function to wait for the user to press ENTER before restarting the game.
If neither of these conditions apply, it means the game should continue. It's not time to prompt the user for a letter and continue on:
Code: Select all
>>>>>>>>else:
>>>>>>>>>>>>guess = input("Guess a letter: ").lower()
Next comes validation of the user's guess. We want to make sure it's a letter (since everything is lowercase, we'll make sure it's between lowercase 'a' and lowercase 'z') and that the user didn't try to guess more than one letter at a time (you could add an option for the user to guess the whole word or part of it, but we won't conver that in this tutorial):
Code: Select all
>>>>>>>>>>>>if len(guess) == 1 and ord(guess) >= 97 and ord(guess) <= 122:
>>>>>>>>>>>>else:
>>>>>>>>>>>>>>>>print("You must enter only one valid character, try again")
Interesting fact: since ord() take a length 1 String as it's parameter, feeding it a String any longer that that (ie, when the user enters an answer longer than one character) would cause the program to crash. However, Python has this interesting and very useful property of not evalutating the rest of an if statement if the first AND condition evaluates to false. This makes sense, as AND will invariably result in False if a condition on either side of it is false. Therefore, by placing the len() function before the AND, if the length of the guess is more than 1, ord() is never called and can therefore not crash the program.
Let's continue now. Once we know the user has given us a valid character, we want to make sure he hasn't already used it. This is where the already_used variable comes in handy. We'll use something we've already seen a bit earlier: checking for a character in a String, to validate this. The following code should go inside the previous if structure, before the else:
Code: Select all
>>>>>>>>>>>>>>>>if not guess in already_used:
>>>>>>>>>>>>>>>>else:
>>>>>>>>>>>>>>>>>>>>print("You have already used that letter!")
Code: Select all
>>>>>>>>>>>>>>>>>>>>if guess in chosen_word:
>>>>>>>>>>>>>>>>>>>>else:
>>>>>>>>>>>>>>>>>>>>>>>>mistakes += 1
>>>>>>>>>>>>>>>>>>>>>>>>print("Sorry, that is incorrect!")
>>>>>>>>>>>>>>>>>>>>#Adds the guessed letter to the guessed list
>>>>>>>>>>>>>>>>>>>>already_used += guess
The following must be added before the else:, inside the above if structure:
Code: Select all
>>>>>>>>>>>>>>>>>>>>>>>>new_visible = ""
>>>>>>>>>>>>>>>>>>>>>>>>for c in range(len(chosen_word)):
We also start a for loop, which you should be familiar with. range() returns a series of numbers, in this case from 0 to the length of chosen_word (exclusively), through which the loop will iterate. Inside this loop we'll insert the following code:
Code: Select all
>>>>>>>>>>>>>>>>>>>>>>>>>>>>if guess == chosen_word[c]:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>new_visible += guess + " "
>>>>>>>>>>>>>>>>>>>>>>>>>>>>else:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>new_visible += visible_word[c*2:c*2+2]
If it is not, however, there is still the possibility that the letter has already been found. So instead of simply appending an underscore and a space, we use visible_word and extract whatever characters are between the indexes on either side of the colon within the brackets ([x:y]). In Python, this is known as slicing. It creates a substring of the String on which we performed the slicing.
There's one last thing we need to do now: make visible_word equal to new_visible. The following line of code will be outside the for loop, so it will be indented the same as new_visible="":
Code: Select all
>>>>>>>>>>>>>>>>>>>>>>>>visible_word = new_visible
Code: Select all
>>>>return 0
And finally:
Code: Select all
if __name__ == "__main__":
>>>>start_game()

That's it! You're now ready to run your script (again, if you're not sure how, you can refer to my 'Getting Started tutorial'). Have fun adding your own words to the list, and challenging yourself or friends to guess them lol cooll;
Full Code
Code: Select all
import random
import math
word_list = ['programming','python','hangman','codenstuff','tutorial','potato'] #A list of words from which the script can choose
already_used = "" #Will contain the letters that have already been guessed (to prevent double-guessing a letter)
mistakes = 0 #The number of mistakes the player is at
figures = ["""\
/---| {0}
|
|
|
|
-
{1}""",
"""\
/---| {0}
| O
|
|
|
-
{1}""",
"""\
/---| {0}
| O
| |
|
|
-
{1}""",
"""\
/---| {0}
| O
| /|
|
|
-
{1}""",
"""\
/---| {0}
| O
| /|\\
|
|
-
{1}""",
"""\
/---| {0}
| O
| /|\\
| /
|
-
{1}""",
"""\
/---| {0}
| O
| /|\\
| / \\
|
-
{1}"""]
def start_game():
>>>>#Variables are reset
>>>>mistakes = 0
>>>>already_used = ""
>>>>#A new word is chosen and the correct figure is displayed
>>>>chosen_word = word_list[math.floor(len(word_list) * random.random())].lower()
>>>>visible_word = "_ " * len(chosen_word)
>>>>#Print the title (just cuz :-) )
>>>>print("----------PyMan Hangman----------\n")
>>>>while True:
>>>>>>>>print(figures[mistakes].format(already_used, visible_word)+"\n")
>>>>>>>>if not "_" in visible_word:
>>>>>>>>>>>>print("Congratulations, you guessed the word",chosen_word,"correctly!")
>>>>>>>>>>>>input()
>>>>>>>>>>>>start_game()
>>>>>>>>elif mistakes == 6:
>>>>>>>>>>>>print("You have lost. The word was",chosen_word,".")
>>>>>>>>>>>>input()
>>>>>>>>>>>>start_game()
>>>>>>>>else:
>>>>>>>>>>>>guess = input("Guess a letter: ").lower()
>>>>>>>>>>>>if len(guess) == 1 and ord(guess) >= 97 and ord(guess) <= 122:
>>>>>>>>>>>>>>>>if not guess in already_used:
>>>>>>>>>>>>>>>>>>>>if guess in chosen_word:
>>>>>>>>>>>>>>>>>>>>>>>>new_visible = ""
>>>>>>>>>>>>>>>>>>>>>>>>for c in range(len(chosen_word)):
>>>>>>>>>>>>>>>>>>>>>>>>>>>>if guess == chosen_word[c]:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>new_visible += guess + " "
>>>>>>>>>>>>>>>>>>>>>>>>>>>>else:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>new_visible += visible_word[c*2:c*2+2]
>>>>>>>>>>>>>>>>>>>>>>>>visible_word = new_visible
>>>>>>>>>>>>>>>>>>>>else:
>>>>>>>>>>>>>>>>>>>>>>>>mistakes += 1
>>>>>>>>>>>>>>>>>>>>>>>>print("Sorry, that is incorrect!")
>>>>>>>>>>>>>>>>>>>>#Adds the guessed letter to the guessed list
>>>>>>>>>>>>>>>>>>>>already_used += guess
>>>>>>>>>>>>>>>>else:
>>>>>>>>>>>>>>>>>>>>print("You have already used that letter!")
>>>>>>>>>>>>else:
>>>>>>>>>>>>>>>>print("You must enter only one valid character, try again")
>>>>return 0
if __name__ == "__main__":
>>>>start_game()


This file is hosted off-site.