import tkinter as tk
from tkinter import messagebox
import random
import time

class SpiderSolitaire:
    def __init__(self, root):
        self.root = root
        self.root.title("🕷️ 蜘蛛纸牌 Spider Solitaire")
        self.root.geometry("1000x700")
        self.root.configure(bg="#006633")
        self.root.resizable(True, True)
        
        # 游戏设置
        self.suits = ['♠', '♥', '♦', '♣']
        self.colors = {'♠': 'black', '♥': 'red', '♦': 'red', '♣': 'black'}
        self.ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
        self.rank_values = {rank: i for i, rank in enumerate(self.ranks)}
        
        # 游戏状态
        self.deck = []
        self.columns = [[] for _ in range(10)]  # 10列
        self.foundations = [[] for _ in range(8)]  # 8组完整牌
        self.score = 500
        self.moves = 0
        self.selected_cards = []  # 选中的牌
        self.selected_column = -1
        self.selected_card_index = -1
        
        # 设置界面
        self.setup_ui()
        
        # 开始新游戏
        self.new_game()
        
    def setup_ui(self):
        """创建界面"""
        # 顶部菜单栏
        menu_frame = tk.Frame(self.root, bg="#004d26")
        menu_frame.pack(fill=tk.X, padx=5, pady=5)
        
        tk.Button(
            menu_frame,
            text="🔄 新游戏",
            font=("Arial", 12, "bold"),
            bg="#4caf50",
            fg="white",
            padx=15,
            pady=5,
            cursor="hand2",
            command=self.new_game
        ).pack(side=tk.LEFT, padx=5)
        
        tk.Button(
            menu_frame,
            text="↩️ 撤销",
            font=("Arial", 12, "bold"),
            bg="#ff9800",
            fg="white",
            padx=15,
            pady=5,
            cursor="hand2",
            command=self.undo_move
        ).pack(side=tk.LEFT, padx=5)
        
        tk.Button(
            menu_frame,
            text="🃏 发牌",
            font=("Arial", 12, "bold"),
            bg="#2196f3",
            fg="white",
            padx=15,
            pady=5,
            cursor="hand2",
            command=self.deal_cards
        ).pack(side=tk.LEFT, padx=5)
        
        # 分数和步数显示
        self.score_label = tk.Label(
            menu_frame,
            text="🏆 分数: 500",
            font=("Arial", 14, "bold"),
            fg="#ffd700",
            bg="#004d26"
        )
        self.score_label.pack(side=tk.RIGHT, padx=20)
        
        self.moves_label = tk.Label(
            menu_frame,
            text="📊 步数: 0",
            font=("Arial", 14, "bold"),
            fg="#ffffff",
            bg="#004d26"
        )
        self.moves_label.pack(side=tk.RIGHT, padx=20)
        
        # 主画布（牌桌）
        self.canvas = tk.Canvas(
            self.root,
            bg="#006633",
            highlightthickness=0
        )
        self.canvas.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 绑定事件
        self.canvas.bind("<Button-1>", self.on_click)
        self.canvas.bind("<B1-Motion>", self.on_drag)
        self.canvas.bind("<ButtonRelease-1>", self.on_release)
        
        # 重置大小变化
        self.root.bind("<Configure>", self.on_resize)
        
        # 计算列宽
        self.card_width = 70
        self.card_height = 95
        self.spacing = 20
        self.offset = 20
        
    def new_game(self):
        """开始新游戏"""
        self.columns = [[] for _ in range(10)]
        self.foundations = [[] for _ in range(8)]
        self.score = 500
        self.moves = 0
        self.selected_cards = []
        self.selected_column = -1
        self.selected_card_index = -1
        
        # 创建牌组（2副牌，共104张）
        self.deck = []
        for _ in range(2):
            for suit in self.suits:
                for rank in self.ranks:
                    self.deck.append((rank, suit))
        
        random.shuffle(self.deck)
        
        # 发牌：前4列6张，后6列5张
        card_index = 0
        for col in range(10):
            num_cards = 6 if col < 4 else 5
            for i in range(num_cards):
                rank, suit = self.deck[card_index]
                # 最后一张牌翻开
                face_up = (i == num_cards - 1)
                self.columns[col].append((rank, suit, face_up))
                card_index += 1
        
        # 剩余牌放入备用牌堆
        self.remaining_deck = self.deck[card_index:]
        
        self.draw_table()
        self.update_score()
        
        # 检查是否已完成
        self.check_win()
        
    def draw_table(self):
        """绘制整个牌桌"""
        self.canvas.delete("all")
        
        # 计算布局
        width = self.canvas.winfo_width()
        height = self.canvas.winfo_height()
        
        if width < 100:
            width = 1000
        if height < 100:
            height = 700
        
        # 计算列宽
        total_margin = 60
        self.card_width = (width - total_margin) // 10 - 10
        self.card_width = min(max(self.card_width, 50), 90)
        self.card_height = int(self.card_width * 1.35)
        self.spacing = self.card_width // 4 + 10
        self.offset = 25
        
        # 顶部显示剩余牌数
        remaining_text = f"剩余牌: {len(self.remaining_deck)}"
        self.canvas.create_text(
            80, 30,
            text=remaining_text,
            fill="#ffd700",
            font=("Arial", 14, "bold"),
            anchor="w"
        )
        
        # 绘制8个完成区
        for i in range(8):
            x = 150 + i * 80
            y = 10
            self.canvas.create_rectangle(
                x, y, x + self.card_width, y + self.card_height,
                outline="#004d26",
                width=2,
                fill="#004d26"
            )
            if self.foundations[i]:
                rank, suit = self.foundations[i][-1]
                self.draw_card(x, y, rank, suit, True)
            else:
                self.canvas.create_text(
                    x + self.card_width//2, y + self.card_height//2,
                    text="🕷️",
                    fill="#004d26",
                    font=("Arial", 20)
                )
        
        # 绘制10列
        start_x = 30
        for col_idx in range(10):
            x = start_x + col_idx * (self.card_width + self.spacing)
            y = 80
            
            cards = self.columns[col_idx]
            for i, (rank, suit, face_up) in enumerate(cards):
                # 计算每张牌的偏移（重叠）
                if i == len(cards) - 1:
                    y_offset = 0
                elif face_up:
                    y_offset = self.offset
                else:
                    y_offset = 10
                
                card_y = y + i * y_offset if face_up else y + i * 10
                
                # 绘制牌
                if face_up:
                    self.draw_card(x, card_y, rank, suit, True)
                else:
                    self.draw_card_back(x, card_y)
            
            # 显示列号
            self.canvas.create_text(
                x + self.card_width//2,
                y + len(cards) * 20 + 20,
                text=f"↓{col_idx+1}↓",
                fill="#004d26",
                font=("Arial", 10)
            )
    
    def draw_card(self, x, y, rank, suit, face_up=True):
        """绘制一张牌"""
        if not face_up:
            self.draw_card_back(x, y)
            return
        
        # 牌面背景
        color = self.colors[suit]
        self.canvas.create_rectangle(
            x, y, x + self.card_width, y + self.card_height,
            fill="white",
            outline="#333",
            width=2,
            tags="card"
        )
        
        # 牌面文字
        text = f"{rank}{suit}"
        font_size = int(self.card_width * 0.3)
        self.canvas.create_text(
            x + 8, y + 8,
            text=text,
            fill=color,
            font=("Arial", font_size, "bold"),
            anchor="nw",
            tags="card"
        )
        
        # 大花色在中间
        if self.card_width > 60:
            self.canvas.create_text(
                x + self.card_width//2,
                y + self.card_height//2,
                text=suit,
                fill=color,
                font=("Arial", int(self.card_width * 0.5)),
                tags="card"
            )
    
    def draw_card_back(self, x, y):
        """绘制牌背"""
        # 牌背图案
        self.canvas.create_rectangle(
            x, y, x + self.card_width, y + self.card_height,
            fill="#1a4a8a",
            outline="#0d2b5c",
            width=3,
            tags="card"
        )
        
        # 装饰纹理
        margin = 8
        self.canvas.create_rectangle(
            x + margin, y + margin,
            x + self.card_width - margin,
            y + self.card_height - margin,
            outline="#2a6aaf",
            width=2,
            tags="card"
        )
        
        # 蜘蛛网装饰
        center_x = x + self.card_width // 2
        center_y = y + self.card_height // 2
        size = min(self.card_width, self.card_height) // 3
        
        for i in range(8):
            angle = i * 45
            end_x = center_x + size * 0.9 * (1 if i % 2 == 0 else 0.6)
            end_y = center_y + size * 0.9 * (1 if i % 2 == 0 else 0.6)
            self.canvas.create_line(
                center_x, center_y,
                end_x, end_y,
                fill="#3a7abf",
                width=1,
                tags="card"
            )
        
        # 蜘蛛图标
        self.canvas.create_text(
            center_x, center_y,
            text="🕷️",
            font=("Arial", int(size * 0.6)),
            tags="card"
        )
    
    def on_click(self, event):
        """鼠标点击事件"""
        # 检查点击位置在哪个列
        col, card_idx = self.get_card_at_position(event.x, event.y)
        
        if col is None:
            return
        
        # 如果点击的是已选中的牌，取消选择
        if self.selected_column == col and self.selected_card_index <= card_idx:
            self.selected_cards = []
            self.selected_column = -1
            self.selected_card_index = -1
            self.draw_table()
            return
        
        # 获取点击的牌
        cards = self.columns[col]
        if card_idx >= len(cards):
            return
        
        rank, suit, face_up = cards[card_idx]
        
        # 只有面朝上的牌才能选中
        if not face_up:
            return
        
        # 检查是否从选中位置开始都是连续的相同花色
        if self.is_valid_sequence(col, card_idx):
            self.selected_column = col
            self.selected_card_index = card_idx
            self.selected_cards = cards[card_idx:]
            
            # 高亮选中的牌
            self.highlight_cards(col, card_idx)
    
    def on_drag(self, event):
        """拖拽事件"""
        if self.selected_column == -1:
            return
        
        # 绘制拖拽效果
        self.draw_table()
        
        # 显示拖拽的牌跟随鼠标
        x = event.x - self.card_width // 2
        y = event.y - 20
        
        for i, (rank, suit, _) in enumerate(self.selected_cards):
            self.draw_card(x, y + i * self.offset, rank, suit, True)
        
        # 显示放置提示
        target_col = self.get_column_at_position(event.x, event.y)
        if target_col is not None and target_col != self.selected_column:
            self.canvas.create_text(
                event.x + self.card_width//2,
                y + len(self.selected_cards) * self.offset + 30,
                text="📥 放置",
                fill="#4caf50",
                font=("Arial", 14, "bold")
            )
    
    def on_release(self, event):
        """鼠标释放事件"""
        if self.selected_column == -1:
            return
        
        # 获取目标列
        target_col = self.get_column_at_position(event.x, event.y)
        
        if target_col is not None:
            # 尝试放置牌
            self.move_cards(self.selected_column, target_col)
        
        # 取消选择
        self.selected_cards = []
        self.selected_column = -1
        self.selected_card_index = -1
        self.draw_table()
        self.update_score()
    
    def get_card_at_position(self, x, y):
        """获取点击位置的列和牌索引"""
        start_x = 30
        for col_idx in range(10):
            col_x = start_x + col_idx * (self.card_width + self.spacing)
            col_y = 80
            
            if col_x <= x <= col_x + self.card_width:
                cards = self.columns[col_idx]
                # 计算点击的是哪张牌
                for i in range(len(cards) - 1, -1, -1):
                    _, _, face_up = cards[i]
                    if face_up:
                        card_y = col_y + i * self.offset
                    else:
                        card_y = col_y + i * 10
                    
                    if card_y <= y <= card_y + self.card_height:
                        return col_idx, i
                
                # 如果没有点击到具体的牌，但点击在列范围内
                if cards:
                    return col_idx, len(cards) - 1
        
        return None, None
    
    def get_column_at_position(self, x, y):
        """获取鼠标位置所在的列"""
        start_x = 30
        for col_idx in range(10):
            col_x = start_x + col_idx * (self.card_width + self.spacing)
            if col_x - 10 <= x <= col_x + self.card_width + 10:
                return col_idx
        return None
    
    def is_valid_sequence(self, col, start_idx):
        """检查从start_idx开始是否是有效的连续序列（同花色递减）"""
        cards = self.columns[col]
        if start_idx >= len(cards):
            return False
        
        # 检查序列是否都面朝上
        for i in range(start_idx, len(cards)):
            if not cards[i][2]:
                return False
        
        # 检查是否连续递减且同花色
        for i in range(start_idx, len(cards) - 1):
            rank1 = cards[i][0]
            rank2 = cards[i+1][0]
            suit1 = cards[i][1]
            suit2 = cards[i+1][1]
            
            if suit1 != suit2:
                return False
            
            if self.rank_values[rank1] != self.rank_values[rank2] + 1:
                return False
        
        return True
    
    def move_cards(self, from_col, to_col):
        """移动牌"""
        if from_col == to_col:
            return
        
        from_cards = self.columns[from_col]
        to_cards = self.columns[to_col]
        
        # 检查目标列是否为空，或者目标列最上面一张牌比要移动的牌大1
        if to_cards:
            top_rank, top_suit, _ = to_cards[-1]
            move_rank, move_suit, _ = from_cards[self.selected_card_index]
            
            # 检查是否可放置（递减1，花色任意）
            if self.rank_values[top_rank] != self.rank_values[move_rank] + 1:
                return
        # 如果目标列为空，可以放置任意牌
        
        # 执行移动
        cards_to_move = from_cards[self.selected_card_index:]
        del from_cards[self.selected_card_index:]
        to_cards.extend(cards_to_move)
        
        # 翻开原来列的顶部牌
        if from_cards and not from_cards[-1][2]:
            rank, suit, _ = from_cards[-1]
            from_cards[-1] = (rank, suit, True)
        
        self.moves += 1
        
        # 检查是否完成了一组完整序列（A到K同花色）
        self.check_complete_sequence(to_col)
        
        # 更新显示
        self.draw_table()
        self.update_score()
        self.check_win()
    
    def check_complete_sequence(self, col):
        """检查是否完成了一组完整的序列（A到K）"""
        cards = self.columns[col]
        if len(cards) < 13:
            return
        
        # 检查最后13张是否完整
        start_idx = len(cards) - 13
        if start_idx < 0:
            return
        
        # 检查是否同花色且从K到A
        suit = cards[start_idx][1]
        for i in range(13):
            rank = cards[start_idx + i][0]
            if not cards[start_idx + i][2]:
                return
            if cards[start_idx + i][1] != suit:
                return
            if self.rank_values[rank] != 12 - i:  # K=12, Q=11, ..., A=0
                return
        
        # 完成一组！移除这些牌并加到foundation
        completed = cards[start_idx:]
        del cards[start_idx:]
        self.foundations[0].append(completed[0])  # 简化存储
        
        # 翻开新的顶部牌
        if cards and not cards[-1][2]:
            rank, suit, _ = cards[-1]
            cards[-1] = (rank, suit, True)
        
        # 加分
        self.score += 100
        self.draw_table()
        self.update_score()
        
        messagebox.showinfo("🎉 完成一组！", 
            f"恭喜完成一组 {suit} 序列！\n+100分！")
    
    def deal_cards(self):
        """发牌（从备用牌堆发到每列）"""
        if not self.remaining_deck:
            messagebox.showinfo("提示", "没有更多的牌了！")
            return
        
        # 检查每列是否都有牌
        for col in self.columns:
            if not col:
                messagebox.showinfo("提示", "所有列都必须有牌才能发牌！")
                return
        
        # 发牌：每列发一张
        cards_dealt = 0
        for col_idx in range(10):
            if self.remaining_deck:
                rank, suit = self.remaining_deck.pop()
                self.columns[col_idx].append((rank, suit, True))
                cards_dealt += 1
        
        self.moves += 1
        self.score -= 10  # 发牌扣分
        
        self.draw_table()
        self.update_score()
    
    def undo_move(self):
        """撤销（简化版）"""
        messagebox.showinfo("提示", "撤销功能开发中...\n目前请重新开始游戏 😅")
    
    def highlight_cards(self, col, start_idx):
        """高亮选中的牌"""
        self.draw_table()
        
        cards = self.columns[col]
        x = 30 + col * (self.card_width + self.spacing)
        y = 80
        
        for i in range(start_idx, len(cards)):
            _, _, face_up = cards[i]
            if face_up:
                y_offset = i * self.offset
            else:
                y_offset = i * 10
            
            card_y = y + y_offset
            
            # 绘制金色边框
            self.canvas.create_rectangle(
                x - 3, card_y - 3,
                x + self.card_width + 3,
                card_y + self.card_height + 3,
                outline="#ffd700",
                width=3,
                tags="highlight"
            )
    
    def update_score(self):
        """更新分数显示"""
        self.score_label.config(text=f"🏆 分数: {self.score}")
        self.moves_label.config(text=f"📊 步数: {self.moves}")
    
    def on_resize(self, event):
        """窗口大小变化时重绘"""
        if event.widget == self.root:
            self.draw_table()
    
    def check_win(self):
        """检查是否获胜"""
        # 检查所有牌是否都在foundations中
        total_cards = 0
        for col in self.columns:
            total_cards += len(col)
        
        if total_cards == 0 and not self.remaining_deck:
            messagebox.showinfo(
                "🎉 恭喜获胜！",
                f"你成功完成了蜘蛛纸牌！\n"
                f"步数: {self.moves}\n"
                f"分数: {self.score}\n"
                f"太棒了！ 🕷️"
            )
            return True
        return False

if __name__ == "__main__":
    root = tk.Tk()
    app = SpiderSolitaire(root)
    root.mainloop()