在本章中,咱们将编写简短的、简单的程序来建立漂亮的、复杂的视觉效果。为了作到这一点,咱们可使用海龟做图软件。在海龟做图中,咱们能够编写指令让一个虚拟的(想象中的)海龟在屏幕上来回移动。这个海龟带着一只钢笔,咱们可让海龟不管移动到哪都使用这只钢笔来绘制线条。经过编写代码,以各类很酷的模式移动海龟,咱们能够绘制出使人惊奇的图片。css
使用海龟做图,咱们不只可以只用几行代码就建立出使人印象深入的视觉效果,并且还能够跟随海龟看看每行代码如何影响到它的移动。这可以帮助咱们理解代码的逻辑。html
第一个海龟程序
让咱们使用海龟做图来编写第一个程序。在一个新的IDLE窗口中输入以下的代码并将其保存为SquareSpiral1.py序)。程序员
SquareSpiral1.py算法
# SquareSpiral1.py - Draws a square spiral编程
import turtle 编程语言
t = turtle.Pen()ide
for x in range(100):函数
t.forward(x)工具
t.left(90)oop
用简短的SquareSpiral1.py程序建立的一个炫目的正方形螺旋线
是如何工做的
让咱们一行一行地分析这个程序,看看它是如何工做的。SquareSpiral1.py的第1行是注释。正如咱们在第1章中所学过的,注释以一个井号(#)开头。注释容许咱们在程序中写入给本身或之后可能阅读该程序的其余人一些提示。计算机不会阅读或试图理解井号以后的任何内容;注释只是让咱们写出关于程序是作什么的一些说明。在这个例子中,咱们将程序的名称以及针对其作什么的一个简单说明放入到注释之中。
第2行导入(import)了绘制海龟图形的功能。导入已经编写过的代码,这是编程工做的最酷的事情之一。若是咱们编写了一些有趣并有用的程序,能够将其与其余的人分享,同时也能够本身重用它。尽管海龟做图最初源自20世纪60年代的Logo编程语言[1],但一些很酷的Python程序员构建了一个库(library,库就是能够重用的代码的一个集合),来帮助其余程序员在Python中使用海龟做图。当咱们输入了import turtle,就表示咱们的程序可以使用那些Python程序员所编写的代码。图2-1中的小的黑色箭头表示海龟,它在屏幕上移动的时候会使用钢笔绘图。
程序的第3行是t = turtle.Pen(),它告诉计算机,咱们将使用字母t表示海龟的钢笔。这使得咱们只须要录入t.forward(),而不是turtle.Pen().forward(),就可让海龟在屏幕上移动的时候用海龟的钢笔进行绘制。字母t是告诉海龟作什么的一种快捷方式。
第4行最为复杂。在这里,咱们建立了一个循环(loop),它重复一组指令不少次(一次又一次地循环这些代码行)。这个特定的循环设置了一个范围(range,或列表),其中拥有从0~99的100个数字(计算机几乎老是从0开始计数,而不是像咱们一般那样从1开始)。在该循环中,字母x遍历了范围中的每个数字。所以,x从0开始,而后变为1,而后是2,依次类推,直到99,一共100个步骤。
x叫做变量(variable)[2](在第1章中的YourName.py程序中,name就是变量)。变量存储了在程序进行的过程当中能够修改(变化)的一个值。咱们在所编写的几乎每个程序中,都要使用变量,所以,早点认识变量为好。
接下来的两行代码缩进了,或者说,在左边留出了空格。这意味着,它们位于该循环之中(in the loop)而且和上面的那一行代码一块儿,每次x从0~99的范围中获取一个新的数字的时候,这些代码行都会重复,直到达到100次。
让咱们看看Python初次读取这一组指令的时候发生了什么。命令t.forward(x)让海龟的钢笔在屏幕上向前移动x个点。由于x是0,钢笔根本不会移动。最后一行代码t.left(90)让海龟向左转90°,或者说转四分之一个圈。
因为这个for循环,程序继续运行而且回到了循环的开始位置。计算机加1后将x移动到范围中的下一个值,由于1仍然位于从0~99的范围中,循环继续。如今x是1,所以,钢笔向前移动1个点。而后,钢笔向左移动90个点,由于代码是t.left(90)。这样一次一次地继续执行,当x到达99,即循环的最后一次迭代,钢笔围绕着正方形螺旋线的外围画了一条长长的线条。
下面咱们随着x从0增长到100,将循环的每一步可视化地表示出来。
-
for x in range(100):
-
t .forward(x)
-
t .left(90)
循环0到4:绘制了前4条线(在x = 4以后)。
循环5到8:绘制了另外4条线;正方形出现了。
循环9到12:正方形螺旋线变为了12条线(3个正方形)。
计算机屏幕上的点或像素可能过小了,以致于咱们没法很好地看到它们。可是,随着x变得愈来愈接近100,海龟绘制的线条包含了愈来愈多的像素。换句话说,当x变得愈来愈大,t.forward(x)绘制的线条愈来愈长。屏幕上的海龟箭头,绘制一下子,而后向左转,再绘制一下子,再向左转,这样一次又一次地绘制,每次线条都变得愈来愈长。
最后,咱们有了一个炫目的正方形形状。连续4次向左转90°,就能够获得一个正方形,就像是围绕一栋建筑连续4次左转的话,将会带着咱们绕建筑转一圈而且回到起点同样。
在这个示例中,咱们之因此获得一个螺旋线,是由于每次左转的时候,都走得更远一点。绘制的第一个线条只是1步长(x = 1的时候),而后是2(循环的下一次迭代),而后是3,而后是4,以此类推,直到达到100步长,这时候,线条的长度为99像素。再一次强调下,屏幕上的像素可能过小了,以致于咱们没法很容易地看到单个的点,可是,它们是存在的,并且咱们会看到随着程序包含更多的像素,线条会变得愈来愈长。
经过完成全部的90°角的旋转,咱们获得了完美的正方形。
旋转的海龟
让咱们看看当修改了程序中某一个数值的时候,会发生什么?学习和程序相关的新知识的一种方法是,当咱们修改其某一个部分的时候,看看发生了什么。咱们不会老是获得一个很好的结果,可是,即便是某些地方出错的时候,咱们也能学到东西。
咱们只是将程序的最后一行修改成t.left(91),将其保存为SquareSpiral2.py。
SquareSpiral2.py
-
import turtle
-
t = turtle.Pen()
-
for x in range(100):
-
t .forward(x)
-
t .left(91)
咱们提到了向左转90°会建立一个完美的正方形。每次向左转的比90°多一点点的话(在这个例子中,是91°),会将正方形略微向外抛出一点点。因为咱们进行下一次旋转的时候,已经偏离了一点点,随着程序继续进行,新的图形愈来愈不像是一个正方形。实际上,它建立了一个开始向左旋转的、漂亮的螺旋形,就像是楼梯同样,如图2-2所示。
图2-2 正方形螺旋线程序略做修改后变成了一个螺旋形的楼梯
这也是一个漂亮的图形,能够帮助咱们理解如何只略微修改一个数字,就显著地改变程序的结果。1°彷佛并非一个很大的误差,除非咱们偏离1° 100次(这加起来就是100°),或者1000次,或者,若是咱们使用的是飞机着陆程序……
若是还不知道度是如何工做的,如今先不要担忧,咱们只要尝试修改数字,看看发生了什么就行了。咱们经过修改range后面的圆括号中的值,让程序绘制的线条数达到200或500,或者50。
咱们再尝试将最后一行的角度修改成9一、4六、61或121等。记住每次都保存程序,而后,咱们运行它,看看所作的修改会如何影响到程序的绘制。年龄大一点的读者了解一些几何知识,可能会根据不一样的角度看到一些熟悉的形状,甚至可以在程序运行以前根据角度来预测出形状。较小的读者则只可以感觉修改带来的变化,等他们某一天上了几何课以后,能够再回头来看这个练习。
海龟画圆
说到几何,海龟做图能够绘制不少有趣的形状,而不仅是直线。咱们将在2.4节中再次回到正方形,但如今,让咱们来更多地了解一下Python Turtle库。
咱们再来修改一行代码:t.forward(x)。咱们在前面看到了这条命令或函数,它将海龟的钢笔向前移动x个像素而且绘制一条笔直的线段;而后,海龟转向而且再次绘制。若是咱们修改这行代码来绘制更为复杂一点的图形,例如圆,那会怎么样呢?
好在,绘制一个固定大小(或半径)的圆的命令,和绘制一条直线的命令同样简单。咱们将t.forward(x)修改成t.circle(x),以下面的代码所示。
CircleSpiral1.py
-
import turtle
-
t = turtle.Pen()
-
for x in range(100):
-
t .circle(x)
-
t .left(91)
哦,将一条命令从t.forward修改成t.circle,会获得一个复杂得多的形状,如图2-3所示。t.circle(x)函数让程序在当前位置绘制了一个半径为x的圆。注意,这个绘制和简单的正方形螺旋线有一些相同点:它也有4组圆形的螺旋线,就像是正方形的螺旋线有4个边同样。这是由于咱们使用t.left(91)命令,每次向左旋转都将超过90°一点点。若是咱们学习过几何就知道,围绕一个点转一圈有360°,就像是一个正方形有4个90°的角(4×90 = 360)。海龟经过每次围绕图形旋转的比90°多一点点,从而绘制出这个螺旋线的形状。
图2-3 只需在改动一点就获得一组漂亮的4个螺旋线的圆
咱们将会看到的一个区别是,圆形螺旋线比正方形螺旋线要大一些,实际上,大约是前者两倍那么大。这是由于t.circle(x)使用x做为圆的半径,而这是从圆心到边缘的距离,大概是圆的宽度的一半。
半径为x意味着,圆的直径,也就是说总的宽度是x的两倍。换句话说,t.circle(x)绘制的圆,当x等于1的时候,总宽度为2个像素;当x为2的时候总宽度为4个像素;按照这种方式,直到x等于99的时候,其宽度为198个像素。这几乎是200个像素宽了,或者说是正方形边最大的时候的两倍,所以,圆螺旋线看上去是正方形螺旋线的两倍的大小,固然,也会加倍的酷!
添加颜色
这些螺旋线的形状不错,可是,若是它们可以更多彩一些,是否是更酷呢?让咱们回到正方形螺旋线代码,在t = turtle.Pen()这一行的后面再添加一行代码,从而将钢笔颜色设置为红色。
SquareSpiral3.py
-
import turtle
-
t = turtle.Pen()
-
t .pencolor(“red”)
-
for x in range(100):
-
t .forward(x)
-
t .left(91)
运行该程序,咱们将会看到正方形螺旋线的一个更多色彩的版本,如图2-4所示。
图2-4 正方形螺旋线变得更多彩一些了
咱们尝试用另外一种经常使用的颜色(如“blue”或“green”)来替换掉“red”或“green”而且再次运行该程序。咱们能够经过Turtle库使用数百种不一样的颜色,包括一些奇怪的颜色,如“salmon”和“lemon chiffon”(访问http://www.tcl.tk/man/tcl8.4/TkCmd/colors.htm能够查看完整的列表)。让整个螺旋线呈现一种不一样的颜色是很不错的一步,可是,若是想要让每一边都显示一种不一样的颜色,咱们该怎么办呢?这须要对程序作一些更多的修改。
一个四色螺旋线
让咱们来考虑一下算法(algorithm)。算法就是一系列的步骤,它能够将单色的螺旋线变为4色的螺旋线。大多数的步骤和以前的螺旋线程序中相同,可是,这里还增长了一些调整:
(1)导入turtle模块而且设置一个海龟;
(2)告诉计算机应该使用何种颜色;
(3)设置一个循环,绘制螺旋线中的100条线段;
(4)为螺旋线的每一边选取一种不一样的钢笔颜色;
(5)向前移动海龟以绘制每一边;
(6)将海龟向左转,以准备好绘制下一边。
首先,咱们须要颜色名称的一个列表,而不是单个的颜色,所以,咱们要建立一个名为colors的列表变量而且在列表中放置4种颜色,以下所示。
colors = [“red”, “yellow”, “blue”, “green”]
这个4种颜色的列表,将会针对正方形的每一边给出一种颜色。注意,咱们将颜色的列表放在了方括号“[”和“]”之间。这里要确保引号中的每一种颜色名都像咱们在第1章中打印出来的单词同样,由于这些颜色名都是字符串(string)或文本值,这是咱们稍后要传递给pencolor函数的值。正如前面所提到的,咱们使用一个名为colors的变量来存储4种颜色的列表。所以,任什么时候候,当想要从列表中获取颜色的时候,咱们都要使用colors变量来表示钢笔的颜色。记住,变量存储的值是变化的,这正如同其名称同样,变量嘛。
咱们须要作的下一件事情是,每次遍历绘制循环的时候修改钢笔颜色。为了作到这一点,咱们须要将t.pencolor()函数移入到for循环下的一组指令之中,还须要告诉pencolor函数,咱们想要使用列表中的哪种颜色。
咱们输入以下的代码并运行它。
ColorSquareSpiral.py
-
import turtle
-
t = turtle.Pen()
-
colors = [“red”, “yellow”, “blue”, “green”]
-
for x in range(100):
-
t .pencolor(colors[x%4])
-
t .forward(x)
-
t .left(91)
4种颜色的列表起做用了,咱们在这个运行的示例中看到了它们(如图2-5所示)。到目前为止,一切还不错。
图2-5 正方形螺旋线程序的一个更加多彩的版本
pencolor函数中惟一的新增部分是(colors[x%4])。这条语句中的x和咱们在程序中其余地方所使用的x是同一个变量,所以,x将持续从0~99增长,就像咱们前面所见到的那样。圆括号中的colors变量名告诉Python,从咱们在程序前面所添加的、名为colors的颜色名称列表中选取一种颜色。
[x%4]告诉Python咱们将使用colors列表中的前4种颜色,即编号从0~3的颜色而且每当x变化的时候就遍历它们。在这个例子中,咱们的颜色列表只有4种颜色,所以,咱们须要一次又一次地遍历这4种颜色。
-
colors = [“red”, “yellow”, “blue”, “green”]
-
0 1 2 3
[x%4]中的“%”叫做模除操做符(modulo operator),表示一次除法运算中的余数(remainder)(5÷4商1余1,所以,5能够包含4一次而且还剩下1;6÷4余2,以此类推)。当咱们想要遍历列表中必定数目的项时,例如咱们对4种颜色列表所作的操做,模除操做符颇有用。
在100步中,colors[x%4]将遍历4种颜色(0、一、2和3,分别表示红色、黄色、蓝色和绿色)整整25次。若是咱们有时间(而且有一个放大镜),能够数一数图2-5中有25条红色的、25条黄色的、25条蓝色的和25条绿色的线段。第1次遍历绘制循环的时候,Python使用列表中的第一种颜色,红色;第2次遍历的时候,它使用黄色,以此类推。第15次遍历循环的时候,Python又回过头来使用红色,而后是黄色,等等;每经过循环4次以后,老是又回过头来使用红色。
修改背景颜色
让咱们再次加入一点内容,创造出比图2-5更漂亮一些的内容。正如我5岁的儿子Alex所指出来的那样,黄色部分太难以识别出来了。这就像是在白色的绘画纸上使用黄色的蜡笔同样,屏幕上的黄色像素没法在白色背景上明显地显示出来。让咱们把背景颜色修改成黑色,来修正这个问题。咱们在程序中的import行以后的任何位置,输入以下的代码行。
turtle.bgcolor(“black”)
添加这一行以后,图片更加漂亮,全部的颜色如今都处在一个黑色的背景之上。注意,海龟钢笔(在程序中由变量t表示)没有任何变化。相反,咱们修改了海龟屏幕的一些内容,也就是背景颜色。turtle.bgcolor()命令容许咱们将整个绘制屏幕修改成Python中指定的任何颜色。在turtle.bgcolor(“black”)这一行中,咱们选择了黑色做为屏幕颜色,所以,红色、黄色、蓝色和绿色都显示得很好。
此外,咱们能够将循环中的range()修改成200甚至更大,以使得螺旋线中的正方形更大。在黑色背景上显示200个线段的新版本的图片,如图2-6
所示。
图2-6 螺旋线程序的路还很长(这是一个简单的开始)
Alex老是想帮助个人程序变得更为惊人,他要求再作一项修改:若是如今把线段替换为圆,那会怎么样呢?那会不会是最酷的图片呢?好吧,我必须认可,这甚至会更酷。完整的代码以下所示。
ColorCircleSpiral.py
-
import turtle
-
t = turtle.Pen()
-
turtle .bgcolor(“black”)
-
colors = [“red”, “yellow”, “blue”, “green”]
-
for x in range(100):
-
t .pencolor(colors[x%4])
-
t .circle(x)
-
t .left(91)
咱们能够在图2-7中看到结果。
图2-7 Alex的惊人的圆螺旋线— 一共8行代码,简单而优雅
一个变量搞定一切
到目前为止,咱们已经使用变量来修改颜色、大小以及螺旋线形状的旋转角度。让咱们再添加一个sides变量,来表示形状的边数。这个新的变量如何改变咱们的螺旋线呢?若是要搞清楚这一点,咱们尝试这个新的程序ColorSpiral.py。
ColorSpiral.py
-
import turtle
-
t = turtle.Pen()
-
turtle .bgcolor(“black”)
-
# You can choose between 2 and 6 sides for some cool shapes!
-
sides = 6
-
colors = [“red”, “yellow”, “blue”, “orange”, “green”, “purple”]
-
for x in range(360):
-
t .pencolor(colors[x%sides])
-
t .forward(x * 3/sides + x)
-
t .left(360/sides + 1)
-
t .width(x*sides/200)
咱们能够将sides的值从6改成2(1个边并非颇有趣,也不能使用太大的数字,除非咱们在程序的第6行中的列表中,添加更多的颜色),而后保存该程序而且能够运行任意屡次。图2-8展现了用sides=六、sides=5,一直到sides=2所建立的图像,其中sides=2的图像很奇怪,这就是图2-8(e)所显示的扁平的螺旋线。咱们能够改变列表中的颜色的顺序,也能够在绘制循环之中的任意函数中,使用较大一些或较小一点的数字。若是把程序给搞乱了,咱们只须要返回到最初的ColorSpiral.py程序从新来玩就行了。
a)
b)
c)
d)
e)
图2-8 经过把变量sides从6(a)修改成2(e)所建立的5种彩色的形状
ColorSpiral.py程序使用了一条新的命令t.width(),它修改了海龟钢笔的宽度。在咱们的程序中,随着钢笔绘制的形状愈来愈大,钢笔变得愈来愈宽(其线条变得更粗)。在第3章和第4章,咱们学习建立程序所需的其余技能的时候,还会再次遇到这个程序以及其余相似的程序。
本章小结
在本章中,咱们使用Turtle库的工具绘制了使人印象深入的彩色形状。咱们使用import命令把这个库导入到本身的程序中,同时了解到,以这种方式来重用代码是编程的最强大的功能之一。一旦编写了有用的内容,或者借用某些人慷慨分享的代码,咱们不只可以、节省时间,并且可以使用这些导入的代码作全新的事情。
咱们还介绍了程序中像x和sides这样的变量。这些变量存储或记住一个数字或值,以便咱们可以在程序中屡次使用它,甚至修改其值。在第3章中,咱们将学习变量的做用以及Python如何可以帮助你完成数学做业。
如今,咱们应该可以作以下这些事情:
-
用Turtle库绘制简单的图形;
-
使用变量来存储简单的数值和字符串;
-
在IDLE中修改、保存和运行程序。
编程挑战
尝试这些挑战以练习咱们在本章中所学习的知识(若是遇到困难,能够访问http://www.nostarch.com/teachkids/寻找示例解答)。
#1:修改边数
在ColorSpiral.py程序中,咱们使用了一个变量sides,可是咱们并无改变它或修改其值,只是再次编辑、保存和运行程序。咱们尝试将sides的值改成另外一个数字,例如5,保存并运行程序,看看这会对绘制有何影响;如今,试一试四、三、2甚至是1。如今,咱们在程序的第6行,向颜色列表中添加两种或更多的颜色,颜色名用引号括起来,用逗号隔开。咱们能够增长sides的值,来使用这些新的颜色,尝试一下8或者10甚至更大。
#2:有多少边
若是想要在程序运行的时候由用户来决定边数,咱们该怎么作呢?使用咱们在第1章中学习的内容,可让用户输入边数而且将其存储到sides变量中。惟一额外的步骤是,计算(evaluate)用户所输入的数字。咱们可使用eval()函数获得用户输入的数字,以下所示。
sides = eval(input(“Enter a number of sides between 2 and 6: “))
咱们使用前面这一行,替换掉ColorSpiral.py中的sides = 6这一行。新的程序将会问用户想要看到有多少个边。而后,程序将绘制用户所要求的形状。尝试一下!
#3:橡皮筋球体
咱们尝试将ColorSpiral.py程序修改成一个更大的角度,并且经过在绘制循环的末尾添加一个额外的转向来扭曲形状。咱们在for循环的末尾添加诸如t.left(90)的一行,使得角度更加尖锐(记住缩进,或者说留下空格,以保证该语句位于循环之中)。结果如图2-9所示,看上去像是一个几何玩具,或者是用彩色的橡皮筋制做的球体。
图2-9 在ColorSpiral.py程序的每一轮循环中添加一个额外的90°将其变为RubberBandBall.py程序
咱们把这个新的版本保存为RubberBandBall.py,或者访问http://www.nostarch.com/teachkids/而且在Chapter2的源代码中找到该程序。
[1] Logo编程语言建立于1967年,这是一种教育编程语言,在50年以后的今天,它仍然用来教授基本的编程。这很酷,是否是?
[2] 小读者可能会把x看成未知数,就像当他们求解x + 4 = 6以求得未知的x同样。年龄大一点的读者可能会经过代数课或其余的数学课程认识x,早期的程序员正是从代数和数学中借用了变量的概念。编写代码的过程当中会有不少数学的典型例子,咱们甚至会在后面见到一些很酷的几何示例。