海龟作图—⽤Python绘图
在本章中,我们将编写简短的、简单的程序来创建漂亮的、复杂的视觉效果。为了做到这⼀点,我们可以使⽤海龟作图软件。在海龟作图中,我们可以编写指令让⼀个虚拟的(想象中的)海龟在屏幕上来回移动。这个海龟带着⼀只钢笔,我们可以让海龟⽆论移动到哪都使⽤这只钢笔来绘制线条。通过编写代码,以各种很酷的模式移动海龟,我们可以绘制出令⼈惊奇的图⽚。
使⽤海龟作图,我们不仅能够只⽤⼏⾏代码就创建出令⼈印象深刻的视觉效果,⽽且还可以跟随海龟看看每⾏代码如何影响到它的移动。这能够帮助我们理解代码的逻辑。
2.1 第⼀个海龟程序
SquareSpiral1.py
python代码画图案# SquareSpiral1.py - Draws a square spiral
import turtle
t = turtle.Pen()
for x in range(100):
t.forward(x)
免费编程软件下载 t.left(90)
当运⾏这段代码的时候,我们会得到⼀幅漂亮整齐的图⽚(如图2-1所⽰)。
tyktc02_01.psd
图2-1 ⽤简短的SquareSpiral1.py程序创建的⼀个炫⽬的正⽅形螺旋线
2.1.1 程序是如何⼯作的
让我们⼀⾏⼀⾏地分析这个程序,看看它是如何⼯作的。SquareSpiral1.py的第1⾏是注释。正如我们在第1章中所学过的,注释以⼀个井号(#)开头。注释允许我们在程序中写⼊给⾃⼰或以后可能阅读该程序的其他⼈⼀些提⽰。计算机不会阅读或试图理解井号之后的任何内容;注释只是让我们写出关于程序是做什么的⼀些说明。在这个例⼦中,我们将程序的名称以及针对其做什么的⼀个简单说明放⼊到注释之中。
第2⾏导⼊(import)了绘制海龟图形的功能。导⼊已经编写过的代码,这是编程⼯作的最酷的事情之⼀。如果我们编写了⼀些有趣并有⽤的程序,可以将其与其他的⼈分享,同时也可以⾃⼰重⽤它。尽
管海龟作图最初源⾃20世纪60年代的Logo编程语⾔,但⼀些很酷的Python程序员构建了⼀个库(library,库就是可以重⽤的代码的⼀个集合),来帮助其他程序员在Python中使⽤海龟作图。当我们输⼊了import turtle,就表⽰我们的程序能够使⽤那些Python程序员所编写的代码。图2-1中的⼩的⿊⾊箭头表⽰海龟,它在屏幕上移动的时候会使⽤钢笔绘图。
11486.png
程序的第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)(在第1章中的YourName.py程序中,name就是变量)。变量存储了在程序进
⾏的过程中可以修改(变化)的⼀个值。我们在所编写的⼏乎每⼀个程序中,都要使⽤变量,因此,早点认识变量为好。
接下来的两⾏代码缩进了,或者说,在左边留出了空格。这意味着,它们位于该循环之中(in the loop)并且和上⾯的那⼀⾏代码⼀起,每次x从0~99的范围中获取⼀个新的数字的时候,这些代码⾏都会重复,直到达到100次。
2.1.2 发⽣了什么
让我们看看Python初次读取这⼀组指令的时候发⽣了什么。命令t.forward(x)让海龟的钢笔在屏幕上向前移动x个点。因为x是0,钢笔根本不会移动。最后⼀⾏代码t.left(90)让海龟向左转90°,或者说转四分之⼀个圈。
11511.png
由于这个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°⾓的旋转,我们得到了完美的正⽅形。
2.2 旋转的海龟
让我们看看当修改了程序中某⼀个数值的时候,会发⽣什么?学习和程序相关的新知识的⼀种⽅法是,当我们修改其某⼀个部分的时候,看看发⽣了什么。我们不会总是得到⼀个很好的结果,但是,即使是某些地⽅出错的时候,我们也能学到东西。
我们只是将程序的最后⼀⾏修改为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所⽰。
tyktc02_02.psd
图2-2 正⽅形螺旋线程序略作修改后变成了⼀个螺旋形的楼梯java为什么安装不了
这也是⼀个漂亮的图形,可以帮助我们理解如何只略微修改⼀个数字,就显著地改变程序的结果。1°似乎并不是⼀个很⼤的偏差,除⾮我们偏离1° 100次(这加起来就是100°),或者1000次,或者,如果我们使⽤的是飞机着陆程序……
11534.png
如果还不知道度是如何⼯作的,现在先不要担⼼,我们只要尝试修改数字,看看发⽣了什么就好了。我们通过修改range后⾯的圆括号中的值,让程序绘制的线条数达到200或500,或者50。
我们再尝试将最后⼀⾏的⾓度修改为91、46、61或121等。记住每次都保存程序,然后,我们运⾏它,看看所做的修改会如何影响到程序的绘制。年龄⼤⼀点的读者了解⼀些⼏何知识,可能会根据不同的⾓度看到⼀些熟悉的形状,甚⾄能够在程序运⾏之前根据⾓度来预测出形状。较⼩的读者则只能够感受修改带来的变化,等他们某⼀天上了⼏何课之后,可以再回头来看这个练习。
2.3 海龟画圆
说到⼏何,海龟作图可以绘制很多有趣的形状,⽽不只是直线。我们将在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°多⼀点点,从⽽绘制出这个螺旋线的形状。
tyktc02_03.psd
图2-3 只需在改动⼀点就得到⼀组漂亮的4个螺旋线的圆
我们将会看到的⼀个区别是,圆形螺旋线⽐正⽅形螺旋线要⼤⼀些,实际上,⼤约是前者两倍那么⼤。这是因为t.circle(x)使⽤x作为圆的半径,⽽这是从圆⼼到边缘的距离,⼤概是圆的宽度的⼀半。
半径为x意味着,圆的直径,也就是说总的宽度是x的两倍。换句话说,t.circle(x)绘制的圆,当x等于1的时候,总宽度为2个像素;当x为2的时候总宽度为4个像素;按照这种⽅式,直到x等于99的时候,其宽度为198个像素。这⼏乎是200个像素宽了,或者说是正⽅形边最⼤的时候的两倍,因此,圆螺旋线看上去是正⽅形螺旋线的两倍的⼤⼩,当然,也会加倍的酷!
2.4 添加颜⾊
这些螺旋线的形状不错,但是,如果它们能够更多彩⼀些,是不是更酷呢?让我们回到正⽅形螺旋线代码,在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所⽰。
tyktc02_04.psd
图2-4 正⽅形螺旋线变得更多彩⼀些了
2.4.1 ⼀个四⾊螺旋线
让我们来考虑⼀下算法(algorithm)。算法就是⼀系列的步骤,它可以将单⾊的螺旋线变为4⾊的螺旋线。⼤多数的步骤和之前的螺旋线程序中相同,但是,这⾥还增加了⼀些调整:
(1)导⼊turtle模块并且设置⼀个海龟;
(2)告诉计算机应该使⽤何种颜⾊;
(3)设置⼀个循环,绘制螺旋线中的100条线段;
(4)为螺旋线的每⼀边选取⼀种不同的钢笔颜⾊;
(5)向前移动海龟以绘制每⼀边;
(6)将海龟向左转,以准备好绘制下⼀边。
⾸先,我们需要颜⾊名称的⼀个列表,⽽不是单个的颜⾊,因此,我们要创建⼀个名为colors的列表变量并且在列表中放置4种颜⾊,如下所⽰。
colors = [“red”, “yellow”, “blue”, “green”]
这个4种颜⾊的列表,将会针对正⽅形的每⼀边给出⼀种颜⾊。注意,我们将颜⾊的列表放在了⽅括号“[”和“]”之间。这⾥要确保引号中的每⼀种颜⾊名都像我们在第1章中打印出来的单词⼀样,因为这些颜⾊名都是字符串(string)或⽂本值,这是我们稍后要传递给pencolor函数的值。正如前⾯所提到的,我们使⽤⼀个名为colors的变量来存储4种颜⾊的列表。因此,任何时候,当想要从列表中获取颜⾊的时候,我们都要使⽤colors变量来表⽰钢笔的颜⾊。记住,变量存储的值是变化的,这正如同其名称⼀样,变量嘛。
11558.png
我们需要做的下⼀件事情是,每次遍历绘制循环的时候修改钢笔颜⾊。为了做到这⼀点,我们需要将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)
ui设计培训班学费t.left(91)
4种颜⾊的列表起作⽤了,我们在这个运⾏的⽰例中看到了它们(如图2-5所⽰)。到⽬前为⽌,⼀切还不错。
tyktc02_05.psd
java多线程join方法图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、1、2和3,分别表⽰红⾊、黄⾊、蓝⾊和绿⾊)整整25次。如果我们有时间(并且有⼀个放⼤镜),可以数⼀数图2-5中有25条红⾊的、25条黄⾊的、25条蓝⾊的和25条绿⾊的线段。第1次遍历绘制循环的时候,Python使⽤列表中的第⼀种颜⾊,红⾊;第2次遍历的时候,它使⽤黄⾊,以此类推。第15次遍历循环的时候,Python⼜回过头来使⽤红⾊,然后是黄⾊,等等;每通过循环4次之后,总是⼜回过头来使⽤红⾊。
11842.png
2.4.2 修改背景颜⾊
让我们再次加⼊⼀点内容,创造出⽐图2-5更漂亮⼀些的内容。正如我5岁的⼉⼦Alex所指出来的那样,黄⾊部分太难以识别出来了。这就像是在⽩⾊的绘画纸上使⽤黄⾊的蜡笔⼀样,屏幕上的黄⾊像素⽆法在⽩⾊背景上明显地显⽰出来。让我们把背景颜⾊修改为⿊⾊,来修正这个问题。我们在程序中的import⾏之后的任何位置,输⼊如下的代码⾏。
turtle.bgcolor(“black”)
添加这⼀⾏之后,图⽚更加漂亮,所有的颜⾊现在都处在⼀个⿊⾊的背景之上。注意,海龟钢笔(在程序中由变量t表⽰)没有任何变化。相反,我们修改了海龟屏幕的⼀些内容,也就是背景颜⾊。turtle.bgcolor()命令允许我们将整个绘制屏幕修改为Python中指定的任何颜⾊。在turtle.bgcolor(“black”)这⼀⾏中,我们选择了⿊⾊作为屏幕颜⾊,因此,红⾊、黄⾊、蓝⾊和绿⾊都显⽰得很好。
此外,我们可以将循环中的range()修改为200甚⾄更⼤,以使得螺旋线中的正⽅形更⼤。在⿊⾊背景上显⽰200个线段的新版本的图⽚,如图2-6
所⽰。
Fig2-6.psd
图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中看到结果。
Fig2-7.psd
score在python是什么意思图2-7 Alex的惊⼈的圆螺旋线— ⼀共8⾏代码,简单⽽优雅
2.5 ⼀个变量搞定⼀切
到⽬前为⽌,我们已经使⽤变量来修改颜⾊、⼤⼩以及螺旋线形状的旋转⾓度。让我们再添加⼀个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)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论