In this post, I share the code and design of my quick but scalable script for writing a fill-in-the-blank application written in Python. You can play a smaller version of the game right here on this page (below). At the end of the post, you’ll find a link to a more refined, UI-polished, online version with more questions of the game.
The Concept: The idea is simple and age-old. You are given a sentence with a blank word (shown as underlines) that you’re supposed to guess. You type it in and hit ENTER. The game will tell you immediately if the answer is correct or not. As an added feature, there is also a set of words shown for each sentence presented called the “WordBank”…one of those words in that bank is the correct answer (so you don’t have to worry about remembering how to spell some words either). The entries are case-insensitive. If 3 incorrect answers were entered, the game ends, otherwise, it continues until the entire list of questions are covered.
The Design: What makes this scalable is that it separates the questions from the code by having them in a separate file. That file called “fillinblank_tabbed.txt” in my case is in the same location as the script .py file. That file also contains the correct answers, words to show in the WordBank. The code is written such that there’s no limit to how many questions can be added to the game, and requires no code change. The “fillinblank_tabbed.txt” can be edited in a text editor to add or remove questions and the app will pick up the latest version of it. Just be aware that this version expects the “fillinblank_tabbed.txt” file to be tab-separated (not comma-separated) so be sure to respect the format and keep the columns intact, which are ‘Question’, ‘Answer’, ‘WordBank’. Each line contains these columns, separated by a tab in-between. The code figures out how many questions to pose in the game by counting the lines in the file at run-time making it scalable and dynamic, although technically, it counts the number of rows in a pandas dataframe since the file is loaded into a dataframe.
In a real-world, the text would be either in binary (not readinly human-readable), or encrypted, or located remotely in a server that’s under your control, to prevent cheating or modification by the user.
Explanation of the Code: I used pandas library to load the file containing the game questions using read_csv() although it’s not really a csv file, but tab-delimited. So, I specify the delimiter as a tab.
I used string.split() for WordBank column strings to break the strings into separate words (by comma delimiter). Then use .join() to display the words as a string. The WordBank column contains multiple words separated by a comma in-between.
I used random.shuffle() to randomize the WordBank words.
I used dataframe.iterrows() in a for loop to go over each row and select column values from the dataframe. Then dataframe.sample(frac=1) to randomly sample the rows, that way, the order of questions will be different every time it’s run. Other than the other usual functions, I used len(dataframe) to get the number of total questions, so we can calculate a score as a percentage of correct answers, regardless of how many questions were in the loaded file.
The rest of it can be thought of as optional. Things like the usage of unicode for ease of reading for the user, the animated text (typewriter effect) display to get user’s attention, etc.
Have a go at it! Press the button on the widget below to run the program. The complete code is shown on the left-pane.
If you’re interested in playing a more refined version of the game here, you can try my version here which uses educaplay’s platform and its polished interface supports modern UI, touch, mouse, animations, and sound, and I have added additional questions.
Have fun playing with it, create your own version if you like, or even without any modification to the code, just add more questions in the tabbed format in the “fillinblank_tabbed.txt” once you download the code and the “fillinblank_tabbed.txt” files locally (they should be in the same directory together or just specify the path in code to the .txt file if in a different location from the source).
Related: