代码解析

导入模块和定义单词列表

import tkinter as tk
import random

sample_words = [
    "apple", "banana", "cherry", "date", "fig", "grape", 
    "kiwi", "lemon", "mango", "orange", "papaya", "quince", 
    "ugli", "vanilla", "yam"
]
  • 导入'tkinter'库用于创建 GUI
  • 导入'random'库用于随机选择单词 
  • 定义'sample_words'列表包含游戏中可能出现的单词
  • TypingGame 类的初始化

    class TypingGame:
        def __init__(self, root):
            self.root = root
            self.root.title("打字练习")  # 修改窗口标题
    
            self.canvas = tk.Canvas(self.root, width=800, height=600, bg="white")
            self.canvas.pack()
    
            self.user_input = tk.StringVar()
    
            self.words = []
            self.labels = []
            self.word_y_positions = []
            self.speed = 2  # 掉落速度
    
            self.game_over = False  # 游戏状态
    
            self.create_widgets()
            self.new_round()
    
  • 初始化游戏类,设置窗口标题和画布 
  • 创建'user_input'变量用于存储用户输入
  • 初始化'words'、'labels'和'word_y_positions'列表
  • 设置'speed'变量控制单词下落速度
  • 初始化'game_over'状态
  • 调用'create_widgets'方法创建控件,并开始新一轮游戏
  • 创建控件

        def create_widgets(self):
            self.entry = tk.Entry(self.root, textvariable=self.user_input, width=50)
            self.entry.pack(pady=10)
            self.entry.bind("<KeyRelease>", self.check_input)
    
            self.result_label = tk.Label(self.root, text="", wraplength=400)
            self.result_label.pack(pady=10)
    
            self.new_round_button = tk.Button(self.root, text="New Round", command=self.new_round)
            self.new_round_button.pack(pady=10)
    
            # 将输入法锁定为英语
            self.root.bind('<FocusIn>', self.set_english_input)
    
  • 创建输入框、结果标签和新一轮按钮,并将它们放置在窗口中
  • 绑定'KeyRelease'事件到'check_input'方法,监听用户输入
  • 绑定'FocusIn'事件到'set_english_input'方法,以确保输入法锁定为英语
  • 设置输入法为英语

        def set_english_input(self, event):
            self.root.tk.call('tk', 'scaling', 1.0)  # 假定的命令以确保输入法锁定为英语
    
  • 绑定窗口获取焦点时设置输入法为英语
  • 新一轮游戏

        def new_round(self):
            num_words = random.randint(1, 5)  # 随机选择1到5个单词
            self.words = random.sample(sample_words, num_words)  # 选择不重复的单词
            self.user_input.set("")
            self.result_label.config(text="")
            self.word_y_positions = [0 for _ in self.words]
            self.game_over = False
    
            for label in self.labels:
                self.canvas.delete(label)
            self.labels = []
            used_positions = []
            for word in self.words:
                while True:
                    x_position = random.randint(50, 750 - len(word) * 15)  # 确保单词不会超出边界
                    y_position = 0
                    if not any(abs(x_position - pos[0]) < len(word) * 15 and abs(y_position - pos[1]) < 30 for pos in used_positions):
                        used_positions.append((x_position, y_position))
                        break
                label = self.canvas.create_text(x_position, y_position, text=word, font=("Helvetica", 24), fill="black")
                self.labels.append(label)
    
            self.entry.config(state='normal')
            self.entry.focus()
            self.drop_words()
    
  • 随机选择1到5个不重复的单词
  • 清空输入框和结果标签,重置单词位置和游戏状态
  • 删除旧的标签并创建新的标签,确保单词不会重叠
  • 调用'drop_words'方法开始单词下落
  • 单词下落

        def drop_words(self):
            if not self.game_over:
                for i, label in enumerate(self.labels):
                    self.word_y_positions[i] += self.speed
                    self.canvas.coords(label, self.canvas.coords(label)[0], self.word_y_positions[i])
                    if self.word_y_positions[i] >= 600:
                        self.result_label.config(text=f"Game Over! The word was: {self.words[i]}")
                        self.game_over = True
                        self.entry.config(state='disabled')
                        return
                self.root.after(50, self.drop_words)
    
  • 如果游戏未结束,所有单词按速度下落
  • 如果单词下落超过画布高度,显示游戏结束信息并禁用输入框
  • 使用'root.after'方法定时调用'drop_words'方法实现动画效果
  • 检查用户输入

        def check_input(self, event):
            if self.game_over:
                return
    
            input_text = self.user_input.get()
            for index, word in enumerate(self.words):
                if word.startswith(input_text):
                    correct_text = ""
                    for i, char in enumerate(input_text):
                        if i < len(word) and char == word[i]:
                            correct_text += char
                        else:
                            break
                    remaining_text = word[len(correct_text):]
                    self.canvas.itemconfig(self.labels[index], text=f"{correct_text}{remaining_text}")
                    self.canvas.itemconfig(self.labels[index], fill="green" if correct_text else "black")
                else:
                    self.canvas.itemconfig(self.labels[index], fill="black")
    
                if input_text == word:
                    self.canvas.delete(self.labels[index])
                    self.words.pop(index)
                    self.labels.pop(index)
                    self.word_y_positions.pop(index)
                    self.user_input.set("")  # 清空输入框
    
                    if not self.words:
                        self.result_label.config(text="Correct! Starting new round...")
                        self.new_round()
                    return
    
  • 如果游戏结束,直接返回
  • 获取用户输入并遍历所有单词,检查输入是否与单词开头匹配
  • 将匹配部分的单词变为绿色
  • 如果用户输入完整单词,删除该单词并清空输入框
  • 如果所有单词都被正确输入,开始新一轮游戏
  • 主程序

    if __name__ == "__main__":
        root = tk.Tk()
        game = TypingGame(root)
        root.mainloop()
    
  • 创建主窗口并实例化'TypingGame'
  • 进入'tkinter'主循环,开始游戏
  • 全部代码

    import tkinter as tk
    import random
    
    # 一些示例单词供用户练习
    sample_words = [
        "apple", "banana", "cherry", "date", "fig", "grape", 
        "kiwi", "lemon", "mango", "orange", "papaya", "quince", 
        "ugli", "vanilla", "yam"
    ]
    
    class TypingGame:
        def __init__(self, root):
            self.root = root
            self.root.title("打字练习")  # 修改窗口标题
    
            self.canvas = tk.Canvas(self.root, width=800, height=600, bg="white")
            self.canvas.pack()
    
            self.user_input = tk.StringVar()
    
            self.words = []
            self.labels = []
            self.word_y_positions = []
            self.speed = 2  # 掉落速度
    
            self.game_over = False  # 游戏状态
    
            self.create_widgets()
            self.new_round()
    
        def create_widgets(self):
            self.entry = tk.Entry(self.root, textvariable=self.user_input, width=50)
            self.entry.pack(pady=10)
            self.entry.bind("<KeyRelease>", self.check_input)
    
            self.result_label = tk.Label(self.root, text="", wraplength=400)
            self.result_label.pack(pady=10)
    
            self.new_round_button = tk.Button(self.root, text="New Round", command=self.new_round)
            self.new_round_button.pack(pady=10)
    
            # 将输入法锁定为英语
            self.root.bind('<FocusIn>', self.set_english_input)
    
        def set_english_input(self, event):
            self.root.tk.call('tk', 'scaling', 1.0)  # 假定的命令以确保输入法锁定为英语,如果需要可以进一步研究具体命令
    
        def new_round(self):
            num_words = random.randint(1, 5)  # 随机选择1到5个单词
            self.words = random.sample(sample_words, num_words)  # 选择不重复的单词
            self.user_input.set("")
            self.result_label.config(text="")
            self.word_y_positions = [0 for _ in self.words]
            self.game_over = False
    
            for label in self.labels:
                self.canvas.delete(label)
            self.labels = []
            used_positions = []
            for word in self.words:
                while True:
                    x_position = random.randint(50, 750 - len(word) * 15)  # 确保单词不会超出边界
                    y_position = 0
                    if not any(abs(x_position - pos[0]) < len(word) * 15 and abs(y_position - pos[1]) < 30 for pos in used_positions):
                        used_positions.append((x_position, y_position))
                        break
                label = self.canvas.create_text(x_position, y_position, text=word, font=("Helvetica", 24), fill="black")
                self.labels.append(label)
    
            self.entry.config(state='normal')
            self.entry.focus()
            self.drop_words()
    
        def drop_words(self):
            if not self.game_over:
                for i, label in enumerate(self.labels):
                    self.word_y_positions[i] += self.speed
                    self.canvas.coords(label, self.canvas.coords(label)[0], self.word_y_positions[i])
                    if self.word_y_positions[i] >= 600:
                        self.result_label.config(text=f"Game Over! The word was: {self.words[i]}")
                        self.game_over = True
                        self.entry.config(state='disabled')
                        return
                self.root.after(50, self.drop_words)
    
        def check_input(self, event):
            if self.game_over:
                return
    
            input_text = self.user_input.get()
            for index, word in enumerate(self.words):
                if word.startswith(input_text):
                    correct_text = ""
                    for i, char in enumerate(input_text):
                        if i < len(word) and char == word[i]:
                            correct_text += char
                        else:
                            break
                    remaining_text = word[len(correct_text):]
                    self.canvas.itemconfig(self.labels[index], text=f"{correct_text}{remaining_text}")
                    self.canvas.itemconfig(self.labels[index], fill="green" if correct_text else "black")
                else:
                    self.canvas.itemconfig(self.labels[index], fill="black")
    
                if input_text == word:
                    self.canvas.delete(self.labels[index])
                    self.words.pop(index)
                    self.labels.pop(index)
                    self.word_y_positions.pop(index)
                    self.user_input.set("")  # 清空输入框
    
                    if not self.words:
                        self.result_label.config(text="Correct! Starting new round...")
                        self.new_round()
                    return
    
    if __name__ == "__main__":
        root = tk.Tk()
        game = TypingGame(root)
        root.mainloop()
    

    作者:⁡ ⁡  

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python打字练习工具

    发表回复