[Python] 借助 Turtle 逐字展示《醉翁亭记》

背景

turtle --- Turtle graphics 中提供了关于 turtle\text{turtle} turtle 模块的介绍。我想到可以用 turtle\text{turtle} turtle 来展示经典的古文,比如《醉翁亭记》,于是用 trae 完成了代码(我做了少量调整)。

正文

整体思路

我想借助 turtle --- Turtle graphics 来逐字展示《醉翁亭记》,示例效果如下图所示 ⬇️

有几个核心的问题

  • 界面的长和宽需要根据字数动态计算,而不是 hard-code
  • 每过一个固定的时间,就多展示一个字,我们可以在 main 方法里实现这个主循环

借助 trae,我们就不必自己处理这些细节了。在它生成的代码的基础上,再让它进行调整(或者自己亲自调整)即可。这次的代码,主要是 trae 完成的,我只做了些微小的调整,就不赘述写代码的过程了(我在它提供的代码的基础上,反复运行并让它继续调整)。

完整的代码

python 复制代码
import math
import time
from turtle import Screen, Turtle

ARTICLE = (
    "環滁皆山也。 其西南諸峰,林壑尤美。望之蔚然而深秀者,琅琊也。"
    "山行六七里,漸聞水聲潺潺,而瀉出於兩峰之間者,讓泉也。"
    "峰回路轉,有亭翼然臨於泉上者,醉翁亭也。作亭者誰?山之僧曰智僊也。"
    "名之者誰?太守自謂也。太守與客來飲於此,飲少輒醉,而年又最高,"
    "故自號曰醉翁也。醉翁之意不在酒,在乎山水之間也。"
    "山水之樂,得之心而寓之酒也。"
    "\n\n"
    "若夫日出而林霏開,雲歸而巖穴暝,晦明變化者,山間之朝暮也。"
    "野芳發而幽香,佳木秀而繁陰,風霜高潔,水落而石出者,山間之四時也。"
    "朝而往,暮而歸,四時之景不同,而樂亦無窮也。"
    "\n\n"
    "至於負者歌於途,行者休於樹,前者呼,後者應,傴僂提攜,"
    "往來而不絕者,滁人遊也。臨谿而漁,谿深而魚肥;釀泉為酒,泉香而酒洌;"
    "山肴野蔌,雜然而前陳者,太守宴也。宴酣之樂,非絲非竹,射者中,"
    "弈者勝,觥籌交錯,起坐而諠譁者,眾賓懽也;蒼顏白髮,"
    "頹然乎其間者,太守醉也。"
    "\n\n"
    "已而夕陽在山,人影散亂,太守歸而賓客從也。樹林陰翳,鳴聲上下,"
    "遊人去而禽鳥樂也。然而禽鳥知山林之樂,而不知人之樂;"
    "人知從太守遊而樂,而不知太守之樂其樂也。醉能同其樂,"
    "醒能述以文者,太守也。太守謂誰?廬陵歐陽脩也。"
)

CHAR_SIZE = 20
CHAR_WIDTH = 36
CHARS_PER_COLUMN = 20
COLUMN_SPACING = 40
MARGIN = 80

CHAR_DELAY_MS = 150

FONT_PATH = "/System/Library/Fonts/PingFang.ttc"

PUNCTUATION = set(",。、;:?!「」『』()【】《》""''......---·〈〉﹝﹞〔〕")


def load_article():
    return "".join(
        ch for ch in ARTICLE if ch not in PUNCTUATION and not ch.isspace()
    )


def draw_char(x, y, ch, pen):
    pen.penup()
    pen.goto(x, y)
    pen.pendown()
    font = (FONT_PATH, CHAR_SIZE, "normal")
    pen.write(ch, align="center", font=font)


def setup_screen(width, height):
    screen = Screen()
    screen.setup(width, height)
    screen.title("醉翁亭記")
    screen.tracer(0)
    return screen


def setup_pen():
    pen = Turtle()
    pen.hideturtle()
    pen.color("black")
    return pen


def draw_next_char(position, characters, screen, pen, start_x, start_y):
    col = position // CHARS_PER_COLUMN
    row = position % CHARS_PER_COLUMN

    x = start_x - col * COLUMN_SPACING
    y = start_y - row * CHAR_WIDTH

    ch = characters[position]
    draw_char(x, y, ch, pen)
    screen.update()


def main():
    characters = list(load_article())

    total = len(characters)
    column_count = math.ceil(total / CHARS_PER_COLUMN)
    content_width = (column_count - 1) * COLUMN_SPACING
    content_height = (CHARS_PER_COLUMN - 1) * CHAR_WIDTH + CHAR_SIZE

    screen_width = content_width + 2 * MARGIN
    screen_height = content_height + 2 * MARGIN

    start_x = screen_width // 2 - MARGIN
    start_y = screen_height // 2 - MARGIN - CHAR_SIZE

    screen = setup_screen(screen_width, screen_height)
    pen = setup_pen()

    for position in range(total):
        draw_next_char(position, characters, screen, pen, start_x, start_y)
        time.sleep(CHAR_DELAY_MS / 1000)

    screen.mainloop()


if __name__ == "__main__":
    main()

运行效果

请将以上代码保存为 main.py。使用如下命令可以运行 main.py

bash 复制代码
python3 main.py

运行中的效果如下图所示 ⬇️

全文都展示好之后,效果如下图所示 ⬇️

说明

字体

我是在 Mac 电脑上进行操作的,代码里有一个地方用到了系统相关的路径(具体位置如下图所示),如果您用的是其他系统,请将其替换为合适的值

《醉翁亭记》

为了便于读者使用,我把《醉翁亭记》全文嵌在代码里了,这并不是好的编程风格。

《醉翁亭记》的内容,我是从 这个链接 复制过来(为了方便展示,我删掉了其中的两个注释符号)的。《醉翁亭记》是北宋欧阳修的作品,所以没有版权问题。

参考资料

相关推荐
用户7088769039382 小时前
给传统 SaaS 增加 AI 能力:3个真实落地场景
python
卷无止境2 小时前
FastAPI中间件全解析:请求处理链条上的隐形关卡
后端·python·fastapi
用户0332126663672 小时前
使用 Python 将 HTML 内容添加到 PowerPoint 演示文稿中
python·html
看浪的路人2 小时前
第4讲:MCP Client 开发——连接、发现、调用
windows·python·ai
Swift社区2 小时前
Python 开发环境怎么选?PyCharm、VS Code、Trae 谁更适合 AI 开发?
人工智能·python·pycharm
卷无止境2 小时前
聊聊Web开发里的流式数据 从原理到FastAPI实战
后端·python·fastapi
SMF19192 小时前
【PyCharm】让 PyCharm 使用 .venv 虚拟环境
ide·python·pycharm
修远客2 小时前
感知模块:Agent的眼睛和耳朵 — 三层降级策略让Agent永不"失明"
python·agent
circuitsosk3 小时前
Prompt Engineering进阶:面向复杂业务场景的模板化管理与动态注入策略
python·langchain·prompt·跨境电商·rag·上下文管理·动态注入