在本章中,咱們將編寫簡短的、簡單的程序來建立漂亮的、複雜的視覺效果。爲了作到這一點,咱們可使用海龜做圖軟件。在海龜做圖中,咱們能夠編寫指令讓一個虛擬的(想象中的)海龜在屏幕上來回移動。這個海龜帶着一隻鋼筆,咱們可讓海龜不管移動到哪都使用這隻鋼筆來繪製線條。經過編寫代碼,以各類很酷的模式移動海龜,咱們能夠繪製出使人驚奇的圖片。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,早期的程序員正是從代數和數學中借用了變量的概念。編寫代碼的過程當中會有不少數學的典型例子,咱們甚至會在後面見到一些很酷的幾何示例。