Coding - Python 3

Python – Make a Hangman game part 2: prerequisites, JSON, random word

For that project, you’ll need to have installed Python (I used the 3.10.2 version), an IDE where you type your code (I’m using Visual Studio Code, really amazing software), and… that’s about it!

Thinking about how you are going to store your data is important. We could use Python’s built-in database (SQLite), but that would be overkill, let’s make it simple and use a JSON (JavaScript Object Notation) file. The cool thing with JSON is that it can be opened in a text editor, hence easily and quickly edited, and it’s easy to understand its content as it is “human readable”.

So for our game, we’re going to do it like that:

{“language1”:[
    “WORD1”,
    “WORD2”,
    “WORD3”
    ],
“language2”:[
    “WORD1”,
    “WORD2”,
    “WORD3”
]}
Straight-forward, isn’t it?
 
Now, although there is a way to go around that constraint, I deliberately chose to add the words in CAPITAL letters for a better readability and to avoid special characters (if you know some French… é à ç etc.).
Also, having a huge list of words increases the risk of redundancy, and of course we could add some code to check the file at each start and either ignore or remove them from the file, but let’s keep it simple for now.
 
So in your IDE, create a new file and call it words.json (you can call it whatever you want, as long as you use the right name when you import it in your code). And create your desired language and populate it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{"english":[
    "BANANA",
    "PHEASANT",
    "COMPUTER",
    "TABLE",
    "SERINGE",
    "MICROPHONE",
    "THUNDER",
    "OAK",
    "GARDEN",
    "VENTILATOR",
    "MEDICINE",
    "CHAIR"
    ],
"francais":[
    "BANANE",
    "SAUCISSE",
    "CHAISE",
    "HERISSON",
    "PASTEQUE",
    "DODO",
    "TELEPHONE",
    "STYLO",
    "MONITEUR",
    "LAMPE"
]}

So what happens here is that we make a dictionary. A dictionary in Python is presented like that:
{“key1”: “value1”, “key2”: “value2”} and so on.
In the game’s case, a key is the target language, and its value is a list of words in that language. That list is going to be “extracted” in the code in order to randomly get one of its words.


EXTRACT DATA TO USE WHAT WE NEED

Open your IDE. We are about to work with a JSON file, so we must import the json module in order to use it.
Then, let’s make a function that will “open” the file and get whatever we want out of it, here the words in English, and check if it works the way we intended it to.
Why use a function and not directly code? Because not only will your code be cleaner, clearer, it will be more maintainable AND will avoid repeating code. A function can be called multiple times, and any changes made to it will affect wherever it is used, with reduces the risks of errors and skipped code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import json

language = "english"


def loadWords(language):
    with open("words.json") as file:
        return json.load(file)[language]

words = loadWords(language)

print(words)

for word in words:
    print(word)

We loaded the file and returned the part with the key “language” (you could call it however you wish). Then we set the variables words as the function that takes the variable language, defined above the function as language = “english”, which is the same as the “english” key in the JSON file. Note that there is NO capital E. Any misspelling will result in an error, as the program would be looking for something that does not exist.
Now, the list of English words should have been imported, it’s time to make sure it did. Using print() to check/debug your program is one of the easiest ways to do so. Once everything works as intended, you can either change your line into a comment (add “#” before it or simply “CTRL + /”) or remove it.
So let’s print the list of word with print(words). Yay, it worked! You can also print each item (word) in the list by using a for loop.
That’s how your terminal should look like:

[‘BANANA’, ‘PHEASANT’, ‘COMPUTER’, ‘TABLE’, ‘SYRINGE’, ‘MICROPHONE’, ‘THUNDER’, ‘OAK’, ‘GARDEN’, ‘VENTILATOR’, ‘MEDICINE’, ‘CHAIR’]
BANANA
PHEASANT
COMPUTER
TABLE
SYRINGE
MICROPHONE
THUNDER
OAK
GARDEN
VENTILATOR
MEDICINE
CHAIR


GETTING A RANDOM WORD FROM THE LIST

Every item of a list (words, in our case) have an index, which is their position. In Python, strangely, it starts from 0. It’s honestly a pain as it increases the risk or errors, the headaches and the loss of time, even after being used to it. So in a list of 5 words, the index will go from… 0 to 4! It sucks, right? You must understand that to understand how to get a random number in a given range.

Our current list is words = [‘BANANA’, ‘PHEASANT’, ‘COMPUTER’, ‘TABLE’, ‘SYRINGE’, ‘MICROPHONE’, ‘THUNDER’, ‘OAK’, ‘GARDEN’, ‘VENTILATOR’, ‘MEDICINE’, ‘CHAIR’]
To get a specific item, we must use words[index of the item].
If we want to get the “BANANA” word, we’ll write words[0], because “BANANA” is the first item, and its index is 0 (not 1, because why make things simple and logical?).
words[1] is “PHEASANT”, words[2] is “COMPUTER”, …….., words[11] is “CHAIR”.

Do you start seeing what we’re going to do? We are going to get a random number as the index of the list.
For that game, the range will be from 0 to the length of the list. You do not need to know the length, it’s a varying number, the program takes care of that for you. What you need to know is how to use the random module. So like before, import the module by typing import random (below or above import json, the order is not important).

Before getting to it, let’s see how range() works.
In your IDE, type and run:

1
2
for number in range(10):
    print(number)

You’ll see that the terminal prints 0 1 2 3 4 5 6 7 8 9
But no 10! It print 10 items, starting from 0, so 10 is not included. If you wanted 10 to be displayed, you’d have to write range(11).
In our case, it’s fine because the index of the last item in a list is the length of that list – 1. So to get the last item of a list of x items, you would need to write list[x-1].
Back to the length of a list, there is a great way to get it: len(list). That’s all. If you write and run print(len(words)), it should output 12. Cool, so we got what we need to finally randomly get a word out of our list.

We are going to use the randrange() method.
Let’s create a variable called “chosen_word” (always remember to give your variables explicit names to understand what they do, it’ll save you some veeery bad moments), and that chosen word is going to be a word from the list: words[x] where x is a random number.
To get x, we use the method randrange() by doing so:
random.randrange(len(words)) where len(words) is the length of our list words.

If you’ve followed along, you should be having something like that (I removed the previous prints):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import json
import random


language = "english"


def loadWords(language):
    with open("words.json") as file:
        return json.load(file)[language]


words = loadWords(language)

chosen_word = words[random.randrange(len(words))]

print(chosen_word)

Run your code, it should print a word from the list. Run again, and again, etc., it should be different words (well, it could be one that’s already been drawn out, that’s the principle of randomness).
Awesoooooome! We’ve got a word generator! Now what to do with it?


DISPLAYING UNDERSCORES INSTEAD OF LETTERS

Remember the principle of Hangman? You draw strokes/underscores in stead of the letters of the word. So again, by using the length of the chosen word (= how many letters it’s got), we can display the underscores the way we wish. We could just replace each letter with a “_”, but it wouldn’t render well. “WELL” would become “____” (4* “_”). I want space between each character.
To do so, I’m going to use an empty string, and for each character, add “_ ” to that string. The final added space can be ignored (or discarded if you want to). Add that to your code:

1
2
3
4
5
6
result = ""

for c in chosen_word:
    result += "_ "

print(f"{result}")

Now, your terminal should display a random word, and below it underscores that match the number of letters:

MEDICINE
_ _ _ _ _ _ _ _

Can’t believe your eyes, right?
So this is what the user will see (excluding the chosen word, yes…). Now, to the next part to create the input and display the right picked letters!

Leave a Reply