我来为您创建一个使用Python Tkinter的卡牌抽取游戏UI。这个程序会实现您描述的所有功能。
这个程序提供了以下功能:
-
牌堆管理:
-
10种不同的牌,每种4张,总共40张牌
-
实时显示牌堆中每种牌的剩余数量
-
用进度条形式直观显示每种牌的数量
-
-
抽取功能:
-
每次显示3张随机抽取的牌
-
可以单独抽取任意一张牌
-
可以一次性抽取全部3张牌
-
抽取后牌堆相应减少
-
-
刷新功能:
-
点击"刷新"按钮将当前未抽取的牌放回牌堆
-
重新洗牌并抽取3张新牌
-
已抽取的牌不会放回牌堆
-
-
显示区域:
-
当前抽取的3张牌(带抽取按钮)
-
用户已抽取的牌(按类型统计)
-
当前牌堆状态
-
游戏统计信息
-
-
游戏控制:
-
重置游戏按钮,可重新开始游戏
-
自动检测游戏结束条件(牌堆不足3张)
-
彩色显示不同类型的牌
-
运行这个程序后,您会看到一个完整的GUI界面,可以按照您的描述进行卡牌抽取游戏。
python
import tkinter as tk
from tkinter import ttk, messagebox
import random
from collections import Counter
class CardGame:
def __init__(self, master, N=10):
self.master = master
self.N = N
self.master.title("卡牌抽取游戏")
self.master.geometry("1000x700")
# 初始化牌堆,每种牌4张
self.card_types = list(range(1, N + 1))
self.initial_counts = {card_type: 4 for card_type in self.card_types}
self.deck = []
self.reset_deck()
# 当前显示的3张牌
self.current_cards = []
# 用户已抽取的牌
self.user_drawn_cards = []
# 游戏状态
self.game_active = True
# 设置样式
self.setup_styles()
# 创建UI
self.create_widgets()
# 初始抽取3张牌
self.draw_initial_cards()
def setup_styles(self):
"""设置样式"""
style = ttk.Style()
style.theme_use('clam')
def reset_deck(self):
"""重置牌堆到初始状态"""
self.deck = []
for card_type, count in self.initial_counts.items():
self.deck.extend([card_type] * count)
def shuffle_deck(self):
"""洗牌"""
random.shuffle(self.deck)
def draw_three_cards(self):
"""从牌堆中抽取3张牌(不放回)"""
if len(self.deck) < 3:
messagebox.showwarning("牌堆不足", "牌堆中剩余牌数不足3张,无法继续游戏!")
self.game_active = False
return []
drawn_cards = []
for _ in range(3):
if self.deck:
card = self.deck.pop(0)
drawn_cards.append(card)
return drawn_cards
def create_widgets(self):
"""创建所有UI组件"""
# 主框架
main_frame = ttk.Frame(self.master, padding="20")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 标题
title_label = ttk.Label(main_frame, text="卡牌抽取游戏", font=("Arial", 20, "bold"))
title_label.grid(row=0, column=0, columnspan=3, pady=(0, 20))
# 牌堆状态区域
deck_frame = ttk.LabelFrame(main_frame, text="当前牌堆状态", padding="10")
deck_frame.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, 20))
self.deck_status_label = ttk.Label(
deck_frame,
text=self.get_deck_status_text(),
font=("Consolas", 10),
wraplength=200
)
self.deck_status_label.pack()
# 抽取的牌显示区域
current_cards_frame = ttk.LabelFrame(main_frame, text="当前抽取的3张牌", padding="20")
current_cards_frame.grid(row=1, column=1, sticky=(tk.W, tk.E, tk.N, tk.S), padx=20)
# 当前3张牌的框架
self.card_frames = []
self.card_labels = []
self.draw_buttons = []
for i in range(3):
card_frame = ttk.Frame(current_cards_frame)
card_frame.grid(row=0, column=i, padx=10)
# 牌显示
card_label = ttk.Label(
card_frame,
text="",
font=("Arial", 24, "bold"),
width=6,
anchor="center",
relief="solid",
padding=10
)
card_label.pack(pady=(0, 10))
self.card_labels.append(card_label)
# 抽取按钮
draw_button = ttk.Button(
card_frame,
text=f"抽取牌{i+1}",
command=lambda idx=i: self.draw_single_card(idx)
)
draw_button.pack()
self.draw_buttons.append(draw_button)
self.card_frames.append(card_frame)
# 用户抽取的牌区域
user_cards_frame = ttk.LabelFrame(main_frame, text="您已抽取的牌", padding="10")
user_cards_frame.grid(row=1, column=2, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(20, 0))
self.user_cards_text = tk.Text(
user_cards_frame,
height=15,
width=20,
font=("Consolas", 10)
)
self.user_cards_text.pack()
self.user_cards_text.config(state=tk.DISABLED)
# 控制按钮区域
control_frame = ttk.Frame(main_frame)
control_frame.grid(row=2, column=0, columnspan=3, pady=20)
# 刷新按钮
self.refresh_button = ttk.Button(
control_frame,
text="刷新牌堆并重新抽取",
command=self.refresh_and_redraw,
width=30
)
self.refresh_button.pack(side=tk.LEFT, padx=5)
# 抽取全部按钮
self.draw_all_button = ttk.Button(
control_frame,
text="抽取全部3张牌",
command=self.draw_all_cards,
width=20
)
self.draw_all_button.pack(side=tk.LEFT, padx=5)
# 重置游戏按钮
self.reset_button = ttk.Button(
control_frame,
text="重置游戏",
command=self.reset_game,
width=15
)
self.reset_button.pack(side=tk.LEFT, padx=5)
# 统计信息
stats_frame = ttk.LabelFrame(main_frame, text="游戏统计", padding="10")
stats_frame.grid(row=3, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=(10, 0))
self.stats_label = ttk.Label(
stats_frame,
text=self.get_stats_text(),
font=("Consolas", 10)
)
self.stats_label.pack()
# 配置网格权重
self.master.columnconfigure(0, weight=1)
self.master.rowconfigure(0, weight=1)
main_frame.columnconfigure(1, weight=1)
def get_deck_status_text(self):
"""获取牌堆状态文本"""
if not self.deck:
return "牌堆已空!"
card_counter = Counter(self.deck)
status_lines = []
for card_type in sorted(card_counter.keys()):
count = card_counter[card_type]
bar = "■" * count
status_lines.append(f"牌{card_type}: {count}张 {bar}")
status_text = f"牌堆总牌数: {len(self.deck)}\n"
status_text += "\n".join(status_lines)
return status_text
def get_stats_text(self):
"""获取统计信息文本"""
card_counter = Counter(self.user_drawn_cards)
stats_lines = []
for card_type in sorted(card_counter.keys()):
count = card_counter[card_type]
stats_lines.append(f"牌{card_type}: 抽取了{count}次")
stats_text = f"您总共抽取了 {len(self.user_drawn_cards)} 张牌\n"
if stats_lines:
stats_text += "\n".join(stats_lines)
return stats_text
def draw_initial_cards(self):
"""初始抽取3张牌"""
self.current_cards = self.draw_three_cards()
self.update_card_display()
self.update_buttons_state()
def update_card_display(self):
"""更新卡牌显示"""
for i, label in enumerate(self.card_labels):
if i < len(self.current_cards):
label.config(text=f"牌{self.current_cards[i]}")
# 为不同牌设置不同颜色
colors = ["lightblue", "lightgreen", "lightcoral", "lightyellow", "lightpink",
"lightcyan", "lightgray", "lightgoldenrodyellow", "lightsalmon", "lightseagreen"]
color_idx = (self.current_cards[i] - 1) % len(colors)
label.config(background=colors[color_idx])
else:
label.config(text="", background="SystemButtonFace")
def update_buttons_state(self):
"""更新按钮状态"""
for i, button in enumerate(self.draw_buttons):
if i < len(self.current_cards) and self.game_active:
button.config(state=tk.NORMAL)
else:
button.config(state=tk.DISABLED)
def draw_single_card(self, card_index):
"""抽取单张牌"""
if not self.game_active or card_index >= len(self.current_cards):
return
# 抽取选中的牌
drawn_card = self.current_cards.pop(card_index)
self.user_drawn_cards.append(drawn_card)
# 更新显示
self.update_card_display()
self.update_buttons_state()
self.update_deck_status()
self.update_user_cards_display()
self.update_stats()
# 检查是否还有牌可抽
if not self.current_cards:
self.check_game_status()
def draw_all_cards(self):
"""抽取全部3张牌"""
if not self.game_active or not self.current_cards:
return
# 抽取所有剩余牌
while self.current_cards:
drawn_card = self.current_cards.pop(0)
self.user_drawn_cards.append(drawn_card)
# 更新显示
self.update_card_display()
self.update_buttons_state()
self.update_deck_status()
self.update_user_cards_display()
self.update_stats()
# 检查游戏状态
self.check_game_status()
def refresh_and_redraw(self):
"""刷新牌堆并重新抽取"""
if not self.game_active:
messagebox.showinfo("游戏结束", "游戏已结束,请点击重置游戏重新开始!")
return
# 将当前剩余的牌放回牌堆
for card in self.current_cards:
self.deck.append(card)
# 洗牌
self.shuffle_deck()
# 重新抽取3张牌
self.current_cards = self.draw_three_cards()
# 更新显示
self.update_card_display()
self.update_buttons_state()
self.update_deck_status()
self.update_stats()
# 检查游戏状态
self.check_game_status()
def reset_game(self):
"""重置游戏"""
# 重置所有状态
self.reset_deck()
self.shuffle_deck()
self.current_cards = []
self.user_drawn_cards = []
self.game_active = True
# 初始抽取
self.draw_initial_cards()
# 更新显示
self.update_deck_status()
self.update_user_cards_display()
self.update_stats()
def update_deck_status(self):
"""更新牌堆状态显示"""
self.deck_status_label.config(text=self.get_deck_status_text())
def update_user_cards_display(self):
"""更新用户抽取的牌显示"""
self.user_cards_text.config(state=tk.NORMAL)
self.user_cards_text.delete(1.0, tk.END)
if not self.user_drawn_cards:
self.user_cards_text.insert(tk.END, "尚未抽取任何牌")
else:
card_counter = Counter(self.user_drawn_cards)
for card_type in sorted(card_counter.keys()):
count = card_counter[card_type]
self.user_cards_text.insert(tk.END, f"牌{card_type}: {count}张\n")
self.user_cards_text.config(state=tk.DISABLED)
def update_stats(self):
"""更新统计信息"""
self.stats_label.config(text=self.get_stats_text())
def check_game_status(self):
"""检查游戏状态"""
if len(self.deck) < 3 and not self.current_cards:
messagebox.showinfo("游戏结束", "牌堆中牌数不足3张,游戏结束!")
self.game_active = False
self.update_buttons_state()
def main():
root = tk.Tk()
app = CardGame(root, N=10)
root.mainloop()
if __name__ == "__main__":
main()