import tkinter as tk
from tkinter import messagebox, Frame, Label, Button
import random
import time
class MemoryGame:
def __init__(self, root, rows=4, cols=4):
self.root = root
self.rows = rows
self.cols = cols
self.total_pairs = (rows * cols) // 2
self.matched_pairs = 0
self.moves = 0
# 创建游戏标题
self.root.title(f"记忆翻牌游戏 ({rows}x{cols})")
# 创建状态栏
self.status_frame = Frame(root)
self.status_frame.grid(row=self.rows+1, column=0, columnspan=self.cols, sticky='ew')
self.moves_var = tk.StringVar()
self.moves_var.set("步数: 0")
moves_label = Label(self.status_frame, textvariable=self.moves_var, font=('Arial', 10))
moves_label.pack(side='left', padx=10)
self.status_var = tk.StringVar()
self.status_var.set("匹配对: 0/{}".format(self.total_pairs))
status_label = Label(self.status_frame, textvariable=self.status_var, font=('Arial', 10))
status_label.pack(side='left', padx=10)
# 创建卡片内容 - 使用Unicode图案
# 常用Unicode符号: ✂️ ✉️ ✏️ ✨ ❤️ ⭐ ☀️ ☁️ ☎️ ☑️ ☔ ☕ ☘️ ☠️ ☢️ ☣️ ☯️ ☸️ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓
symbols = [
'\u2702', '\u2709', '\u270F', '\u2728', # ✂️ ✉️ ✏️ ✨
'\u2764', '\u2B90', '\u2200', '\u2601', # ❤️ ⭐ ☀️ ☁️
'\u2705', '\u2611', '\u2114', '\u2615', # ☎️ ☑️ ☔ ☕
'\u2618', '\u2620', '\u2622', '\u2623', # ☘️ ☠️ ☢️ ☣️
'\u262F', '\u2638', '\u2608', '\u2649', # ☯️ ☸️ ♈ ♉
'\u264A', '\u264B', '\u264C', '\u264D', # ♊ ♋ ♌ ♍
'\u264E', '\u264F', '\u2650', '\u2651', # ♎ ♏ ♐ ♑
'\u2652', '\u2653', '\u2693', '\u26A1' # ♒ ♓ ⚡ ⚓
]
# 根据难度选择符号数量
selected_symbols = random.sample(symbols, self.total_pairs) * 2
random.shuffle(selected_symbols)
# 创建按钮网格
self.buttons = {}
self.symbols = {}
for r in range(rows):
for c in range(cols):
idx = r * cols + c
btn = Button(
root,
text=' ',
width=4,
height=1
,
font=('Arial', 20, 'bold'), # 增大字体以适应Unicode符号
bg='#f0f0f0', # 背景色
fg='#333333', # 前景色
command=lambda x=r, y=c: self.show_card(x, y)
)
btn.grid(row=r, column=c, padx=3, pady=3)
self.buttons[(r, c)] = btn
self.symbols[(r, c)] = selected_symbols[idx]
# 添加重新开始按钮
restart_btn = Button(
root,
text="重新开始",
command=self.restart_game,
font=('Arial', 15),
bg='#e0e0e0',
padx=65
)
restart_btn.grid(row=self.rows+2, column=0, columnspan=self.cols, pady=20)
# 游戏状态变量
self.first_card = None
self.is_waiting = False
# 显示所有卡片2秒后翻面(记忆时间)
self.show_all_cards()
self.root.after(2000, self.hide_all_cards)
def show_all_cards(self):
"""显示所有卡片(记忆阶段)"""
for pos, btn in self.buttons.items():
btn['text'] = self.symbols[pos]
btn['state'] = tk.DISABLED # 禁用点击
def hide_all_cards(self):
"""隐藏所有卡片(开始游戏)"""
for btn in self.buttons.values():
btn['text'] = ' '
btn['state'] = tk.NORMAL # 启用点击
def show_card(self, x, y):
"""处理卡片点击事件"""
# 如果正在等待或卡片已匹配,则忽略点击
if self.is_waiting or self.buttons[(x, y)]['state'] == tk.DISABLED:
return
# 显示卡片内容
self.buttons[(x, y)]['text'] = self.symbols[(x, y)]
self.moves += 1
self.moves_var.set(f"步数: {self.moves}")
if self.first_card is None:
# 第一次点击
self.first_card = (x, y)
else:
# 第二次点击
self.is_waiting = True
self.root.after(500, lambda: self.check_match(x, y))
def check_match(self, x, y):
"""检查两张卡片是否匹配"""
x1, y1 = self.first_card
symbol1 = self.symbols[(x1, y1)]
symbol2 = self.symbols[(x, y)]
if symbol1 == symbol2:
# 匹配成功
self.buttons[self.first_card]['state'] = tk.DISABLED
self.buttons[(x, y)]['state'] = tk.DISABLED
# 设置匹配成功的卡片颜色
self.buttons[self.first_card]['bg'] = '#d0f0d0'
self.buttons[(x, y)]['bg'] = '#d0f0d0'
self.matched_pairs += 1
self.status_var.set("匹配对: {}/{}".format(self.matched_pairs, self.total_pairs))
# 检查游戏胜利
if self.matched_pairs == self.total_pairs:
messagebox.showinfo("恭喜", f"你赢了!\n总步数: {self.moves}")
else:
# 不匹配,翻回卡片
self.buttons[self.first_card]['text'] = ' '
self.buttons[(x, y)]['text'] = ' '
# 短暂高亮不匹配的卡片
self.buttons[self.first_card]['bg'] = '#f0d0d0'
self.buttons[(x, y)]['bg'] = '#f0d0d0'
self.root.after(300, lambda: self.reset_card_colors(x1, y1, x, y))
# 重置状态
self.first_card = None
self.is_waiting = False
def reset_card_colors(self, x1, y1, x, y):
"""重置卡片背景色"""
self.buttons[(x1, y1)]['bg'] = '#f0f0f0'
self.buttons[(x, y)]['bg'] = '#f0f0f0'
def restart_game(self):
"""重新开始游戏"""
# 重置游戏状态
self.first_card = None
self.is_waiting = False
self.matched_pairs = 0
self.moves = 0
self.status_var.set("匹配对: 0/{}".format(self.total_pairs))
self.moves_var.set("步数: 0")
# 重新洗牌
all_symbols = [self.symbols[pos] for pos in self.symbols]
random.shuffle(all_symbols)
# 更新按钮和符号
idx = 0
for r in range(self.rows):
for c in range(self.cols):
self.symbols[(r, c)] = all_symbols[idx]
self.buttons[(r, c)]['text'] = ' '
self.buttons[(r, c)]['state'] = tk.NORMAL
self.buttons[(r, c)]['bg'] = '#f0f0f0' # 重置背景色
idx += 1
# 显示所有卡片2秒后翻面
self.show_all_cards()
self.root.after(2000, self.hide_all_cards)
# 创建主窗口
root = tk.Tk()
root.geometry("680x600") # 设置初始窗口大小
# 创建难度选择界面
def start_game(rows, cols):
# 销毁选择界面
select_frame.destroy()
# 创建游戏
game = MemoryGame(root, rows, cols)
root.mainloop()
select_frame = Frame(root, padx=20, pady=20)
select_frame.pack(expand=True)
Label(select_frame, text="记忆翻牌游戏", font=('Arial', 18, 'bold')).pack(pady=10)
Label(select_frame, text="选择游戏难度", font=('Arial', 14)).pack(pady=10)
difficulties = [
("开始游戏", 6, 4),
]
button_frame = Frame(select_frame)
button_frame.pack(pady=10)
for text, rows, cols in difficulties:
btn = Button(
button_frame,
text=text,
width=15,
height=2,
font=('Arial', 12),
bg='#e0f0ff',
command=lambda r=rows, c=cols: start_game(r, c)
)
btn.pack(pady=5)
# 添加游戏说明
instructions = Label(
select_frame,
text="游戏规则:\n1. 游戏开始时会显示所有卡片2秒\n2. 点击两张卡片,如果图案相同则匹配成功\n3. 匹配所有卡片对即可获胜",
font=('Arial', 10),
justify='left'
)
instructions.pack(pady=10)
root.title("记忆翻牌游戏")
root.mainloop()
让纸牌变成圆角按钮,代码:button.grid(column=x,row=y)