第4章 案例研究:接口设计
练习 4-4 用函数画大写字母表
字母表中的字母可以使用一些基本元素来构成,如横线、竖线以及一些曲线。设计一个字母表,可以使用最少的基本元素画出来,并且编写函数来画出字母。
【求解】
这道题教会我最重要的一件事是:用完东西要放回原处。
虽然这么简单的一个道理,父母从小就教,但是我根本没care,常用的东西放在显眼的地方,不常用的东西就随缘了,到用的时候再找。
平时生活中用东西我都当成了一个件独立的事,并没有连成整体思考,但是通过本题 打字机代码 验证的时候把26个字母连成了整体,我第一次验证的时候,虽然能打出字,但是不仅对不齐,甚至有的字母还是躺着的……就是因为画完每个字母乌龟没有归位,后面又花了时间重新给每个字母乌龟用前移动到起点、用完归位。
第二个道理是:将应用模块与公共调用模块彻底分开。
由于验证的时候发生了“没有归位”的问题,当时就想赶紧归位解决了,在每个字母的函数后面直接添加归位位移,结果在验证有的字母就直接变形了。
比如我的G、O、Q是在画完没有归位的C的基础上直接添加直角、竖线、斜线完成的,G、O直接调的C,Q直接调的O,当我给C的乌龟归位后,调用C的这3个字母的其他部分全都跟着位移了……导致后面很多字母都重写了(不仅这几个字母,还有很多直线我之前直接用的draw_i
)。
Step.1 设计字体
本来想设计一个像电子表数字的字体,丑点就丑点不要画弧线(弧线麻烦),但是发现26个字母,形态还是挺丰富的,光靠直线不行必须要弧线……
话说这题其实是锻炼抽象能力吧?草稿改了两次,终于统一到只保留横线、竖线、左斜线、右斜线、弧线:
这里N写错了不要在意,后面调试的时候发现改过来了(虽然是在写这篇文章的时候)
Step.2 分类抽象
横竖线:E、F、H、I、L、T
左右斜线:A、K、M、N、V、W、X、Y、Z
半圆+横线:B、P、R
半圆+竖线:J、U
基于C:C、G、O、Q
只有弧线:S
Step.3 问题求解
只有弧线:S
#多边线
def polyline(t, n, length, angle):
for i in range(n):
t.fd(length)
t.lt(angle)
#弧
def arc(t, r, angle):
arc_length = 2 * math.pi * r * abs(angle) / 360
n = int(arc_length / 4) + 3
step_length = arc_length / n
step_angle = float(angle) / n
t.lt(step_angle/2)
polyline(t, n, step_length, step_angle)
t.rt(step_angle/2)
横竖线:E、F、H、I、L、T
#线段
def line(t, l):
t.fd(l)
#左转直角
def right_angle(t, l1, l2):
line(t, l1)
t.lt(90)
line(t, l2)
左右斜线:A、K、M、N、V、W、X、Y、Z
#左斜线
def l_slash(t, tan, l):
angle = math.atan(tan) * 180 / math.pi
m = math.sqrt( 1 / tan**2 + 1) * l
t.lt(angle)
line(t, m)
t.rt(angle)
#右斜线
def r_slash(t, tan, l):
angle = math.atan(tan) * 180 / math.pi
m = math.sqrt( 1 / tan**2 + 1) * l
t.rt(angle)
line(t, m)
t.lt(angle)
半圆+横线:B、P、R
#B、P、R公共部分:
def bpr(t, l):
r = l/4
angle = 180
line(t, r)
arc(t, r, angle)
line(t, r)
基于C:C、G、O、Q
#C、G、O、Q公共部分:
def cgoq(t, l):
#移动到起点
t.pu()
right_angle(t, l*1/2, l*3/4)
t.pd()
#C
arc(t, l/4, 180)
line(t, l/2)
arc(t, l/4, 180)
Step.4 完成代码
文件 letters.py
中不要有具体函数的调用指令,要不然你还没打字,typewriter.py
就直接执行这个函数了。也不要有 turtle.mainloop()
指令,要不然还没开始就什么都执行不了。
"""
《Think Python》练习 4-4:字母表
基本元素:弧线、直线、左斜线、右斜线
"""
#引入数学模块、乌龟模块
import math
import turtle
#调用乌龟画图、提高画弧速度
bob = turtle.Turtle()
bob.delya = 0.01
#多边线
def polyline(t, n, length, angle):
for i in range(n):
t.fd(length)
t.lt(angle)
#弧
def arc(t, r, angle):
arc_length = 2 * math.pi * r * abs(angle) / 360
n = int(arc_length / 4) + 3
step_length = arc_length / n
step_angle = float(angle) / n
t.lt(step_angle/2)
polyline(t, n, step_length, step_angle