代碼解析
導入模塊和定義單詞列表
import tkinter as tk
import randomsample_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 = rootself.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 = Falsefor 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 = 0if 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))breaklabel = 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.speedself.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 = Trueself.entry.config(state='disabled')returnself.root.after(50, self.drop_words)
- 如果游戲未結束,所有單詞按速度下落
- 如果單詞下落超過畫布高度,顯示游戲結束信息并禁用輸入框
- 使用'
root.after'
方法定時調用'drop_words'
方法實現動畫效果
檢查用戶輸入
def check_input(self, event):if self.game_over:returninput_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 += charelse:breakremaining_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 = rootself.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 = Falsefor 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 = 0if 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))breaklabel = 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.speedself.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 = Trueself.entry.config(state='disabled')returnself.root.after(50, self.drop_words)def check_input(self, event):if self.game_over:returninput_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 += charelse:breakremaining_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()returnif __name__ == "__main__":root = tk.Tk()game = TypingGame(root)root.mainloop()