陈斌 陈天翔
Python语言中内置的海龟作图turtle模块设计巧妙,作图模型简单强大,能够让程序设计初学者很快编写出趣味生动的作图程序,极大提高编程学习的兴趣和积极性,在练习过程中培养和提高计算思维。除了绘制图形之外,Python turtle模块还具有基本的交互功能,加上学习门槛低,又是Python语言内置的标准模块,所以非常适合作为创意编程的学习和开发平台。本文以Python turtle模块为核心,展示和分析交互游戏、数学对象可视化等学科领域的创意编程实例,并介绍turtle模块的深入编程,以供创意编程的教学参考,也可用于高中Python程序设计课程的教学案例。
本文实例所涉及的代码和截图,均可通过链 接(https://github. com/chbpku/bdfz.courses/wiki)访问获取。
交互游戏:接苹果
本作品是一个通过鼠标控制的交互游戏。程序运行后,在turtle窗口中会有随机数量和位置的红色苹果从顶端向下掉落,掉落速度各不相同。用户需要通过鼠标拖动窗口中间的三角形状“托篮”接住每一个苹果。托篮可以在窗口中随意移功,如果接住苹果,则加10分,分数在窗口左下角实时更新显示,但如果未能接住苹果使其掉出窗口下沿的话,则惩罚性地减100分。由于苹果产生的位置和速度均为随机,数量不定,惩罚性减分幅度大,游戏还是有相当难度的,想一直保持正分不太容易。最后点击关闭窗口即可退出游戏。游戏运行效果如图1所示。
turtle功能
本作品涉及到的turtle模块功能主要有5个。
第1个是海龟绘图加速功能,通过在程序前部加tracer方法调用禁止动画显示。
将海龟basket的拖动事件绑定到basket的goto函数,这样,当用户用鼠标点击这个海龟并进行拖动的时候,会触发drag事件,实现调用basket.goto函数,并将事件发生时海龟的坐标作为参数传递给basket. goto函数,从而实现鼠标拖动到哪里,海龟asket就跟到哪里的交互效果。海龟的鼠标交互事件还有点击事件onclick、释放事件nrelease,都可以绑定处理函数,从而实现点击、释放鼠标各个按钮的交互。
第3个是海龟克隆功能,如程序中的第14行,海龟model的clone方法,可以将model对象复制1个,赋值给basket,克隆会产生新的海龟对象,并且保留原海龟对象的所有属性值。利用克隆功能,能够很方便地复制出相互独立而又具有相同初始属性的多个海龟,这些海龟后续修改属性并不会相互影响。
第4个是海龟形状设定功能,如程序中的第13、15行,由于鼠标交互需要整体拖动一个图形,我们就可以将一个海龟的形状设置为这个图形,实现图形的动画和接受鼠标拖动事件。第13行在程序中用addshape函数添加注册1个名字为“basket”的形状,从代码可以看出,这是1个以海龟坐标为中心的倒三角形。第15行用shape函数将海龟basket设置成名称为“basket”的形状。
我们也可以用shape函数将海龟的形状改为turtle模块内置的形状,如箭头"arrowl"、海龟"turtle"、圆"circle"、方形"square"、三角形"triangle"和经典形状"classic"。
第5个是海龟的“盖戳”复印功能,如程序中的第43行,设定好红色苹果形状的海龟mould作为印模,可以在海龟当前位置上留下自身的形状。即便移走海龟,这个形状仍然保持在原地。
40 #苹果下落,并用印模画出苹果
41 apple[1] -=apple[2]
42 mould. goto(apple[0],apple[1])
43 mould.stamp()
stamp函数将返回一个stampid,如果需要清除這个形状,则可以调用clearstamp豳数清除指定stampid的形状,或者调用clearstamps函数清除所有形状。
程序代码分析
程序可以分为2个部分:第1-28行为初始化部分,第30-57行为循环体部分。
初始化部分中,第1-2行导入了必要的运行库。
1 import turtle, time
2 form random import randrange
第4-7行关闭了turtle的动画效果,并创建了基础的画笔对象,用于后续的复制。
4 turtle.tracer(0)
5 model=turtle.Turtle( )
6 model.hideturtle()
7 model.penup()
第9-10行设置了几个游戏参数。
9 FPS=30 #每秒30帧刷新率
10 FREQ=FPS//2#平均每秒生成2个苹果
第12-18行创建了果篮对象,将其设置为自定义形状,并绑定至鼠标拖动事件上。
12 #接苹果的篮子
13 turtle.addshape('basket', ((-100,0),(100,0),(0,-25)))
14 basket=model.clone()
15 basket.shape('basket')
16 basket.setheading(90)
17 basket.ondrag(basket.goto) #把goto函数绑定到鼠标拖动事件上
18 basket.showturtle()
第20-23行创建了绘制苹果印模的画笔对象,并设置了其颜色与形状。
20 #用来显示苹果的印模
21 mould=model.clone()
22 mouldcolor('red')
23 mould.shape('circle')
第25-28行创建了绘制得分文字的画笔,设置了颜色与位置。
26 board = model.clone()
27 board.goto(-300,-300)
28 board.color('blue')
循环体部分前声明了苹果列表与当前得分,随后进入无限循环;循环体内首先清除了上一帧绘制的苹果。
30 apples=[]
31 score=0
32 while True:
33 mould.clearstamps()
随后,根据随机数值确定当前帧是否生成苹果,并将相应生成的苹果加入列表内,每个对象记录了横纵坐标与下落速度。
34 if randrange(FREQ)==0:
35 #生成苹果[x,y,s]加入列表,s是一次下落高度
36 apples.append([randrange(-350,350),400,5+ randrange(10)])
38-52行为主要的涛戏逻辑:首先记录篮子横纵坐标为b_x与b_y,随后遍历苹果列表中每个对象。
38 b_x. b_y=basket.pos()
39 for apple in apples:
对每个苹果,在40-43行,首先使其下落相应高度,并在下落后的位置使用stamp绘制。
40 #苹果下落,并用印模画出苹果
41 apple[1]-=apple[2]
42 mould.goto(apple[0], apple[1])
43 mould.stamp()
之后,44-52行中判断了每个苹果的位置,若在篮子内则加分并移除;若落出底边则扣分并移除。
44 #判断苹果的位置
45 if,abs(apple[0]-b_x)<=100 and -<=apple[1]-b_y<=25:
46 #篮子碰上了苹果,加分
47 score+=10
48 apples.remove(apple)
49 elif apple[1]<-400:
50 #苹果掉出底线,没接到,减分
51 score-= 100
52 apples.remove(apple)
最后,在54-57行,由得分板画笔写出当前得分,并刷新屏幕呈现内容,最后按帧率停顿相应时间。
54 board.clear()
55 board.write(f'SCORE: {score}',font=('SYSTEM', 40,'normal'))
56 turtle.update()
57 time.sleep(1/FPS)
【因篇幅所限,以下创意编程实例中的“程序代码分析”部分,请访问杂志官网阅读。】
数学对象可视化:玫瑰曲线
本作品通过玫瑰曲线的数学定义,使用turtle库绘制出来。通过改变代码内参数可绘制不同的玫瑰曲线。程序运行结果如图2。
turtle功能
本作品涉及的turtle功能有2个。
第1个是通过pencolor与pensize函数设置画笔颜色与大小,此外还有fillcolor设
置填充色,color同時设置画笔色与填充色,shapesize设置画笔形状大小等函数。例如程序10-11行。
10 rose.pencolor('red')
11 rose.pensize(7)
第2个是设置动画移动速度,如第12行设置其为最快。
12 rose.speed('fastest')
数学财象可视化:分形Koch雪花
本作品通过科赫曲线的定义,将3条科赫曲线绘制成为雪花形状的分形进行呈现。程序运行效果如图3。
turtle功能
本作品涉及到的turtle模块功能主要有2个。
第1个是取消动画效果与手动更新。
3 turtle.tracer(0)#取消动画加快绘图速度
35 turtle.update()#与tracer配合使用
第2个是turtle中的颜色系统,不仅可以指定RGB值设置颜色,也包括很多由颜色名称预置的颜色,如"sky blue"与"snow";此外,可以通过bgcolor设置画布颜色,以及begin_fill与end_fill填充多边形内部。
4 turtle.bgcolor('sky blue')
26
snow.flllcolor('snow')
27 snow.begin_fill()
数学对象可视化:蒙特卡洛法求圆周率
本作品模拟了经典的平面授点求圆周率的过程,将投点的过程与相应的估算圆周率通过turtle可视化为动画。程序运行效果如图4。
turtle功能
本作品涉及到的turtle模块功能主要有4个。
首先是绘图加速功能,通过turtle.tracer(0)关闭动画效果,辅以手动的turtle。update()更新画面。
3
turtle.tracer(0)
42
#刷新屏幕
43
turtle.update()
其次是移动系统,包括坐标移动函数goto,前进转向等控制方式forward. left等,以及预定义的轨迹移动,如circle函数。
14 t.goto(0, -R)
15 t.pendown()
16 t.circle(R)
17 for i in range(4):
18
t.forward(R)
19
t.left(90)
20
t.forward(R)
21 t.penup()
第3个是dot画点的功能,可以输入参数指定点大小与颜色。
29 if x **2+y**2<=R**2:
30 n+=1
31 t.dot(3,'red')
32 else:
33 t.dont(.,'black')
最后是write绘制文字的功能。
38
#显示文字
39
label.clear()
40
label.write(f'pi~={pi: .6f}({n:7):{m 6}),font=FONT)
物理仿真:抛物和碰撞
本作品通过欧拉法逐帧模拟了一个小球受到重力与空气阻尼(正比于速度)作用,进行斜抛运动,并在墙面与地面发生弹性碰撞的现象。通过turtle库可视化了墙面与地面的位置,以及小球的运动路线,并且保留绘制了小球从发射到减速停止的运动轨迹。程序运行效果如图5。
turtle功能
本作品涉及到的turtle功能主要有3个。
第1个是绘制加速和千动更新画面。
3
turtle.tracer(0)
42
turtle.update()
第2个是绘制路径的基本功能。
14 #绘制地面和墙
15 ball.pencolor('blue')
16 ball.penup()
17
ball.goto(-500,GROUND_Y)
18 ball.pendown()
19
ball.goto(WALL_X,GROUND_Y)
20 ball.goto(WALL_X,500)
第3个是更改形状与形状大小。
12
ball = turtle.Turtle ('circle')
13 ball.shapesize(R / 10)
地球空间信息可视化:地图绘制
本作品结合了shapefile库(通过pip install pyshp安装)的功能,读取ESRI Shapefile (shp)地图矢量图文件,并使用turtle库将其绘制出来。程序运行效果如图6。
turtle功能
本作品涉及的turtle功能有3个。
第1个是海龟绘图加速功能。
1
import turtle, random
2
import shapefile#需要安装shapefile模块,读取
4 turtle.tracer(0) #海龟加速,无动画
47 turtle.update()
第2个是turtle画布的设置,包括第17行设置窗口宽高,与第21行谩置坐标系。
17 turtle.setup(w+20,h+30)
18
19 #将海龟坐标系设置为与地图坐标相同
20
#turtle. setworldcoordinates (layer.bbox[0], layer.bbox[l], layer.bbox[2], layer bbox[3])
21
turtle. setworldcoordinates( *layer. bbox)
第3个是多边形的绘制与上色,turtle中要绘制复杂边界的区域,并对其内部进行上色时,使用begin_fill与end_fill函數标记区域边界的起止,在落笔前调用beginfill()并在结束绘制后调用end_fill()就会根据画笔当前通过color或fillcolor函数设置的填充颜色对其间经过的区域进行上色。如代码中32-43行。
32 for xy in f.shape.points:
33 map_pen.goto(xy)
34 if new_polygon :
35
start xy
36 map_pen.pendown()
37 map_pen.fillcolor(random. choice(colors))
38 map_pen.begin_fill()
39 new_polygon = False
40 elif xy == start:
41 map_pen.endjll()
42 map_pen.penup()
43 new_polygon = True
生物学仿真:标记重捕法
栎记重捕法是生物学上用于研究一个地区种群数量的方法,通过捕捉少量的个体进行标记并放回,一段时间后重新捕捉,并通过重捕数、重捕的标记数与标记总数估算出整个种群的数量。本作品通过turtle可视化了标记重捕法中标记、放回、重捕的动态过程,并且即时地进行数量估算,与实际数量进行对比,将估算公式与结果以文字形式输出。程序运行截图如图7。
turtle功能
本作品涉及到的turtle模块功能主要有4个。
首先是绘图加速功能,通过turtletracer(0)关闭动画效果,辅以手动的turtle.tracer(0)关闭动画效果,辅以手动的turtle.update()更新画面。
4
turtle.tracer(0)
75
turtle.update()
其次是基础的坐标移动与画线功能。
27
for x in SIZEC, SIZEP:
28
tt.goto(-x, x)
29
tt.pendown()
30
tt.goto(-x, -x)
31
tt.goto(x, -x)
32
tt.goto(x, x)
33
tt.goto(-x, x)
34
tt.penup()
第3个是dot画点的功能。
59
#绘制
60
t_dot.goto(pos)
61
t_dot.dot()
最后是write绘制文字的功能。
71
t_text.clear()
72
t_text.write(
73
'Actual: %\nEstimated: %s= %s'%(N, n_calc, formula), font=FON)
Python語言是一种语法简洁、功能强大而又对初学者友好的通用型编程语言,在标准的Python语言发行版中,内置了入门快、表现力强的turtle模块,让初学者通过几行代码就能绘出精美的图形,再通过简单的逻辑即可进行键盘鼠标的交互。Python语言及turtle模块的组合非常适合初学者进行创意编程的起点和创作工具,本文展示了艺术化的数字图形之外,在基础教育中各学科创意编程的实例,希望以此抛砖引玉,读者们可以创作出更多面向科学探索的创意编程作品。