Logo小海龟,冲冲冲 English Version

我承认我激动了,居然刚发现python从2.5版本开始就自带了turtle这个模块。一见到这个久违了的名字,记忆就像一双大手,把我一下拽回那个属于童年的翡翠梦境。

本文就带各位看官在梦境中走一遭,示范如何使用python3提供的turtle模块进行七巧板拼图。

什么是小海龟?

话说了这么多,到底啥是小海龟?其实小海龟是国外用来启蒙青少年学习计算机的经典案例,源自一门名为Logo的专用语言。通过简单的指令,就可以操纵画板上的小海龟前进后退,左右转向。屏幕上的小海龟就是小朋友手中的画笔,能够在屏幕上绘制出各种各样的图形,通过所见即所得的方式激发小朋友们学习计算机的热情,算是寓教于乐的绝佳样板。

中西合璧的应用竞赛

回想起来很幸运,1999年我有幸代表无锡参加了在上海市少年宫举办的第三届全国少儿计算机应用竞赛。比赛一共分为两个项目,一项是使用windows95系统下自带的画图软件制作小报,美观者胜;另一项就是使用Logo语言在规定时间内绘制各种七巧板,根据完成数量判定胜负。

在那个486刚刚流行的年代,为了响应邓小平“教育要从娃娃抓起”的号召,一些有识之士及时把计算机相关教育引入国内,并组织发起一系列比赛,包括上文提到的全国少儿计算机应用竞赛。印象特别深刻的是除了我参加的这两个项目之外,大赛还开设了诸如机器人走迷宫之类的项目:娃娃们把机器人放在迷宫入口,机器人就开始跌跌撞撞地寻找出口。这在现在都算是相当超前的计算机早教了吧。

比赛结束之后还有大巴载着我们去参观计算机博物馆,给娃娃们展览那一系列梦境之源:8086系列芯片。那个年纪的我仅仅知道这些就是传说中计算机的大脑,但是它到底是怎么运作的?无论如何,这个问题已经悄然为我日后的生
活埋下了一条重要的主线。
全家福

重温经典

为了向Logo语言致敬,我将在使用python3的turtle模块时尽量模拟Logo环境,包括:

  • 放弃python3提供的面向对象的编程范式而使用过程式范式
  • 通过设置turtle.mode('logo')使用Logo定义的默认方向
    • 0代表正北方
    • 90代表正东方
    • 180代表正南方
    • 270代表正西方

听我指挥

要让小海龟动起来,第一步当然是基础的移动指令和转向指令:

  • 前进
    turtle.forward(distance)或者turtle.fd(distance)
  • 后退
    turtle.backward(distance)或者turtle.back(distance)
  • 向左转
    turtle.left(degree)
  • 向右转
    turtle.right(degree)
  • 也可以直接设置小海龟的朝向
    turtle.setheading(degree)

通过调用这些最基础的指令就能在画布上画出一个基本的正方形了。

1
2
3
4
5
6
7
8
9
10
11
12
import turtle

# 初始化
turtle.mode('logo') # 设置模式
turtle.home() # 设置归位到原点

for i in range(4):
turtle.forward(100)
turtle.right(90)

if __name__=='__main__':
turtle.exitonclick() # 保持画布不会自动关闭

效果如下图:
基本正方形

五颜六色

如果只是画出形状岂不是太单调了,五颜六色的世界才能吸引孩子们的眼球。turtle提供两条指令来进行颜色控制:

  • 设置画笔颜色
    turtle.pencolor(color_string)
  • 设置填充颜色
    turtle.fillcolor(color_string)
  • 或者同时设置画笔颜色和填充颜色
    turtle.color(pencolor, fillcolor)

如果要给一个形状填充颜色,需要调用begin_fill和end_fill方法。以下代码示范了如何在画布上画出一个红色的正三角。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import turtle

# 初始化
turtle.mode('logo') # 设置模式
turtle.home() # 设置归位到原点
turtle.color('red', 'red') # 同时设置画笔和填充色为红色
turtle.setheading(30) # 设置成30度

turtle.begin_fill()
for i in range(3):
turtle.forward(100)
turtle.right(120)
turtle.end_fill()

if __name__=='__main__':
turtle.exitonclick() # 保持画布不会自动关闭

效果如下图:
红色三角形

过程化

过程化编程是一种为了提高代码可复用性而将代码组织成一个个可重复调用过程的编程范式,在七巧板这个案例中,我们可以为每一块七巧板定义一个专用的过程,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
'''
filename: tangrams.py
Define procedures for each tangram.
'''
import turtle

turtle.mode('logo')

# 设置单位边长
SMALL_LENGTH = 100
MIDDLE_LENGTH = round(SMALL_LENGTH * (2 ** 0.5), 2)
LARGE_LENGTH = SMALL_LENGTH * 2
LARGEST_LENGTH = round(2 * SMALL_LENGTH * (2 ** 0.5), 2)

# 设置默认颜色
COLOR_LARGE_TRIANGLE_1 = '#99FF00' #绿色
COLOR_LARGE_TRIANGLE_2 = '#FF3300' #橘色
COLOR_MIDDLE_TRIANGLE = '#0033FF' #蓝色
COLOR_SMALL_TRIANGLE_1 = '#FF66FF' #粉色
COLOR_SMALL_TRIANGLE_2 = '#6600CC' #紫色
COLOR_SQUARE = '#FFFF33' #黄色
COLOR_TRAPEZOID = '#CCCCCC' #灰色

# 绘制基础三角形
def base_triangle(side_length, color):
turtle.color(color, color)
turtle.begin_fill()
turtle.fd(side_length)
turtle.right(135)
turtle.fd(round(side_length * (2 ** 0.5), 2))
turtle.right(135)
turtle.fd(side_length)
turtle.right(90)
turtle.end_fill()

# 绘制基础正方形
def base_square(side_length, color):
turtle.color(color, color)
turtle.begin_fill()

for i in range(4):
turtle.fd(side_length)
turtle.right(90)
turtle.end_fill()

# 绘制基础梯形
def base_trapezoid(side_length, color, direction='left'):
turtle.color(color, color)
turtle.begin_fill()

turtle.fd(round(side_length * (2 ** 0.5), 2))
if direction=='left':
turtle.left(45)
else:
turtle.right(45)
turtle.fd(side_length)
if direction=='left':
turtle.left(135)
else:
turtle.right(135)
turtle.fd(round(side_length * (2 ** 0.5), 2))
if direction=='left':
turtle.left(45)
else:
turtle.right(45)
turtle.fd(side_length)
if direction=='left':
turtle.left(135)
else:
turtle.right(135)
turtle.end_fill()

# 抬笔,在空中移动,并落笔
def move(distance):
turtle.penup()
turtle.fd(distance)
turtle.pendown()

# 右转
def right(degree):
turtle.right(degree)

# 左转
def left(degree):
turtle.left(degree)

# 展示
def end():
turtle.hideturtle()
turtle.exitonclick()

# 绘制大三角形1
def large_triangle_1():
base_triangle(LARGE_LENGTH, COLOR_LARGE_TRIANGLE_1)

# 绘制大三角形2
def large_triangle_2():
base_triangle(LARGE_LENGTH, COLOR_LARGE_TRIANGLE_2)

# 绘制小三角形1
def small_triangle_1():
base_triangle(SMALL_LENGTH, COLOR_SMALL_TRIANGLE_1)

# 绘制小三角形2
def small_triangle_2():
base_triangle(SMALL_LENGTH, COLOR_SMALL_TRIANGLE_2)

# 绘制中等三角形
def middle_triangle():
base_triangle(MIDDLE_LENGTH, COLOR_MIDDLE_TRIANGLE)

# 绘制正方形
def square():
base_square(SMALL_LENGTH, COLOR_SQUARE)

# 绘制梯形
def trapezoid(direction):
base_trapezoid(SMALL_LENGTH, COLOR_TRAPEZOID, direction)

if __name__=='__main__':
left(45)
square()
right(90)
large_triangle_1()
right(90)
large_triangle_2()
right(90)
small_triangle_1()
move(SMALL_LENGTH*2)
right(135)
trapezoid('right')
move(LARGEST_LENGTH)
right(90)
middle_triangle()
move(MIDDLE_LENGTH)
right(45)
move(SMALL_LENGTH)
right(180)
small_triangle_2()
end() # 保持画布不会自动关闭

如果单独运行上面的代码文件,可以得到如下的七巧板图案:
七巧板

来拼七巧板吧!

通过在你自己的代码中引入上面的模块,看官们就可以自己来绘制任意七巧板图形啦,比如我们用下面的代码来拼一个阿拉伯数字1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import turtle
from tangrams import *

left(45)
square()

move(SMALL_LENGTH)
right(90)
move(SMALL_LENGTH)
small_triangle_1()

right(90)
move(SMALL_LENGTH)
left(135)
trapezoid('right')

left(135)
move(SMALL_LENGTH)
right(180)
large_triangle_1()

right(90)
move(LARGE_LENGTH)
right(90)
large_triangle_2()

move(SMALL_LENGTH)
right(180)
small_triangle_2()

right(90)
middle_triangle()

end()

效果如下图:
七巧板-阿拉伯数字1

接下来就请有兴趣的看官自由发挥,实现下图中的其他阿拉伯数字吧:
七巧板-家庭作业

写在最后

Logo语言之所以能够作为一门教育专用语言受到孩子们的青睐,源于它抓住了画图这个切入口,在吸引孩子们动手画画的同时,潜移默化地为孩子们启蒙了二位坐标系,角度,方向等一系列几何概念。

时至今日,我尤其感激当年发起少儿计算机应用竞赛的前辈们。当时比赛的两个项目暗中契合了如今计算机在我们日常生活中通过提供计算能力所提供的主流应用场景:

  • 感知延伸
    所有在线展示环境(web网页/视频站点/音乐网站以及集大成者游戏),都借由计算机拓展了我们的感知系统,提升的是我们接触获取信息的效率。
  • 建模
    通用计算机通过执行内存中的程序来模拟人类活动,越来越多的流程被移植到计算平台上来执行,以利用计算机稳定/高速的特点,提升的是处理信息本身的效率。

更快地获取信息加上更快地处理信息,我们离奇点越来越近。

参考资料

  1. Logo语言
  2. 七巧板 - 维基百科,自由的百科全书
  3. 过程式编程 - 维基百科,自由的百科全书
  4. 24.1. turtle — Turtle graphics — Python 3.6.3rc1 documentation