import turtle
import tkinter as tk
from tkinter import messagebox, scrolledtext
import random
import math
import sys
class AnimationManager:
def __init__(self):
self.screen = None
self.bg_pen = None
self.snow = None
self.horse = None
self.leg_phase = 0
self.horse_pos = -400
self.firework_index = 0
self.firework_positions = [(0, 100), (200, 50), (-100, 80), (300, 100)]
self.current_firework = None
self.is_drawing = False
self.root_gui = None
def init_turtle_screen(self):
"""初始化 turtle 屏幕(主线程)"""
if self.is_drawing:
return
self.is_drawing = True
turtle.TurtleScreen._RUNNING = True
self.screen = turtle.Screen()
self.screen.title("2026 元旦快乐 · 龙马精神")
self.screen.bgcolor("#0a0a2a")
self.screen.setup(width=900, height=600)
self.screen.tracer(0)
self.bg_pen = turtle.Turtle()
self.bg_pen.hideturtle()
self.bg_pen.speed(0)
self.bg_pen.penup()
self.bg_pen.goto(350, 200)
self.bg_pen.color("#FFD700")
self.bg_pen.write("2026", font=("微软雅黑", 40, "bold"))
self.bg_pen.goto(320, 150)
self.bg_pen.color("#DC143C")
self.bg_pen.write("元旦快乐", font=("微软雅黑", 20, "bold"))
lantern_pos = [(-350, 150), (-250, 100), (250, 100), (350, 150)]
for x, y in lantern_pos:
self.draw_lantern(x, y, 25, self.bg_pen)
self.snow = self.DynamicSnow(self.screen, count=40)
self.horse = turtle.Turtle()
self.horse.speed(0)
self.horse.pensize(3)
self.horse.hideturtle()
self.leg_phase = 0
self.horse_pos = -400
self.firework_index = 0
self.current_firework = None
self.animate_horse()
def draw_lantern(self, x, y, size, pen):
"""绘制元旦灯笼(带流苏)"""
pen.penup()
pen.goto(x, y)
pen.pendown()
pen.color("#DC143C")
pen.begin_fill()
pen.setheading(180)
pen.circle(size, 180)
pen.setheading(0)
pen.circle(size, 180)
pen.end_fill()
pen.color("#FFD700")
pen.pensize(2)
pen.penup()
pen.goto(x - size, y)
pen.pendown()
pen.goto(x + size, y)
pen.penup()
pen.goto(x, y + size)
pen.pendown()
pen.goto(x, y + size + 10)
pen.setheading(90)
pen.circle(3, 360)
pen.penup()
pen.goto(x, y - size)
pen.pendown()
pen.color("#DC143C")
for i in range(10):
pen.penup()
pen.goto(x - 8 + i * 1.6, y - size)
pen.pendown()
pen.goto(x - 8 + i * 1.6, y - size - 20)
pen.color("#FFD700")
pen.penup()
pen.goto(x - 8, y - size - 20)
pen.pendown()
pen.goto(x + 8, y - size - 20)
def draw_horse(self, x, y, leg_offset=0):
"""绘制小马(主线程)"""
self.horse.clear()
self.horse.penup()
self.horse.goto(x, y)
self.horse.pendown()
self.horse.color("#8B4513")
self.horse.begin_fill()
self.horse.circle(40)
self.horse.end_fill()
self.horse.penup()
self.horse.goto(x + 30, y + 25)
self.horse.pendown()
self.horse.color("#DC143C")
self.horse.begin_fill()
for _ in range(2):
self.horse.forward(20)
self.horse.left(90)
self.horse.forward(10)
self.horse.left(90)
self.horse.end_fill()
self.horse.penup()
self.horse.goto(x + 35, y + 30)
self.horse.pendown()
self.horse.color("#8B4513")
self.horse.begin_fill()
self.horse.circle(25)
self.horse.end_fill()
self.horse.penup()
self.horse.goto(x + 20, y + 55)
self.horse.pendown()
self.horse.color("#654321")
for _ in range(6):
self.horse.setheading(120 + _ * 10)
self.horse.forward(15)
self.horse.backward(15)
legs = [
(x - 20, y - 40, -leg_offset),
(x - 40, y - 40, leg_offset),
(x + 20, y - 40, leg_offset),
(x + 40, y - 40, -leg_offset)
]
for (lx, ly, offset) in legs:
self.horse.penup()
self.horse.goto(lx, ly)
self.horse.pendown()
self.horse.color("#8B4513")
self.horse.goto(lx, ly - 50 + offset)
self.horse.penup()
self.horse.goto(lx - 5, ly - 50 + offset)
self.horse.pendown()
self.horse.color("black")
self.horse.begin_fill()
self.horse.circle(5)
self.horse.end_fill()
self.horse.penup()
self.horse.goto(x - 40, y)
self.horse.pendown()
self.horse.color("#654321")
self.horse.setheading(135)
for _ in range(5):
self.horse.forward(10)
self.horse.backward(10)
self.horse.right(10)
self.horse.penup()
self.horse.goto(x + 25, y + 50)
self.horse.pendown()
self.horse.color("#8B4513")
self.horse.goto(x + 15, y + 65)
self.horse.penup()
self.horse.goto(x + 45, y + 50)
self.horse.pendown()
self.horse.goto(x + 35, y + 65)
self.horse.penup()
self.horse.goto(x + 45, y + 35)
self.horse.pendown()
self.horse.color("black")
self.horse.begin_fill()
self.horse.circle(5)
self.horse.end_fill()
self.horse.penup()
self.horse.goto(x + 47, y + 40)
self.horse.pendown()
self.horse.color("white")
self.horse.begin_fill()
self.horse.circle(2)
self.horse.end_fill()
self.horse.penup()
self.horse.goto(x + 55, y + 25)
self.horse.pendown()
self.horse.setheading(-30)
self.horse.circle(8, 60)
def animate_horse(self):
"""小马奔跑动画循环(主线程,after 调度)"""
if not self.is_drawing:
return
if self.horse_pos < 300:
self.snow.update()
leg_offset = int(10 * abs(self.leg_phase % 20 - 10) / 10)
y_offset = random.randint(-3, 3)
self.draw_horse(self.horse_pos, y_offset, leg_offset)
self.leg_phase += 1
self.horse_pos += 5
self.screen.update()
self.root_gui.after(30, self.animate_horse)
else:
end_flag = turtle.Turtle()
end_flag.hideturtle()
end_flag.penup()
end_flag.goto(300, 50)
end_flag.pendown()
end_flag.color("#DC143C")
end_flag.write("🏁 2026 新起点", font=("微软雅黑", 20, "bold"))
self.screen.update()
self.animate_firework()
def animate_firework(self):
"""烟花动画循环(主线程,after 调度)"""
if not self.is_drawing:
return
if self.firework_index < len(self.firework_positions):
if self.current_firework is None:
x, y = self.firework_positions[self.firework_index]
self.current_firework = self.DynamicFirework(self.screen, x, y)
if self.current_firework.launch_step_update():
self.root_gui.after(10, self.animate_firework)
elif self.current_firework.explode_step_update():
self.root_gui.after(50, self.animate_firework)
else:
self.firework_index += 1
self.current_firework = None
self.root_gui.after(500, self.animate_firework)
else:
self.screen.update()
self.root_gui.after(1000, self.show_blessing_popup)
self.is_drawing = False
def show_blessing_popup(self):
"""安全显示祝福弹窗"""
try:
if self.root_gui and self.root_gui.winfo_exists():
messagebox.showinfo(
parent=self.root_gui,
title="2026 元旦快乐",
message="🎉 2026 元旦快乐 · 龙马精神 🐴\n愿你策马扬鞭,一路向前,万事顺遂!"
)
except Exception as e:
print(f"弹窗显示异常:{e}")
class DynamicSnow:
"""动态雪花类(飘落 + 晃动)"""
def __init__(self, screen, count=40):
self.screen = screen
self.count = count
self.snow_list = []
self.snow_pens = []
self._create_snow()
def _create_snow(self):
"""创建雪花"""
for _ in range(self.count):
x = random.randint(-450, 450)
y = random.randint(-250, 300)
speed_y = random.uniform(0.5, 1.5)
speed_x = random.uniform(-0.3, 0.3)
self.snow_list.append([x, y, speed_y, speed_x])
pen = turtle.Turtle()
pen.hideturtle()
pen.penup()
pen.color("#FFFFFF")
pen.goto(x, y)
pen.write("❄️", font=("Arial", 12))
self.snow_pens.append(pen)
def update(self):
"""更新雪花位置(飘落动画)"""
for i, (x, y, speed_y, speed_x) in enumerate(self.snow_list):
y -= speed_y
x += speed_x
if y < -250:
y = 300
x = random.randint(-450, 450)
self.snow_pens[i].clear()
self.snow_pens[i].goto(x, y)
self.snow_pens[i].write("❄️", font=("Arial", 12))
self.snow_list[i] = [x, y, speed_y, speed_x]
class DynamicFirework:
"""动态烟花类(升空 + 爆炸 + 消散)"""
def __init__(self, screen, x, y):
self.screen = screen
self.x = x
self.y = y
self.pen = turtle.Turtle()
self.pen.hideturtle()
self.pen.speed(0)
self.pen.penup()
self.particles = []
self.launch_step = -250
self.explode_step = 0
def launch_step_update(self):
"""升空动画单步更新(适配 after 调度)"""
if self.launch_step < self.y:
self.pen.clear()
self.pen.pendown()
self.pen.color("#FFFFFF")
self.pen.pensize(2)
self.pen.goto(self.x, self.launch_step)
self.launch_step += 5
self.screen.update()
return True
else:
self.pen.penup()
self.pen.clear()
return False
def explode_step_update(self):
"""爆炸动画单步更新(适配 after 调度)"""
if self.explode_step == 0:
colors = ["#FFD700", "#DC143C", "#FF1493", "#00CED1", "#008000"]
self.particles = []
for _ in range(50):
angle = random.randint(0, 360)
speed = random.randint(5, 12)
color = random.choice(colors)
self.particles.append([self.x, self.y, angle, speed, color, 1.0])
if self.explode_step < 30:
self.pen.clear()
for i, (x, y, angle, speed, color, alpha) in enumerate(self.particles):
rad = math.radians(angle)
new_x = x + speed * math.cos(rad)
new_y = y + speed * math.sin(rad)
speed *= 0.95
alpha -= 0.03
if alpha > 0:
self.pen.goto(new_x, new_y)
self.pen.color(color)
self.pen.dot(int(alpha * 6))
self.particles[i] = [new_x, new_y, angle, speed, color, alpha]
self.explode_step += 1
self.screen.update()
return True
else:
self.pen.clear()
return False
def ascii_horse_blessing_gui(text_widget):
"""GUI 版 ASCII 艺术马年元旦祝福"""
text_widget.delete(1.0, tk.END)
text_widget.tag_configure("yellow", foreground="#FFD700")
text_widget.tag_configure("red", foreground="#DC143C")
text_widget.tag_configure("green", foreground="#008000")
text_widget.tag_configure("blue", foreground="#191970")
text_widget.tag_configure("magenta", foreground="#FF1493")
text_widget.tag_configure("cyan", foreground="#00CED1")
text_widget.tag_configure("white_red_bg", foreground="white", background="#DC143C")
text_widget.insert(tk.END, "=" * 50 + "\n", "white_red_bg")
horse_lines = [
" ┏┓ ┏┓ 2026\n",
" ┃┃ ┃┃ 丙午马年\n",
" ┃┗━━━┛┃ 🐴 龙马精神\n",
" ┃┏━━━┓┃ \n",
" ┗┛ ┗┛ \n"
]
for i, line in enumerate(horse_lines):
color = "yellow" if i in [0, 1, 4] else "red"
text_widget.insert(tk.END, line, color)
text_widget.insert(tk.END, "🎊 2026 元旦快乐 · 策马扬鞭 🎊\n", "blue")
text_widget.insert(tk.END, "✨ 新岁启封,万事顺遂,马到成功 ✨\n", "magenta")
text_widget.insert(tk.END, "🌟 前路浩浩荡荡,万事皆可期待 🌟\n", "cyan")
text_widget.insert(tk.END, "=" * 50 + "\n", "white_red_bg")
text_widget.see(1.0)
def custom_name_blessing_gui(name_entry, text_widget):
"""生成个性化祝福"""
blessing_templates = [
"{name},2026 丙午马年,元旦快乐!愿你策马扬鞭,前程似锦~",
"🐴 {name},元旦喜乐!2026 龙马精神,万事兴'马',一路生花!",
"新岁启封,{name}!2026 元旦快乐,马到成功,事事顺心~",
"🌟 {name},2026 元旦安康!愿你如骏马奔腾,不负韶华!",
"2026 元旦快乐,{name}!策马前行,日子滚烫,我们都闪闪发光~",
"🎊 {name},2026 马年元旦至!愿你步步生风,马开得胜,岁岁安澜~",
"🐎 {name},新岁有新章!2026 元旦快乐,纵马踏歌,奔赴山海~",
"✨ {name},2026 元旦大吉!愿你如良驹踏春,前路皆坦途,万事皆可期~",
"🎈 {name},元旦快乐!2026 马年行大运,扬鞭奋蹄,所求皆如愿~",
"🌿 {name},新岁伊始,2026 元旦快乐!愿你策马向暖阳,岁岁常欢愉~",
"🔥 {name},2026 丙午马年,元旦添喜!愿你快马加鞭,不负时光,不负自己~",
"🎁 {name},元旦快乐!2026 愿你驭马乘风,日子有盼,心中有光~"
]
name = name_entry.get().strip() or "朋友"
text_widget.delete(1.0, tk.END)
text_widget.tag_configure("blue_bg", foreground="white", background="#191970")
text_widget.tag_configure("gold", foreground="#FFD700")
text_widget.insert(tk.END, "🎁 2026 马年专属元旦祝福 🎁\n", "blue_bg")
text_widget.insert(tk.END, random.choice(blessing_templates).format(name=name) + "\n", "gold")
name_entry.delete(0, tk.END)
text_widget.see(1.0)
def create_main_gui():
"""创建主窗口"""
tk.NoDefaultRoot()
root_gui = tk.Tk()
root_gui.title("2026 丙午马年元旦祝福程序 🐴")
root_gui.geometry("900x650")
root_gui.resizable(True, True)
root_gui.configure(bg="#FFF8DC")
anim_manager = AnimationManager()
anim_manager.root_gui = root_gui
def on_closing():
anim_manager.is_drawing = False
try:
if anim_manager.screen:
anim_manager.screen.bye()
except: pass
root_gui.destroy()
sys.exit(0)
root_gui.protocol("WM_DELETE_WINDOW", on_closing)
title_label = tk.Label(
root_gui, text="2026 丙午马年元旦祝福 🎊", font=("微软雅黑", 24, "bold"), bg="#FFF8DC", fg="#DC143C"
)
title_label.pack(pady=15)
button_frame = tk.Frame(root_gui, bg="#FFF8DC")
button_frame.pack(pady=12)
ascii_btn = tk.Button(
button_frame, text="📜 显示马年 ASCII 祝福", font=("微软雅黑", 14), bg="#FFD700", fg="black", padx=15, pady=8, relief=tk.RAISED, command=lambda: ascii_horse_blessing_gui(result_text)
)
ascii_btn.grid(row=0, column=0, padx=12)
draw_horse_btn = tk.Button(
button_frame, text="🎨 绘制奔跑小马", font=("微软雅黑", 14), bg="#FF6347", fg="white", padx=15, pady=8, relief=tk.RAISED, command=anim_manager.init_turtle_screen
)
draw_horse_btn.grid(row=0, column=1, padx=12)
name_frame = tk.Frame(root_gui, bg="#FFF8DC", bd=2, relief=tk.GROOVE, padx=10, pady=8)
name_frame.pack(pady=12, fill=tk.X, padx=50)
name_label = tk.Label(
name_frame, text="✨ 输入祝福对象姓名:", font=("微软雅黑", 14), bg="#FFF8DC", fg="#191970"
)
name_label.grid(row=0, column=0, padx=8, pady=5)
name_entry = tk.Entry(
name_frame, font=("微软雅黑", 14), width=25, bd=2, relief=tk.SUNKEN
)
name_entry.grid(row=0, column=1, padx=8, pady=5)
generate_btn = tk.Button(
name_frame, text="生成专属祝福", font=("微软雅黑", 14), bg="#008000", fg="white", padx=15, pady=5, relief=tk.RAISED, command=lambda: custom_name_blessing_gui(name_entry, result_text)
)
generate_btn.grid(row=0, column=2, padx=8, pady=5)
result_label = tk.Label(
root_gui, text="祝福内容显示:", font=("微软雅黑", 14), bg="#FFF8DC", fg="#DC143C"
)
result_label.pack(pady=8)
result_text = scrolledtext.ScrolledText(
root_gui, font=("微软雅黑", 12), width=90, height=22, wrap=tk.WORD, bd=3, relief=tk.GROOVE, bg="#FFFFFF"
)
result_text.pack(padx=25, pady=10)
result_text.tag_configure("blue", foreground="#191970")
result_text.tag_configure("green", foreground="#008000")
result_text.insert(tk.END, "🎉 欢迎使用 2026 丙午马年元旦祝福程序!\n", "blue")
result_text.insert(tk.END, "👉 点击上方按钮选择功能,或输入姓名生成专属马年祝福~\n", "green")
root_gui.mainloop()
if __name__ == "__main__":
create_main_gui()