背景
turtle --- Turtle graphics 中提供了关于 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 电脑上进行操作的,代码里有一个地方用到了系统相关的路径(具体位置如下图所示),如果您用的是其他系统,请将其替换为合适的值

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

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