# GESP等级：四级 | GESP Python 四级考点
"""
================================================================================
 综合项目 ★★★ — 迷你画图程序（turtle版）
================================================================================

  项目概述：
    使用 Python turtle 模块 + set + dict 构建一个迷你画图程序。
    用户可以通过键盘快捷键切换画笔颜色、调整粗细、记录轨迹等。

  set + dict 在本项目中的角色：
    ┌───────────────────────────────────────────────────────┐
    │  COLOR_PALETTE  (dict)   →  颜色名 → RGB 三元组      │
    │  KEY_MAP        (dict)   →  快捷键 → 操作函数        │
    │  pen_history    (set)    →  记录使用过的颜色          │
    │  drawn_points   (set)    →  已绘制的像素位置          │
    │  pen_config     (dict)   →  当前画笔配置              │
    └───────────────────────────────────────────────────────┘

  运行要求：
    - Python 标准库 turtle（无需安装）
    - 直接运行本文件即可进入交互画图模式

  操作说明：
    ┌────────────┬────────────────────────────────────────┐
    │  按键       │  功能                                  │
    ├────────────┼────────────────────────────────────────┤
    │  方向键     │  移动画笔                               │
    │  1~7        │  切换颜色（1=红 2=绿 3=蓝 4=黄 5=紫   │
    │             │         6=青 7=橙）                    │
    │  + / -      │  增加/减小画笔粗细                     │
    │  c          │  清空画布                               │
    │  s          │  显示统计信息                           │
    │  q / Esc    │  退出                                  │
    │  鼠标点击   │  点击位置画点（需先按 p 启用点模式）     │
    └────────────┴────────────────────────────────────────┘
================================================================================
"""
import turtle
import sys

# ========== 1. dict — 颜色调色板 ==========
COLOR_PALETTE = {
    "1": ("红色", "red"),
    "2": ("绿色", "green"),
    "3": ("蓝色", "blue"),
    "4": ("黄色", "yellow"),
    "5": ("紫色", "purple"),
    "6": ("青色", "cyan"),
    "7": ("橙色", "orange"),
}

# ========== 2. dict — 当前画笔配置 ==========
pen_config = {
    "color": "red",
    "width": 3,
    "speed": 8,
    "is_down": True,   # 画笔是否落下
    "dot_mode": False, # 点击模式
}

# ========== 3. set — 记录历史 ==========
used_colors: set = set()          # 使用过的颜色
drawn_points: set = set()        # 绘制过的坐标（近似）

# ========== 画布设置 ==========
screen = turtle.Screen()
screen.title("迷你画图程序 — set + dict 综合项目")
screen.bgcolor("white")
screen.setup(width=800, height=600)

pen = turtle.Turtle()
pen.shape("turtle")
pen.speed(pen_config["speed"])
pen.color(pen_config["color"])
pen.pensize(pen_config["width"])


# ========== 核心函数 ==========

def set_color(key: str):
    """切换画笔颜色（通过按键 1~7）"""
    info = COLOR_PALETTE.get(key)
    if info:
        name_en = info[1]
        pen.color(name_en)
        pen_config["color"] = name_en
        used_colors.add(info[0])  # set 记录使用过的颜色名
        screen.title(f"当前颜色：{info[0]}（{name_en}） | 粗细：{pen_config['width']}")
        print(f"  切换颜色 → {info[0]}（{name_en}）")


def change_width(delta: int):
    """调整画笔粗细"""
    new_width = max(1, min(20, pen_config["width"] + delta))
    pen_config["width"] = new_width
    pen.pensize(new_width)
    screen.title(f"当前颜色：{pen_config['color']} | 粗细：{new_width}")


def pen_up():
    """抬笔"""
    pen.penup()
    pen_config["is_down"] = False


def pen_down():
    """落笔"""
    pen.pendown()
    pen_config["is_down"] = True


def toggle_pen():
    """切换抬笔/落笔"""
    if pen_config["is_down"]:
        pen_up()
        print("  抬笔")
    else:
        pen_down()
        print("  落笔")


def clear_canvas():
    """清空画布"""
    pen.clear()
    drawn_points.clear()
    print("  画布已清空")


def show_stats():
    """显示绘制统计信息"""
    # 从画笔位置收集数据
    pos = pen.position()
    x, y = int(pos[0]), int(pos[1])
    drawn_points.add((x, y))

    # 统计调色板中哪些颜色被用过
    unused = {v[0] for v in COLOR_PALETTE.values()} - used_colors

    print("\n" + "=" * 40)
    print("  画图统计")
    print("=" * 40)
    print(f"  当前颜色  ：{pen_config['color']}")
    print(f"  画笔粗细  ：{pen_config['width']}")
    print(f"  当前位置  ：({x}, {y})")
    print(f"  已用颜色  ：{len(used_colors)} 种 → {used_colors}")
    print(f"  未用颜色  ：{unused if unused else '全部使用过！'}")
    print(f"  记录点位数：{len(drawn_points)}")
    print("=" * 40)


def record_position():
    """记录当前位置"""
    pos = pen.position()
    drawn_points.add((int(pos[0]), int(pos[1])))


# ========== 移动函数（自动记录轨迹） ==========

def move_up():
    pen.setheading(90)
    pen.forward(10)
    record_position()


def move_down():
    pen.setheading(270)
    pen.forward(10)
    record_position()


def move_left():
    pen.setheading(180)
    pen.forward(10)
    record_position()


def move_right():
    pen.setheading(0)
    pen.forward(10)
    record_position()


def click_handler(x, y):
    """鼠标点击事件"""
    if pen_config["dot_mode"]:
        pen.penup()
        pen.goto(x, y)
        pen.pendown()
        pen.dot(pen_config["width"] * 2)
        drawn_points.add((int(x), int(y)))
        print(f"  在 ({int(x)}, {int(y)}) 画点")


def toggle_dot_mode():
    """切换点击画点模式"""
    pen_config["dot_mode"] = not pen_config["dot_mode"]
    if pen_config["dot_mode"]:
        screen.onclick(click_handler)
        print("  点击模式：开启（点击画布画点）")
    else:
        screen.onclick(None)
        print("  点击模式：关闭")


def quit_program():
    """退出程序"""
    print("\n  退出画图程序，再见！")
    print(f"  本次共使用 {len(used_colors)} 种颜色，绘制 {len(drawn_points)} 个点位")
    screen.bye()
    sys.exit(0)


# ========== 键盘绑定 ==========
# 颜色切换 1~7
for key in COLOR_PALETTE:
    screen.onkey(lambda k=key: set_color(k), key)

# 方向键
screen.onkey(move_up, "Up")
screen.onkey(move_down, "Down")
screen.onkey(move_left, "Left")
screen.onkey(move_right, "Right")

# 功能键
screen.onkey(lambda: change_width(1), "plus")     # + 号键
screen.onkey(lambda: change_width(-1), "minus")   # - 号键
screen.onkey(toggle_pen, "space")                 # 空格切换抬/落笔
screen.onkey(clear_canvas, "c")
screen.onkey(show_stats, "s")
screen.onkey(toggle_dot_mode, "p")               # p 切换点击模式
screen.onkey(quit_program, "q")
screen.onkey(quit_program, "Escape")

# ========== 显示操作提示 ==========
print("=" * 60)
print("  迷你画图程序 ★★★ — set + dict 综合项目")
print("=" * 60)
print()
print("  操作指南：")
print("  ┌────────────┬─────────────────────────────────┐")
print("  │  方向键     │  移动画笔                       │")
print("  │  1~7 数字键 │  切换颜色（1=红 2=绿 3=蓝     │")
print("  │             │  4=黄 5=紫 6=青 7=橙）         │")
print("  │  + / -      │  增加/减小画笔粗细             │")
print("  │  Space      │  抬笔/落笔切换                 │")
print("  │  c          │  清空画布                       │")
print("  │  p          │  点击画点模式开关               │")
print("  │  s          │  显示统计信息                   │")
print("  │  q / Esc    │  退出                           │")
print("  └────────────┴─────────────────────────────────┘")
print()
print("  提示：程序启动后，点击 turtle 窗口并按键操作。")
print()

# ========== 启动事件循环 ==========
screen.listen()
turtle.done()

# ========== 项目结构总结 ==========
# 本文件的 set + dict 使用分析：
#
#  dict —— COLOR_PALETTE:     按键 → (中文名, 颜色名) 映射
#  dict —— pen_config:        集中管理所有画笔状态
#  set  —— used_colors:       自动去重记录用过哪些颜色
#  set  —— drawn_points:      记录绘制过的位置，可做覆盖率分析
#  dict —— screen.onkey:      每个按键绑定一个函数（虽然 turtle 内部处理）
#
# 这个项目展示了 dict 做配置/映射 + set 做去重记录
# 两种数据结构搭配使用的经典模式。
