# GESP等级：三级 | GESP Python 三级考点


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
第4节：位运算实战 — Turtle 位运算魔法秀
面向7-10岁少儿编程教学
=========================================
展示位运算的实战应用：
1. 奇偶判断 (n & 1)
2. RGB颜色通道提取 (掩码)
3. 异或交换
4. 2的幂判断
5. 快速乘除
"""

import turtle
import time
import random

# ====================================================================
# 师生互动说明：
#   运行本程序后，首先会询问"请输入一个数字（默认53）："
#   输入后，turtle会画出"位运算魔法秀"——展示这个数字的二进制、
#   以及6大位运算实战技巧的结果。
#   之后会自动播放5个专题演示。
# ====================================================================

# ========== 全局设置 ==========
SCREEN_W = 900
SCREEN_H = 700

# 颜色
COLOR_BG = "#1a1a2e"
COLOR_ODD = "#F39C12"     # 奇数=金色
COLOR_EVEN = "#3498DB"    # 偶数=蓝色
COLOR_POWER2 = "#2ECC71"  # 2的幂=绿色
COLOR_WHITE = "#FFFFFF"
COLOR_GRAY = "#95A5A6"

# ========== 初始化画布 ==========
screen = turtle.Screen()
screen.setup(SCREEN_W, SCREEN_H)
screen.bgcolor(COLOR_BG)
screen.title("位运算实战 — 魔法秀")
screen.tracer(0)

# ========== 创建海龟 ==========
pen = turtle.Turtle()
pen.speed(0)
pen.hideturtle()


def clear_screen():
    """清屏"""
    pen.clear()
    pen.penup()


def draw_title(title, y=300, color="#E74C3C"):
    """画标题"""
    pen.penup()
    pen.goto(0, y)
    pen.color(color)
    pen.write(title, align="center", font=("Arial", 24, "bold"))


def draw_subtitle(text, y=260, color="#BDC3C7"):
    """画副标题"""
    pen.penup()
    pen.goto(0, y)
    pen.color(color)
    pen.write(text, align="center", font=("Arial", 14, "normal"))


def draw_result(text, y=100, color="#F1C40F"):
    """画结果"""
    pen.penup()
    pen.goto(0, y)
    pen.color(color)
    pen.write(text, align="center", font=("Arial", 18, "bold"))


def draw_info(text, y=-280, color="#7F8C8D"):
    """画底部信息"""
    pen.penup()
    pen.goto(0, y)
    pen.color(color)
    pen.write(text, align="center", font=("Arial", 12, "normal"))


def draw_box(x, y, w, h, color, label=""):
    """画一个带标签的矩形"""
    pen.penup()
    pen.goto(x, y)
    pen.pendown()
    pen.fillcolor(color)
    pen.pencolor(COLOR_WHITE)
    pen.pensize(1)
    pen.begin_fill()
    for _ in range(2):
        pen.forward(w)
        pen.right(90)
        pen.forward(h)
        pen.right(90)
    pen.end_fill()
    if label:
        pen.penup()
        pen.goto(x + w // 2, y + h // 2 - 8)
        pen.color(COLOR_WHITE)
        pen.write(label, align="center", font=("Arial", 14, "bold"))


def draw_circle(x, y, r, color, label=""):
    """画一个带标签的圆"""
    pen.penup()
    pen.goto(x, y - r)
    pen.pendown()
    pen.fillcolor(color)
    pen.pencolor(COLOR_WHITE)
    pen.pensize(1)
    pen.begin_fill()
    pen.circle(r)
    pen.end_fill()
    if label:
        pen.penup()
        pen.goto(x, y - 8)
        pen.color(COLOR_WHITE)
        pen.write(label, align="center", font=("Arial", 14, "bold"))


# ====================================================================
# 位运算魔法秀 —— 输入 → 二进制 → 运算 → 结果
# 展示全部6大实战技巧（适合课堂演示）
# ====================================================================

def bit_magic_show_all(num):
    """
    位运算魔法秀——对给定的数字num，展示6大位运算实战技巧。
    布局：
      ┌──────────────────────────────────────┐
      │       🎪 位运算魔法秀 🎪              │
      │  输入: 53  =  110101                  │
      │                                       │
      │  🟡 ① 判断奇偶  53 & 1 = 1 → 奇数    │
      │  🟢 ② 判断相等  (53^53)==0 → 是      │
      │  🟠 ③ 异或交换  53 ↔ 37 → 三步搞定   │
      │  🪷 ④ 取末k位  53 & 7 = 5            │
      │  🟣 ⑤ 快速乘除  53<<2=212 53>>2=13   │
      │  🔴 ⑥ 2的幂判断 53&52≠0 → 不是      │
      └──────────────────────────────────────┘
    """
    pen.clear()
    pen.penup()

    # ---- 标题 ----
    pen.goto(0, 260)
    pen.color("#FFD700")
    pen.write("🎪 位运算魔法秀 🎪", align="center",
              font=("SimHei", 26, "bold"))

    pen.goto(0, 225)
    pen.color("#BDC3C7")
    pen.write(f"对数字 {num} 施展6大位运算魔法",
              align="center", font=("SimHei", 14, "normal"))

    # ---- 二进制展示 ----
    binary_str = bin(num)[2:]
    pen.goto(-350, 170)
    pen.color("#00FFFF")
    pen.write(f"输入: {num}  =  (二进制)  {binary_str}",
              font=("Courier", 18, "bold"))

    # 画二进制小方块（每个位一个小格子）
    box_size = 22
    gap = 3
    total_bits = len(binary_str)
    start_x = 350 - total_bits * (box_size + gap)
    for i, bit in enumerate(binary_str):
        x = start_x + i * (box_size + gap)
        pen.penup()
        pen.goto(x, 140)
        pen.pendown()
        if bit == '1':
            pen.fillcolor("#2ECC71")  # 绿色=1
        else:
            pen.fillcolor("#E74C3C")  # 红色=0
        pen.pencolor("#34495E")
        pen.begin_fill()
        for _ in range(4):
            pen.forward(box_size)
            pen.right(90)
        pen.end_fill()
        # 在位上方标注位权
        bit_pos = total_bits - 1 - i
        pen.penup()
        pen.goto(x + box_size // 2, 165)
        pen.color("#95A5A6")
        pen.write(f"2^{bit_pos}", align="center",
                  font=("Arial", 7, "normal"))

    # ---- 6大绝招展示 ----
    ops = [
        # (标题, 表达式文本, 结果文本, 颜色, y坐标)
        ("① 判断奇偶",
         f"  {num} & 1 = {num & 1}",
         f"→ {'奇数' if num & 1 else '偶数'}",
         "#F39C12", 80),

        ("② 判断相等",
         f"  ({num} ^ {num}) = {num ^ num}",
         "→ 相等 ✔" if (num ^ num) == 0 else "→ 不等 ✘",
         "#2ECC71", 50),

        ("③ 异或交换",
         "  a^=b; b^=a; a^=b  (无需第三变量!)",
         f"  eg: a={num}, b=37 → a={37}, b={num}",
         "#E67E22", 20),

        ("④ 取末k位 (掩码)",
         f"  mask = (1<<3)-1 = 7",
         f"  {num} & 7 = {num & 7}",
         "#9B59B6", -10),

        ("⑤ 快速乘除2的幂",
         f"  <<: {num}<<2 = {num<<2}  (×4)",
         f"  >>: {num}>>2 = {num>>2}  (÷4)",
         "#1ABC9C", -40),

        ("⑥ 判断2的幂",
         f"  {num} & {num-1} = {num & (num-1)}",
         "→ 是2的幂! ✔" if num > 0 and (num & (num-1)) == 0 else "→ 不是2的幂",
         "#E74C3C", -70),
    ]

    for title, expr_text, result_text, color, y in ops:
        pen.penup()
        pen.goto(-370, y)
        pen.color(color)
        pen.write(title, align="left", font=("SimHei", 13, "bold"))

        pen.goto(-240, y)
        pen.color("#ECF0F1")
        pen.write(expr_text, align="left", font=("Courier", 12, "normal"))

        pen.goto(120, y)
        pen.color("#F1C40F")
        pen.write(result_text, align="left", font=("Courier", 12, "bold"))

    # ---- 底部总结 ----
    pen.penup()
    pen.goto(0, -130)
    pen.color("#FFD700")
    pen.write("✨ 位运算 = CPU的母语，快到飞起！ ✨",
              align="center", font=("SimHei", 16, "bold"))

    pen.goto(0, -160)
    pen.color("#7F8C8D")
    pen.write("按画面任意键继续观看专题演示...",
              align="center", font=("SimHei", 12, "normal"))

    screen.update()
    """演示1：奇偶判断"""
    clear_screen()
    draw_title("演示1: 奇偶判断器  n & 1", y=300, color="#E74C3C")
    draw_subtitle("二进制最低位 = 1 是奇数，= 0 是偶数",
                  y=260, color="#BDC3C7")

    test_numbers = [5, 6, 13, 20, 31, 42, 63, 100]

    for i, n in enumerate(test_numbers):
        is_odd = n & 1
        col = i % 4
        row = i // 4
        x = -300 + col * 160
        y = 200 - row * 200

        # 画数字标签
        pen.penup()
        pen.goto(x + 40, y + 70)
        pen.color(COLOR_WHITE)
        pen.write(f"{n} = {bin(n)}",
                  align="center", font=("Courier", 11, "bold"))

        # 画二进制位展示
        bits = [(n >> i) & 1 for i in range(7, -1, -1)]
        box_w = 12
        gap = 2
        start_bit_x = x + (80 - 8 * (box_w + gap)) // 2
        for bi, bv in enumerate(bits):
            bx = start_bit_x + bi * (box_w + gap)
            pen.penup()
            pen.goto(bx, y + 40)
            pen.pendown()
            if bv == 1:
                pen.fillcolor("#2ECC71")
            else:
                pen.fillcolor("#E74C3C")
            pen.pencolor("#34495E")
            pen.begin_fill()
            for _ in range(4):
                pen.forward(box_w)
                pen.right(90)
            pen.end_fill()

        # 强调最低位（用框标记）
        last_bit_x = start_bit_x + 7 * (box_w + gap)
        pen.penup()
        pen.goto(last_bit_x - 2, y + 38)
        pen.pendown()
        pen.pencolor("#F1C40F")
        pen.pensize(2)
        for _ in range(4):
            pen.forward(box_w + 4)
            pen.right(90)
        pen.pensize(1)

        # 显示奇偶结果
        if is_odd:
            draw_circle(x + 40, y - 20, 30, COLOR_ODD, "奇数")
        else:
            draw_box(x + 5, y - 55, 70, 50, COLOR_EVEN, "偶数")

        # 计算方法
        pen.penup()
        pen.goto(x + 40, y - 90)
        pen.color("#F1C40F")
        pen.write(f"{n} & 1 = {is_odd}",
                  align="center", font=("Courier", 11, "normal"))

        screen.update()
        time.sleep(0.3)

    draw_info("规律: 奇数最低位=1, 偶数最低位=0  |  n & 1 秒判奇偶",
              y=-280)
    screen.update()
    time.sleep(2)


def show_color_extraction_demo():
    """演示2：RGB颜色通道提取"""
    clear_screen()
    draw_title("演示2: RGB颜色通道提取 — 掩码操作", y=300, color="#9B59B6")
    draw_subtitle("用 >> 和 & 0xFF 提取 R/G/B 分量", y=260, color="#BDC3C7")

    # 展示几种颜色
    colors = [
        (0xFF0000, "红色"),
        (0x00FF00, "绿色"),
        (0x0000FF, "蓝色"),
        (0xFFFF00, "黄色"),
        (0xFF00FF, "紫色"),
        (0x66CCFF, "天蓝"),
    ]

    for i, (color_val, name) in enumerate(colors):
        col = i % 3
        row = i // 3
        x = -280 + col * 190
        y = 180 - row * 200

        # 提取RGB
        R = (color_val >> 16) & 0xFF
        G = (color_val >> 8) & 0xFF
        B = color_val & 0xFF

        # 颜色方块
        pen.penup()
        pen.goto(x, y)
        pen.pendown()
        hex_str = f"#{color_val:06X}"
        pen.pencolor("#34495E")
        pen.fillcolor(hex_str)
        pen.begin_fill()
        for _ in range(2):
            pen.forward(80)
            pen.right(90)
            pen.forward(60)
            pen.right(90)
        pen.end_fill()

        # 颜色名和十六进制
        pen.penup()
        pen.goto(x + 40, y - 12)
        pen.color(COLOR_WHITE)
        pen.write(name, align="center", font=("Arial", 13, "bold"))
        pen.goto(x + 40, y - 28)
        pen.color("#BDC3C7")
        pen.write(hex_str, align="center", font=("Courier", 10, "normal"))

        # R分量
        r_x = x + 90
        pen.penup()
        pen.goto(r_x, y + 35)
        pen.color("#E74C3C")
        pen.write(f"R >> 16 & 0xFF", align="left",
                  font=("Courier", 9, "normal"))
        pen.goto(r_x, y + 18)
        pen.write(f"  = ({color_val}>>16) & 255", align="left",
                  font=("Courier", 9, "normal"))
        pen.goto(r_x, y)
        pen.color("#F1C40F")
        pen.write(f"  = {R}", align="left",
                  font=("Courier", 11, "bold"))

        # G分量
        pen.goto(r_x, y - 20)
        pen.color("#2ECC71")
        pen.write(f"G >> 8 & 0xFF", align="left",
                  font=("Courier", 9, "normal"))
        pen.goto(r_x, y - 37)
        pen.color("#F1C40F")
        pen.write(f"  = {G}", align="left",
                  font=("Courier", 11, "bold"))

        # B分量
        pen.goto(r_x, y - 57)
        pen.color("#3498DB")
        pen.write(f"B & 0xFF", align="left",
                  font=("Courier", 9, "normal"))
        pen.goto(r_x, y - 74)
        pen.color("#F1C40F")
        pen.write(f"  = {B}", align="left",
                  font=("Courier", 11, "bold"))

        screen.update()
        time.sleep(0.3)

    draw_info("掩码 0xFF = 255 = 11111111, 右移后再与掩码提取指定通道",
              y=-280)
    screen.update()
    time.sleep(2)


def show_swap_demo():
    """演示3：异或交换"""
    clear_screen()
    draw_title("演示3: 异或交换法  a^=b; b^=a; a^=b", y=300, color="#E67E22")
    draw_subtitle("不借助第三个变量，交换两个数的值", y=260, color="#BDC3C7")

    a, b = 5, 3
    steps = [
        ("初始状态", a, b, ""),
        ("第1步: a ^= b", a ^ b, b, "a = a ^ b"),
        ("第2步: b ^= a", a ^ b, b ^ (a ^ b), "b = b ^ a"),
        ("第3步: a ^= b", (a ^ b) ^ (b ^ (a ^ b)), b ^ (a ^ b), "a = a ^ b"),
    ]

    # 实际计算
    a_val, b_val = 5, 3
    a_val ^= b_val  # a = 6
    b_val ^= a_val  # b = 5
    a_val ^= b_val  # a = 3

    # 画初始状态
    box_w = 120
    box_h = 60
    y_a = 180
    y_b = 100
    y_result = -20

    # 画标签
    pen.penup()
    pen.goto(-250, y_a + box_h // 2 + 10)
    pen.color("#E74C3C")
    pen.write("初始:", align="left", font=("Arial", 14, "bold"))

    pen.goto(-250, y_b + box_h // 2 + 10)
    pen.color("#3498DB")
    pen.write("初始:", align="left", font=("Arial", 14, "bold"))

    # 画A的盒子
    pen.penup()
    pen.goto(-100, y_a)
    pen.pendown()
    pen.pencolor("#E74C3C")
    pen.fillcolor("#E74C3C")
    pen.begin_fill()
    for _ in range(2):
        pen.forward(box_w)
        pen.right(90)
        pen.forward(box_h)
        pen.right(90)
    pen.end_fill()
    pen.penup()
    pen.goto(-100 + box_w // 2, y_a + box_h // 2 - 8)
    pen.color(COLOR_WHITE)
    pen.write("A=5", align="center", font=("Arial", 18, "bold"))

    # 二进制
    pen.goto(-100 + box_w // 2, y_a - 25)
    pen.color("#F1C40F")
    pen.write("0101", align="center", font=("Courier", 12, "bold"))

    # 画B的盒子
    pen.penup()
    pen.goto(-100, y_b)
    pen.pendown()
    pen.pencolor("#3498DB")
    pen.fillcolor("#3498DB")
    pen.begin_fill()
    for _ in range(2):
        pen.forward(box_w)
        pen.right(90)
        pen.forward(box_h)
        pen.right(90)
    pen.end_fill()
    pen.penup()
    pen.goto(-100 + box_w // 2, y_b + box_h // 2 - 8)
    pen.color(COLOR_WHITE)
    pen.write("B=3", align="center", font=("Arial", 18, "bold"))

    # 二进制
    pen.goto(-100 + box_w // 2, y_b - 25)
    pen.color("#F1C40F")
    pen.write("0011", align="center", font=("Courier", 12, "bold"))

    # 画右箭头
    pen.penup()
    pen.goto(50, y_a + box_h // 2)
    pen.color("#E67E22")
    pen.write("用异或交换 👉", align="left", font=("Arial", 16, "bold"))

    # 画交换后的结果
    x_result = 200
    pen.penup()
    pen.goto(x_result - 10, y_result + 65)
    pen.color("#2ECC71")
    pen.write("交换后:", align="left", font=("Arial", 14, "bold"))

    # A变成3(蓝色)
    pen.penup()
    pen.goto(x_result, y_result + 35)
    pen.pendown()
    pen.pencolor("#3498DB")
    pen.fillcolor("#3498DB")
    pen.begin_fill()
    for _ in range(2):
        pen.forward(box_w)
        pen.right(90)
        pen.forward(box_h)
        pen.right(90)
    pen.end_fill()
    pen.penup()
    pen.goto(x_result + box_w // 2, y_result + box_h // 2 + 27)
    pen.color(COLOR_WHITE)
    pen.write("A=3", align="center", font=("Arial", 18, "bold"))
    pen.goto(x_result + box_w // 2, y_result + box_h // 2 + 5)
    pen.color("#F1C40F")
    pen.write("0011", align="center", font=("Courier", 12, "bold"))

    # B变成5(红色)
    pen.penup()
    pen.goto(x_result, y_result - 25)
    pen.pendown()
    pen.pencolor("#E74C3C")
    pen.fillcolor("#E74C3C")
    pen.begin_fill()
    for _ in range(2):
        pen.forward(box_w)
        pen.right(90)
        pen.forward(box_h)
        pen.right(90)
    pen.end_fill()
    pen.penup()
    pen.goto(x_result + box_w // 2, y_result + box_h // 2 - 33)
    pen.color(COLOR_WHITE)
    pen.write("B=5", align="center", font=("Arial", 18, "bold"))
    pen.goto(x_result + box_w // 2, y_result + box_h // 2 - 55)
    pen.color("#F1C40F")
    pen.write("0101", align="center", font=("Courier", 12, "bold"))

    # 逐位推演
    pen.penup()
    pen.goto(-250, -160)
    pen.color("#F1C40F")
    pen.write("逐位推演:", align="left", font=("Arial", 14, "bold"))

    steps_text = [
        "第1步: a = a ^ b = 0101 ^ 0011 = 0110 (6)",
        "第2步: b = b ^ a = 0011 ^ 0110 = 0101 (5) ← 原来的a",
        "第3步: a = a ^ b = 0110 ^ 0101 = 0011 (3) ← 原来的b",
    ]
    for idx, text in enumerate(steps_text):
        pen.goto(-230, -190 - idx * 25)
        pen.color("#BDC3C7")
        pen.write(text, align="left", font=("Courier", 11, "normal"))

    draw_info("神奇吗？三步异或，不用第三杯水就交换了两杯水！", y=-280)
    screen.update()
    time.sleep(2)


def show_power_of_two_demo():
    """演示4：2的幂判断"""
    clear_screen()
    draw_title("演示4: 2的幂判断  n & (n-1) == 0", y=300, color="#2ECC71")
    draw_subtitle("2的幂的二进制只有一个1", y=260, color="#BDC3C7")

    test_nums = [1, 2, 3, 4, 5, 8, 16, 31, 32, 63, 64, 100, 128, 255]

    # 画标题列
    headers = ["数字", "二进制", "n-1", "n & (n-1)", "是2的幂?"]
    x_positions = [-380, -280, -120, 40, 200]
    for idx, (hdr, x) in enumerate(zip(headers, x_positions)):
        pen.penup()
        pen.goto(x, 220)
        pen.color("#F1C40F")
        pen.write(hdr, align="left" if idx > 0 else "center",
                  font=("Arial", 12, "bold"))

    for i, n in enumerate(test_nums):
        y = 195 - i * 18
        is_power = n > 0 and (n & (n - 1)) == 0

        # 数字
        pen.penup()
        pen.goto(x_positions[0], y)
        pen.color("#E74C3C" if is_power else COLOR_WHITE)
        pen.write(f"{n:3d}", align="center", font=("Courier", 11, "bold"))

        # 二进制
        pen.goto(x_positions[1], y)
        pen.color("#3498DB")
        pen.write(f"{bin(n):>10s}", align="left",
                  font=("Courier", 10, "normal"))

        # n-1
        pen.goto(x_positions[2], y)
        pen.color("#E67E22")
        if n > 0:
            pen.write(f"{bin(n-1):>10s}", align="left",
                      font=("Courier", 10, "normal"))
        else:
            pen.write("N/A", align="left", font=("Courier", 10, "normal"))

        # n & (n-1)
        pen.goto(x_positions[3], y)
        result = n & (n - 1) if n > 0 else 0
        pen.color("#9B59B6" if result == 0 else "#7F8C8D")
        pen.write(f"0x{result:08X}", align="left",
                  font=("Courier", 11, "bold"))

        # 判断结果
        pen.goto(x_positions[4], y)
        if is_power:
            pen.color("#2ECC71")
            pen.write("✓ 是", align="left", font=("Courier", 11, "bold"))
        else:
            pen.color("#E74C3C")
            pen.write("✗", align="left", font=("Courier", 11, "bold"))

        screen.update()

    draw_info("2的幂的二进制只有一个1: 1, 2, 4, 8, 16, 32, 64, 128, 256...",
              y=-280)
    screen.update()
    time.sleep(2)


def show_speed_compare():
    """演示5：速度对比"""
    clear_screen()
    draw_title("演示5: 位运算速度对比", y=300, color="#F1C40F")
    draw_subtitle("位运算比普通算术运算快很多！", y=260, color="#BDC3C7")

    # 用动画展示速度对比
    import time as _time

    n = 123456789
    iterations = 5000000

    # 测试乘法
    start = _time.time()
    for _ in range(iterations):
        r = n * 8
    mul_time = _time.time() - start

    # 测试左移
    start = _time.time()
    for _ in range(iterations):
        r = n << 3
    shift_time = _time.time() - start

    # 显示结果
    bar_max_width = 400
    y_center = 100

    # 乘法条形
    pen.penup()
    pen.goto(-200, y_center + 30)
    pen.color("#E74C3C")
    pen.write("乘法 n * 8:", align="left", font=("Arial", 16, "bold"))

    mul_width = bar_max_width * min(mul_time / (mul_time + 0.001), 1.0)
    pen.penup()
    pen.goto(-200, y_center - 10)
    pen.pendown()
    pen.fillcolor("#E74C3C")
    pen.begin_fill()
    for _ in range(2):
        pen.forward(mul_width)
        pen.right(90)
        pen.forward(40)
        pen.right(90)
    pen.end_fill()
    pen.penup()
    pen.goto(-200 + mul_width + 10, y_center + 5)
    pen.color("#E74C3C")
    pen.write(f"{mul_time:.3f}秒", align="left",
              font=("Arial", 14, "bold"))

    # 左移条形
    pen.penup()
    pen.goto(-200, y_center - 70)
    pen.color("#2ECC71")
    pen.write("左移 n << 3:", align="left", font=("Arial", 16, "bold"))

    shift_width = bar_max_width * min(shift_time / (mul_time + 0.001), 1.0)
    pen.penup()
    pen.goto(-200, y_center - 110)
    pen.pendown()
    pen.fillcolor("#2ECC71")
    pen.begin_fill()
    for _ in range(2):
        pen.forward(shift_width)
        pen.right(90)
        pen.forward(40)
        pen.right(90)
    pen.end_fill()
    pen.penup()
    pen.goto(-200 + shift_width + 10, y_center - 95)
    pen.color("#2ECC71")
    pen.write(f"{shift_time:.3f}秒", align="left",
              font=("Arial", 14, "bold"))

    # 倍数比较
    speedup = mul_time / shift_time if shift_time > 0 else 0
    pen.penup()
    pen.goto(0, y_center - 170)
    pen.color("#F1C40F")
    pen.write(f"左移比乘法快了约 {speedup:.1f} 倍！",
              align="center", font=("Arial", 18, "bold"))

    pen.goto(0, y_center - 200)
    pen.color("#BDC3C7")
    pen.write(f"测试次数: {iterations:,} 次",
              align="center", font=("Arial", 12, "normal"))

    draw_info("位运算是CPU的'母语'，几乎不花时间！", y=-280)
    screen.update()
    time.sleep(3)


def show_magic_show():
    """综合魔术秀"""
    clear_screen()
    draw_title("🎩 位运算魔法秀 🎩", y=150, color="#F1C40F")
    draw_subtitle("今天学会的实战技巧", y=100, color="#BDC3C7")

    tricks = [
        ("n & 1", "一眼看穿奇偶", "#E74C3C"),
        ("(a^b)==0", "判断两数相等", "#3498DB"),
        ("a^=b; b^=a; a^=b", "三步交换数值", "#E67E22"),
        ("n & (1<<k)-1", "掩码提取末k位", "#9B59B6"),
        ("n << 3", "快速乘8", "#2ECC71"),
        ("n >> 2", "快速除4", "#1ABC9C"),
        ("n & (n-1)==0", "判断2的幂", "#F39C12"),
    ]

    for i, (expr, desc, color) in enumerate(tricks):
        y = 50 - i * 40
        pen.penup()
        pen.goto(-250, y)
        pen.color(color)
        pen.write(f"{expr:>25s}", align="right",
                  font=("Courier", 14, "bold"))
        pen.goto(-220, y)
        pen.color(COLOR_WHITE)
        pen.write(f"→  {desc}", align="left", font=("Arial", 14, "normal"))

    draw_info("位运算 = 计算机的母语，学会它，你就拥有了'超能力'！",
              y=-230, color="#F1C40F")
    pen.penup()
    pen.goto(0, -260)
    pen.color("#7F8C8D")
    pen.write("点击画面退出", align="center", font=("Arial", 12, "normal"))
    screen.update()


# ========== 入口 ==========
if __name__ == "__main__":
    try:
        # 第1步：师生互动 —— 输入数字
        screen.tracer(0)
        num_str = turtle.textinput("🎪 位运算魔法秀 🎪",
            "请输入一个数字，让 turtle 施展6大位运算魔法！\n"
            "（输入后按确定，默认53）")
        if num_str is None or num_str.strip() == "":
            num = 53
        else:
            num = int(num_str.strip())

        # 第2步：展示综合魔法秀
        bit_magic_show_all(num)
        time.sleep(2)

        # 第3步：等待点击后继续专题演示
        screen.exitonclick()
        screen.clear()

        # 第4步：依次展示5个专题演示
        screen.tracer(0)
        show_odd_even_demo()
        show_color_extraction_demo()
        show_swap_demo()
        show_power_of_two_demo()
        show_speed_compare()
        show_magic_show()

        screen.exitonclick()
    except ValueError:
        # 输入不是数字时自动用默认值
        screen.tracer(0)
        pen.penup()
        pen.goto(0, 0)
        pen.color("#E74C3C")
        pen.write("输入有误，使用默认数字 53",
                  align="center", font=("SimHei", 18, "bold"))
        screen.update()
        time.sleep(1)
        screen.tracer(0)
        num = 53
        bit_magic_show_all(num)
        time.sleep(2)
        screen.exitonclick()
        screen.clear()
        screen.tracer(0)
        show_odd_even_demo()
        show_color_extraction_demo()
        show_swap_demo()
        show_power_of_two_demo()
        show_speed_compare()
        show_magic_show()
        screen.exitonclick()
