Typing Speed Test Game using Python

Introduction:
In this article, we will create a Typing Speed Test Game using Python and Tkinter. This game will help users check how fast they can type in Words Per Minute (WPM) and also measure their typing accuracy. Whether you’re new to Python or have some experience, this project is a fun way to practice coding while improving your typing speed!
Typing is an important skill for everyone who uses computers, whether it’s for coding, writing, or everyday communication. In this article, we will show you how to make a Typing Speed Test Game that calculates your typing speed (WPM) and accuracy based on a text.
The game will help you track your typing performance, making it a great tool for improving your typing speed. We will use Python and Tkinter, which is a built-in library for creating simple graphical interfaces, to build the game. The game will have a basic interface where users can type random text, and it will track how well they do.
Required Modules or Packages:
To build this typing speed test game, you will need the following Python modules:
Tkinter: A built-in library in Python that helps create graphical user interfaces (GUIs).
Time: A Python module used to measure time intervals.
Random: A module used to generate random text for the typing challenge.
If Tkinter is not installed on your system, you can install it using the following command in your terminal:
pip install tk
How to Run the Code:
Follow these steps to run the Typing Speed Test Game on your system:
Make sure Python is installed on your computer.
Install Tkinter using pip (if it’s not already installed).
Copy the full code provided below into a Python file (e.g.,
typing_speed_test.py
).Open your terminal or command prompt, go to the folder where the file is saved, and run the file using the command:
python typing_speed_test.py
5. The game window will open, and you can start typing the displayed text to test your speed and accuracy.
Code Explanation:
In this section, we will go through the key parts of the code that make the Typing Speed Test Game work.
Importing Libraries:
import time
import random
import tkinter as tk
from tkinter import font
We import the required modules for time tracking, random text selection, and GUI creation using Tkinter.
Class Initialization (__init__ method):
The __init__
method sets up the main window, custom fonts, and prepares the layout by calling the setup_ui
method and initializing the test.
def __init__(self, root):
self.root = root
self.setup_ui()
self.new_test()
UI Setup (setup_ui method):
The setup_ui
method creates the layout of the game: adding labels for the title, sample text, input box for typing, and a restart button.
def setup_ui(self):
self.header = tk.Label(self.root, text="Typing Speed Test Game", font=self.title_font)
self.sample_label = tk.Label(self.sample_frame, text="", font=self.text_font)
self.input_text = tk.Text(self.root, font=self.text_font, height=5, width=60)
self.restart_btn = tk.Button(self.btn_frame, text="New Test", command=self.new_test)
self.result_label = tk.Label(self.root, text="", font=self.result_font)
Starting a New Test (new_test method):
The new_test
method selects a random typing challenge text and prepares the game for a fresh start by resetting the input box and clearing results.
def new_test(self):
self.original_text = random.choice(self.texts)
self.sample_label.config(text=self.original_text)
self.input_text.delete(1.0, tk.END)
self.result_label.config(text="")
Start Timer (start_timer method):
The start_timer
method tracks the time when the user begins typing and starts the timer upon the first keystroke.
def start_timer(self, event):
if not self.running:
self.running = True
self.start_time = time.time()
self.root.after(100, self.update_timer)
Update Timer (update_timer method):
This method updates the time every 100 milliseconds and displays the elapsed time.
def update_timer(self):
if self.running:
elapsed_time = time.time() - self.start_time
self.result_label.config(text=f"Time: {elapsed_time:.2f} seconds")
self.root.after(100, self.update_timer)
Displaying Final Results (show_final_results method):
Once the user finishes typing, this method calculates the Words Per Minute (WPM), accuracy, and elapsed time, then displays the results.
def show_final_results(self):
elapsed_time = time.time() - self.start_time
wpm = int(len(user_input.split()) / (elapsed_time / 60))
accuracy = (correct / len(self.original_text)) * 100
result_text = f"Time: {elapsed_time:.2f}s | WPM: {wpm} | Accuracy: {accuracy:.1f}%"
self.result_label.config(text=result_text)
Running the Application:
Finally, we run the main Tkinter event loop to keep the game window open
if __name__ == "__main__":
root = tk.Tk()
app = TypingSpeedTest(root)
root.mainloop()
Source Code:
import time
import random
import tkinter as tk
from tkinter import font
def get_text():
texts = [
"The quick brown fox jumps over the lazy dog.",
"Python programming is fun and engaging.",
"Typing tests improve your speed and accuracy.",
"Practice makes perfect when it comes to typing."
]
return random.choice(texts)
class TypingSpeedTest:
def __init__(self, root):
self.root = root
self.root.title("Typing Speed Test")
self.root.geometry("800x600")
self.root.configure(bg='#F0F0F0')
# Custom fonts
self.title_font = font.Font(family="Helvetica", size=24, weight="bold")
self.text_font = font.Font(family="Courier New", size=16)
self.result_font = font.Font(family="Arial", size=14, weight="bold")
# Initialize variables
self.start_time = None
self.running = False
self.original_text = ""
# Build UI
self.setup_ui()
self.new_test()
def setup_ui(self):
self.header = tk.Label(self.root, text="Typing Speed Test", font=self.title_font, bg='#F0F0F0', fg='#2C3E50')
self.header.pack(pady=20)
self.sample_frame = tk.Frame(self.root, bg='white', padx=20, pady=20)
self.sample_frame.pack(pady=10, fill=tk.X, padx=40)
self.sample_label = tk.Label(
self.sample_frame,
text="",
font=self.text_font,
bg='white',
fg='#34495E',
wraplength=700,
justify=tk.LEFT
)
self.sample_label.pack()
self.input_text = tk.Text(
self.root,
font=self.text_font,
height=5,
width=60,
padx=10,
pady=10,
wrap=tk.WORD,
bg='#FFFFFF'
)
self.input_text.pack(pady=20)
self.input_text.bind("", self.start_timer) # 🛠️ Binding the typing event
self.btn_frame = tk.Frame(self.root, bg='#F0F0F0')
self.btn_frame.pack(pady=10)
self.restart_btn = tk.Button(
self.btn_frame,
text="New Test",
font=self.text_font,
command=self.new_test,
bg='#3498DB',
fg='white'
)
self.restart_btn.pack(side=tk.LEFT, padx=10)
self.result_label = tk.Label(
self.root,
text="Click the text area below to start typing!",
font=self.result_font,
bg='#F0F0F0',
fg='#27AE60'
)
self.result_label.pack(pady=20)
def new_test(self):
self.original_text = get_text()
self.sample_label.config(text=self.original_text)
self.input_text.delete('1.0', tk.END)
self.result_label.config(text="Click the text area below to start typing!", fg='#27AE60')
self.running = False
self.start_time = None
self.input_text.config(bg='#FFFFFF', state=tk.NORMAL)
self.input_text.focus_set()
def start_timer(self, event):
if not self.running:
self.running = True
self.start_time = time.time()
self.input_text.config(bg='#F9EBEA')
self.result_label.config(text="Typing...", fg='#E74C3C')
self.root.after(100, self.update_timer)
self.check_completion()
def update_timer(self):
if self.running:
elapsed = time.time() - self.start_time
wpm = self.calculate_wpm(elapsed)
self.result_label.config(text=f"Elapsed Time: {elapsed:.1f}s | WPM: {wpm}")
self.root.after(1000, self.update_timer)
def calculate_wpm(self, elapsed):
typed_text = self.input_text.get('1.0', 'end-1c')
typed_words = len(typed_text.split())
return int(typed_words / (elapsed / 60)) if elapsed > 0 else 0
def check_completion(self):
user_input = self.input_text.get('1.0', 'end-1c')
if user_input == self.original_text:
self.show_final_results()
def show_final_results(self):
self.running = False
self.input_text.config(state=tk.DISABLED)
elapsed_time = time.time() - self.start_time
user_input = self.input_text.get('1.0', 'end-1c')
min_length = min(len(self.original_text), len(user_input))
correct = sum(1 for o, t in zip(self.original_text, user_input) if o == t)
accuracy = (correct / len(self.original_text)) * 100 if len(self.original_text) > 0 else 0
wpm = self.calculate_wpm(elapsed_time)
result_text = (
f"Time: {elapsed_time:.2f}s | WPM: {wpm} | Accuracy: {accuracy:.1f}%\n"
"Press 'New Test' to try again!"
)
if user_input == self.original_text:
result_text = "Perfect! " + result_text
self.result_label.config(text=result_text, fg='#27AE60')
self.input_text.config(bg='#EAFAF1')
if __name__ == "__main__":
root = tk.Tk()
app = TypingSpeedTest(root)
root.mainloop()
Output
