代码解析

导入模块和定义单词列表

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()

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部