Upgrade to Pro — share decks privately, control downloads, hide ads and more …

turtledemo002

Renyuan Lyu
November 26, 2014

 turtledemo002

draft of turtledemo's documentation

Renyuan Lyu

November 26, 2014
Tweet

More Decks by Renyuan Lyu

Other Decks in Education

Transcript

  1. 01.bytedesign.py 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 A B #!/usr/bin/env python3 """ turtle-example-suite: tdemo_bytedesign.py An example adapted from the example-suite of PythonCard's turtle graphics. It's based on an article in BYTE magazine Problem Solving with Logo: Using Turtle Graphics to Redraw a Design November 1982, p. 118 - 134 ------------------------------------------- Due to the statement t.delay(0) in line 152, which sets the animation delay to 0, this animation runs in "line per line" mode as fast as possible. """ import math 引入 math 【數學】 模組 from turtle import Turtle, mainloop 從 turtle 【龜】 模組 引入 Turtle 【龜類】 物類,mainloop 【主迴圈】 函數。 from time import clock 從 time 【時間】 模組 引入 clock 【鐘】 物類。 # wrapper for any additional drawing routines # that need to know about each other 1
  2. 01.bytedesign.py 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 A B class Designer(Turtle): 定義 class 【物類】,名為 Designer 【設計師類】,繼承 Turtle 【龜類】。 def design(self, homePos, scale): 定義 design 【設計】 類函數(方法),傳入 self, homePos, scale。分別是 物件本身 (自我),設計圖所在中心位置 (家位置),以及設計圖之縮放比例。 self.up() 首先,自我(是一個設計師,又繼承了龜類) 提起筆來,如此行動時才不會留下 不想要的軌跡。 for i in range(5): 在此設定將要執行迴圈 5 次。 self.forward(64.65 * scale) 自我 前進 64.65 (說明時暫時忽略【比例】) self.down() 自我在此下筆。 self.wheel(self.position(), scale) 自我 呼叫 輪子 出來 幫忙畫圖,在當下的位置。 self.up() 自我 提筆。 self.backward(64.65 * scale) 自我後退 64.65。 self.right(72) 自我右轉 72 度。 self.up() 自我 提筆。 self.goto(homePos) 自我 前往 (家位置) self.right(36) 自我右轉 36 度。 self.forward(24.5 * scale) 自我 前進 24.5 self.right(198) 自我右轉 198 度。 self.down() 自我在此下筆。 self.centerpiece(46 * scale, 143.4, scale) 自我 呼叫 centerpiece 【中央塊】出來 幫忙畫圖,傳入邊長 46,角度 143.5。 self.getscreen().tracer(True ) 自我 取得 所在的螢幕,並設定追蹤器為開啟(True)狀態。 def wheel(self, initpos, scale): 定義 wheel 【輪子】 類函數(方法),傳入 self, initpos, scale。 self.right(54) for i in range(4): self.pentpiece(initpos, scale) self.down() self.left(36) for i in range(5): self.tripiece(initpos, scale) 2
  3. 01.bytedesign.py 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 A B self.left(36) for i in range(5): self.down() self.right(72) self.forward(28 * scale) self.up() self.backward(28 * scale) self.left(54) self.getscreen().update() def tripiece(self, initpos, scale): 定義 tripiece 【三角塊】 類函數(方法),傳入 self, initpos, scale。 oldh = self.heading() self.down() self.backward(2.5 * scale) self.tripolyr(31.5 * scale, scale) self.up() self.goto(initpos) self.setheading(oldh) self.down() self.backward(2.5 * scale) self.tripolyl(31.5 * scale, scale) self.up() self.goto(initpos) self.setheading(oldh) self.left(72) self.getscreen().update() def pentpiece(self, initpos, scale): 定義 pentpiece 【五角塊】 類函數(方法),傳入 self, initpos, scale。 oldh = self.heading() self.up() 3
  4. 01.bytedesign.py 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 A B self.forward(29 * scale) self.down() for i in range(5): self.forward(18 * scale) self.right(72) self.pentr(18 * scale, 75, scale) self.up() self.goto(initpos) self.setheading(oldh) self.forward(29 * scale) self.down() for i in range(5): self.forward(18 * scale) self.right(72) self.pentl(18 * scale, 75, scale) self.up() self.goto(initpos) self.setheading(oldh) self.left(72) self.getscreen().update() def pentl(self, side, ang, scale): 定義 pentl 【左五角】 類函數(方法),傳入 self, side, ang, scale。 if side < (2 * scale): return self.forward(side) self.left(ang) self.pentl(side - (.38 * scale), ang, scale) def pentr(self, side, ang, scale): 定義 pentr 【右五角】 類函數(方法),傳入 self, side, ang, scale。 if side < (2 * scale): return self.forward(side) 4
  5. 01.bytedesign.py 119 120 121 122 123 124 125 126 127

    128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 A B self.right(ang) self.pentr(side - (.38 * scale), ang, scale) def tripolyr(self, side, scale): 定義 tripolyr 【右三角】 類函數(方法),傳入 self, side, scale。 if side < (4 * scale): return self.forward(side) self.right(111) self.forward(side / 1.78) self.right(111) self.forward(side / 1.3) self.right(146) self.tripolyr(side * .75, scale) def tripolyl(self, side, scale): 定義 tripolyl 【左三角】 類函數(方法),傳入 self, side, scale。 if side < (4 * scale): return self.forward(side) self.left(111) self.forward(side / 1.78) self.left(111) self.forward(side / 1.3) self.left(146) self.tripolyl(side * .75, scale) def centerpiece(self, s, a, scale): 定義 centerpiece 【中央塊】 類函數(方法),傳入 self, s, a, scale。 self.forward(s); self.left(a) if s < (7.5 * scale): return self.centerpiece(s - (1.2 * scale), a, scale) def main(): 定義 main 【主要】 函數,將包含本程式之主要流程。 5
  6. 01.bytedesign.py 149 150 151 152 153 154 155 156 157

    158 159 160 161 162 A B t = Designer() 呼叫 Designer 物類,製造一個 物件,名為 t。 t.speed(0) 由於 Designer 繼承 Turtle 因此 t 擁有一切 Turtle 的 方法。t.speed() 設定 t 行動之 速度,傳入 0代表最快的速度。 t.hideturtle() 隱藏 t 之形狀。 t.getscreen().delay(0) t 取得 自身所在的螢幕,並設定螢幕延遲為 0 。 t.getscreen().tracer(0) t 取得 自身所在的螢幕,並設定螢幕追蹤為 0 。 at = clock() 利用 clock 函數,取得當下時間。並記下來存在 at 變數裡。 t.design(t.position(), 2) t 呼叫自身的方法 design,傳入當前自己所在的位置,設定 比例=2,傳入。啟動 本程式最主要的任務執行,畫出複雜的設計圖。 et = clock() 利用 clock 函數,取得當下時間。並記下來存在 et 變數裡。 return "runtime: %.2f sec." % (et-at) 計算畫設計圖所需時間 (et-at),回傳出 main 函數之外,由其他呼叫main函數者 運用。 if __name__ == '__main__': 這一行經常被使用,它偵測當前這個 python 程式是否自己被當成主程式由 python 直譯器直接呼叫,還是被當成模組由其他 python 程式呼叫。若是當自己 被當成主程式,則 一個特殊變數名為 __name__ 其值會等於 字串 '__main__',因 此接下來 3 行將會被執行。 msg = main() 這一行直接呼叫 main() 函數,定義在 行號 148 處,為本程式的主要執行流程。 print(msg) 印出 main() 執行後產生的訊息,在此為 執行本程式畫設計圖所需的時間。 mainloop() 這個 mainloop() 代表系統將進入使用者圖形介面的無線迴圈狀態,程式開始等 待使用者運用滑鼠或鍵盤來操控它。 6
  7. 02.chaos.py 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 A B C D E F G H # File: tdemo_chaos.py # Author: Gregor Lingl # Date: 2009-06-24 # A demonstration of chaos from turtle import * N = 80 def f(x): 定義 f 函數 return 3.9*x*(1-x) def g(x): 定義 g 函數 return 3.9*(x-x**2) def h(x): 定義 h 函數 return 3.9*x-3.9*x*x def jumpto(x, y): 跳到 (x,y) 座標。 penup(); goto(x,y) def line(x1, y1, x2, y2): 畫直線。 jumpto(x1, y1) pendown() goto(x2, y2) def coosys(): 畫座標直線。 line(-1, 0, N+1, 0) line(0, -0.1, 0, 1.1) 7
  8. 02.chaos.py 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 A B C D E F G H def plot(fun, start, colour): 畫函數圖,傳入函數名 fun,函數x 座標起點 start,以及線圖之顏色 colour。 pencolor(colour) x = start 設 x 為 起點 jumpto(0, x) 把 x 設為縱座標,跳到 (0, x) pendown() 下筆。 dot(5) 畫點。 for i in range(N): x=fun(x) goto(i+1,x) dot(5) def main(): reset() 重設龜圖螢幕 setworldcoordinates(-1.0,-0.1, N+1, 1.1) 設定龜圖座標世界 speed(0) 設定龜速度,0為最快。 hideturtle() 龜隱身。 coosys() plot(f, 0.35, "blue") 畫 f 函數,藍色。 plot(g, 0.35, "green") 畫 g 函數,綠色。 plot(h, 0.35, "red") 畫 h 函數,紅色。 # Now zoom in: for s in range(100): 執行迴圈100次 setworldcoordinates(0.5*s,-0.1, N+1, 1.1) 重新設定龜圖座標世界。 return "Done!" if __name__ == "__main__": main() mainloop() 8
  9. 03.clock.py 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 A B #!/usr/bin/env python3 # -*- coding: cp1252 -*- """ turtle-example-suite: tdemo_clock.py Enhanced clock-program, showing date and time ------------------------------------ Press STOP to exit the program! ------------------------------------ """ from turtle import * from datetime import datetime def jump(distanz, winkel=0): 定義 跳(距離, 角度): penup() right(winkel) forward(distanz) left(winkel) pendown() 定義 畫指針(長度, 大小): def hand(laenge, spitze): fd(laenge*1.15) rt(90) fd(spitze/2.0) lt(120) fd(spitze) lt(120) fd(spitze) 9
  10. 03.clock.py 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 A B lt(120) fd(spitze/2.0) def make_hand_shape(name, laenge, spitze): 定義 造指針形狀(名稱, 長度, 大小): reset() jump(-laenge*0.15) begin_poly() 開始記錄多邊形() hand(laenge, spitze) 畫指針() end_poly() 結束記錄多邊形() hand_form = get_poly() 指針形= 取多邊形() register_shape(name, hand_form) 註冊形狀(名稱, 指針形) def clockface(radius): 定義 畫鐘面(半徑): reset() pensize(7) for i in range(60): jump(radius) if i % 5 == 0: fd(25) jump(-radius-25) else : dot(3) jump(-radius) rt(6) def setup(): 定義 設立 函數,目的為設立整個程式的畫面,包括鐘面、指針等等。 global second_hand, minute_hand, hour_hand, writer mode("logo") 設定繪圖模式為頭向北角度射為0,順時針方向為正。 make_hand_shape("second_hand", 125, 25) 造指針形狀,名為「秒針」("second_hand"),長度為 125,(針頭)大小為 25 make_hand_shape("minute_hand", 130, 25) 造指針形狀,名為「分針」("minute_hand"),長度為 130,(針頭)大小為 25 10
  11. 03.clock.py 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 A B make_hand_shape("hour_hand", 90, 25) 造指針形狀,名為「時針」("hour_hand"),長度為 90,(針頭)大小為 25 clockface(160) 畫鐘面,半徑為 160,會用到上述 3 個指針形狀。 second_hand = Turtle() 由龜類(Turtle) 造一隻龜,名為 秒針 (second_hand) second_hand.shape("second_hand") 設定秒針(龜)的形狀為 「秒針」("second_hand") second_hand.color("gray20", "gray80") 設定秒針(龜)的顏色為 「灰」("gray") minute_hand = Turtle() 由龜類(Turtle) 造一隻龜,名為 分針 (minute_hand) minute_hand.shape("minute_hand") 設定分針(龜)的形狀為 「分針」("minute_hand") minute_hand.color("blue1", "red1") 設定分針(龜)的顏色為 「藍」「紅」("blue", "red") hour_hand = Turtle() 由龜類(Turtle) 造一隻龜,名為 時針 (hour_hand) hour_hand.shape("hour_hand") 設定時針(龜)的形狀為 「時針」("hour_hand") hour_hand.color("blue3", "red3") 設定時針(龜)的顏色為 「藍」「紅」("blue", "red") for hand in second_hand, minute_hand, hour_hand: 對所有3種指針,執行以下動作: hand.resizemode("user") 重設大小模式設為「使用者控制」("user") hand.shapesize(1, 1, 3) 重設指針形狀之大小 hand.speed(0) 設定指針(龜)移動速度為最快。 ht() 指針(龜)隱身。 writer = Turtle() 由龜類(Turtle) 造一隻龜,名為 寫手 (writer) #writer.mode("logo") writer.ht() 寫手 隱身 writer.pu() 寫手 提筆 writer.bk(85) 寫手 後退 def wochentag(t): 定義 星期之名稱: wochentag = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] return wochentag[t.weekday()] def datum(z): 定義 年月日期之名稱: monat = ["Jan.", "Feb.", "Mar.", "Apr.", "May", "June", "July", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."] 11
  12. 03.clock.py 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 A B j = z.year m = monat[z.month - 1] t = z.day return "%s %d %d" % (m, t, j) def tick(): 定義 鐘指針的移動 以及 持續移動: t = datetime.today() 取得當前時間資訊。 sekunde = t.second + t.microsecond*0.000001 計算 秒數 (sekunde)。 minute = t.minute + sekunde/60.0 計算 分數 (minute)。 stunde = t.hour + minute/60.0 計算 時數 (stunde)。 try : tracer(False ) # Terminator can occur here writer.clear() writer.home() writer.forward(65) writer.write(wochentag(t), 寫手(龜) 寫下 星期。 align="center", font=("Courier", 14, "bold")) writer.back(150) writer.write(datum(t), 寫手(龜) 寫下 年月日期。 align="center", font=("Courier", 14, "bold")) writer.forward(85) tracer(True ) second_hand.setheading(6*sekunde) # or here 秒針(龜)設頭向(),把 秒數 *6 當作 角度。 (360度/60秒 = 6度/秒) minute_hand.setheading(6*minute) 分針(龜)設頭向(),把 分數 *6 當作 角度。 (360度/60分 = 6度/分) hour_hand.setheading(30*stunde) 時針(龜)設頭向(),把 時數 *30 當作 角度。 (360度/12時 = 30度/時) tracer(True ) ontimer(tick, 100) 每隔 100 毫秒 (millisecond),計時器(ontimer) 呼叫 本函數(tick)一次,程 式在此進入無窮迴圈。 except Terminator: 直到外來的例外訊號 Terminator 被本程式捕獲為止。 pass # turtledemo user pressed STOP 12
  13. 03.clock.py 120 121 122 123 124 125 126 127 128

    129 130 131 132 A B def main(): 定義 主函數: tracer(False ) setup() 設立() tracer(True ) tick() 指針開始移動並持續() return "EVENTLOOP" if __name__ == "__main__": 若本程式被做為主程式執行,則: mode("logo") 設定繪圖之角度模式為 "logo"。 msg = main() 執行主程式。 print(msg) mainloop() 進入使用者介面主迴圈。 13
  14. 04.colormixer.py 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 A B # colormixer from turtle import Screen, Turtle, mainloop class ColorTurtle(Turtle): 定義物類 「顏色龜類」,繼承「龜類」。 def __init__(self, x, y): 定義 顏色龜類 的 誕生 方法,須指定 x,y 座標 Turtle.__init__(self) 這一行表示 「顏色龜類」 所繼承的「龜類」也要初始化 self.shape("turtle") self.resizemode("user") self.shapesize(3,3,5) self.pensize(10) self._color = [0,0,0] 顏色龜類自身的顏色屬性,用三維顏色列表 [x0, x1, x2] 來表示。 self.x = x 顏色龜類的x座標。 self._color[x] = y 顏色列表的 0, 1, 2位置分別代表 red, green, blue 的比重,由龜自身的 y 座標來設定。 self.color(self._color) .color(r,g,b),r,g,b 都介於 0,1之間,代表3種顏色成分的比重。 self.speed(0) self.left(90) self.pu() self.goto(x,0) self.pd() self.sety(1) self.pu() self.sety(y) self.pencolor("gray25") self.ondrag(self.shift) 當自身被滑鼠拖拉時,執行自身的 shift 方法,並自動把目前滑鼠之 (x, y)座標傳入 shift 方法中。 def shift(self, x, y): 定義 移動(shift)方法, 傳入 (x,y) 座標。 14
  15. 04.colormixer.py 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 A B self.sety(max(0,min(y,1))) 自身設定y座標 self._color[self.x] = self.ycor() 自身的顏色向量之x成分設為自身的 y 座標值,在此,x 為 0, 1 或 2, 恰對應 紅、綠、藍,y則為滑鼠拖拉出來的比重值。 self.fillcolor(self._color) 把自身用決定出來的顏色填滿。 setbgcolor() 也把背景填滿該顏色。 def setbgcolor(): screen.bgcolor(red.ycor(), green.ycor(), blue.ycor()) 螢幕的 背景色 ( bgcolor) 方法可用來設定螢幕的背景色。 def main(): global screen, red, green, blue screen = Screen() 由 幕類 (Screen)製造一個畫圖螢幕,名為 screen screen.delay(0) 設定螢幕之畫圖延遲時間為 0,這是最快的。 screen.setworldcoordinates(-1, -0.3, 3, 1.3) 設定使用者自訂的螢幕座標範圍,左下座標、右上座標。 red = ColorTurtle(0, .5) 由「顏色龜類」(ColorTurtle)製造一隻龜,名為 紅色(龜),red,放在 座標 (0, .5)處。 green = ColorTurtle(1, .5) 由「顏色龜類」(ColorTurtle)製造一隻龜,名為 綠色(龜),green,放 在座標 (1, .5)處。 blue = ColorTurtle(2, .5) 由「顏色龜類」(ColorTurtle)製造一隻龜,名為 藍色(龜),blue,放在 座標 (2, .5)處。 setbgcolor() 設定 背景顏色。 writer = Turtle() 由 龜類 (Turtle) 製造一隻龜,名為 寫手(龜) writer.ht() 寫手 隱身 writer.pu() 寫手 提筆 writer.goto(1,1.15) 寫手前往 (1, 1.15) writer.write("DRAG!",align="center",font=("Arial",30,("bold","italic"))) 寫手 寫下 ("DRAG") return "EVENTLOOP" 15
  16. 04.colormixer.py 55 56 57 58 A B if __name__ ==

    "__main__": msg = main() print(msg) mainloop() 16
  17. 05.forest.py 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 A B C D #!/usr/bin/env python3 """ turtlegraphics-example-suite: tdemo_forest.py Displays a 'forest' of 3 breadth-first-trees similar to the one in tree. For further remarks see tree.py This example is a 'breadth-first'-rewrite of a Logo program written by Erich Neuwirth. See http://homepage.univie.ac.at/erich.neuwirth/ """ from turtle import Turtle, colormode, tracer, mainloop from random import randrange from time import clock def symRandom(n): return randrange(-n,n+1) def randomize( branchlist, angledist, sizedist ): return [ (angle+symRandom(angledist), sizefactor*1.01**symRandom(sizedist)) for angle, sizefactor in branchlist ] def randomfd( t, distance, parts, angledist ): for i in range(parts): t.left(symRandom(angledist)) t.forward( (1.0 * distance)/parts ) 17
  18. 05.forest.py 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 A B C D def tree(tlist, size, level, widthfactor, branchlists, angledist=10, sizedist=5): # benutzt Liste von turtles und Liste von Zweiglisten, # fuer jede turtle eine! if level > 0: lst = [] brs = [] for t, branchlist in list(zip(tlist,branchlists)): t.pensize( size * widthfactor ) t.pencolor( 255 - (180 - 11 * level + symRandom(15)), 180 - 11 * level + symRandom(15), 0 ) t.pendown() randomfd(t, size, level, angledist ) yield 1 for angle, sizefactor in branchlist: t.left(angle) lst.append(t.clone()) brs.append(randomize(branchlist, angledist, sizedist)) t.right(angle) for x in tree(lst, size*sizefactor, level-1, widthfactor, brs, angledist, sizedist): yield None def start(t,x,y): colormode(255) t.reset() t.speed(0) t.hideturtle() t.left(90) 18
  19. 05.forest.py 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 A B C D t.penup() t.setpos(x,y) t.pendown() def doit1(level, pen): pen.hideturtle() start(pen, 20, -208) t = tree( [pen], 80, level, 0.1, [[ (45,0.69), (0,0.65), (-45,0.71) ]] ) return t def doit2(level, pen): pen.hideturtle() start(pen, -135, -130) t = tree( [pen], 120, level, 0.1, [[ (45,0.69), (-45,0.71) ]] ) return t def doit3(level, pen): pen.hideturtle() start(pen, 190, -90) t = tree( [pen], 100, level, 0.1, [[ (45,0.7), (0,0.72), (-45,0.65) ]] ) return t # Hier 3 Baumgeneratoren: def main(): p = Turtle() p.ht() tracer(75,0) u = doit1(6, Turtle(undobuffersize=1)) s = doit2(7, Turtle(undobuffersize=1)) t = doit3(5, Turtle(undobuffersize=1)) 19
  20. 05.forest.py 91 92 93 94 95 96 97 98 99

    100 101 102 103 104 105 106 107 108 A B C D a = clock() while True : done = 0 for b in u,s,t: try : b.__next__() except : done += 1 if done == 3: break tracer(1,10) b = clock() return "runtime: %.2f sec." % (b-a) if __name__ == '__main__': main() mainloop() 20
  21. 06.fractalCurves.py 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 A B C D E F #!/usr/bin/env python3 """ turtle-example-suite: tdemo_fractalCurves.py This program draws two fractal-curve-designs: (1) A hilbert curve (in a box) (2) A combination of Koch-curves. The CurvesTurtle class and the fractal-curve- methods are taken from the PythonCard example scripts for turtle-graphics. """ from turtle import * from time import sleep, clock class CurvesTurtle(Pen): # example derived from # Turtle Geometry: The Computer as a Medium for Exploring Mathematics # by Harold Abelson and Andrea diSessa # p. 96-98 def hilbert(self, size, level, parity): if level == 0: return # rotate and draw first subcurve with opposite parity to big curve self.left(parity * 90) self.hilbert(size, level - 1, -parity) # interface to and draw second subcurve with same parity as big curve self.forward(size) self.right(parity * 90) 21
  22. 06.fractalCurves.py 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 A B C D E F self.hilbert(size, level - 1, parity) # third subcurve self.forward(size) self.hilbert(size, level - 1, parity) # fourth subcurve self.right(parity * 90) self.forward(size) self.hilbert(size, level - 1, -parity) # a final turn is needed to make the turtle # end up facing outward from the large square self.left(parity * 90) # Visual Modeling with Logo: A Structural Approach to Seeing # by James Clayson # Koch curve, after Helge von Koch who introduced this geometric figure in 1904 # p. 146 def fractalgon(self, n, rad, lev, dir): import math # if dir = 1 turn outward # if dir = -1 turn inward edge = 2 * rad * math.sin(math.pi / n) self.pu() self.fd(rad) self.pd() self.rt(180 - (90 * (n - 2) / n)) for i in range(n): self.fractal(edge, lev, dir) self.rt(360 / n) self.lt(180 - (90 * (n - 2) / n)) 22
  23. 06.fractalCurves.py 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 A B C D E F self.pu() self.bk(rad) self.pd() # p. 146 def fractal(self, dist, depth, dir): if depth < 1: self.fd(dist) return self.fractal(dist / 3, depth - 1, dir) self.lt(60 * dir) self.fractal(dist / 3, depth - 1, dir) self.rt(120 * dir) self.fractal(dist / 3, depth - 1, dir) self.lt(60 * dir) self.fractal(dist / 3, depth - 1, dir) def main(): ft = CurvesTurtle() ft.reset() ft.speed(0) ft.ht() ft.getscreen().tracer(1,0) ft.pu() size = 6 ft.setpos(-33*size, -32*size) ft.pd() 23
  24. 06.fractalCurves.py 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 A B C D E F ta=clock() ft.fillcolor("red") ft.begin_fill() ft.fd(size) ft.hilbert(size, 6, 1) # frame ft.fd(size) for i in range(3): ft.lt(90) ft.fd(size*(64+i%2)) ft.pu() for i in range(2): ft.fd(size) ft.rt(90) ft.pd() for i in range(4): ft.fd(size*(66+i%2)) ft.rt(90) ft.end_fill() tb=clock() res = "Hilbert: %.2fsec. " % (tb-ta) sleep(3) ft.reset() ft.speed(0) ft.ht() ft.getscreen().tracer(1,0) 24
  25. 06.fractalCurves.py 121 122 123 124 125 126 127 128 129

    130 131 132 133 134 135 136 137 138 A B C D E F ta=clock() ft.color("black", "blue") ft.begin_fill() ft.fractalgon(3, 250, 4, 1) ft.end_fill() ft.begin_fill() ft.color("red") ft.fractalgon(3, 200, 4, -1) ft.end_fill() tb=clock() res += "Koch: %.2fsec." % (tb-ta) return res if __name__ == '__main__': msg = main() print(msg) mainloop() 25
  26. 07.lindenmayer.py 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 A B C D E F G H #!/usr/bin/env python3 """ turtle-example-suite: xtx_lindenmayer_indian.py Each morning women in Tamil Nadu, in southern India, place designs, created by using rice flour and known as kolam on the thresholds of their homes. These can be described by Lindenmayer systems, which can easily be implemented with turtle graphics and Python. Two examples are shown here: (1) the snake kolam (2) anklets of Krishna Taken from Marcia Ascher: Mathematics Elsewhere, An Exploration of Ideas Across Cultures """ ################################ # Mini Lindenmayer tool ############################### from turtle import * def replace( seq, replacementRules, n ): 26
  27. 07.lindenmayer.py 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 A B C D E F G H for i in range(n): newseq = "" for element in seq: newseq = newseq + replacementRules.get(element,element) seq = newseq return seq def draw( commands, rules ): for b in commands: try : rules[b]() except TypeError: try : draw(rules[b], rules) except : pass def main(): ################################ # Example 1: Snake kolam ################################ def r(): right(45) def l(): left(45) 27
  28. 07.lindenmayer.py 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 A B C D E F G H def f(): forward(7.5) snake_rules = {"-":r, "+":l, "f":f, "b":"f+f+f--f--f+f+f"} snake_replacementRules = {"b": "b+f+b--f--b+f+b"} snake_start = "b--f--b--f" drawing = replace(snake_start, snake_replacementRules, 3) reset() speed(3) tracer(1,0) ht() up() backward(195) down() draw(drawing, snake_rules) from time import sleep sleep(3) ################################ # Example 2: Anklets of Krishna ################################ def A(): color("red") circle(10,90) def B(): 28
  29. 07.lindenmayer.py 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 A B C D E F G H from math import sqrt color("black") l = 5/sqrt(2) forward(l) circle(l, 270) forward(l) def F(): color("green") forward(10) krishna_rules = {"a":A, "b":B, "f":F} krishna_replacementRules = {"a" : "afbfa", "b" : "afbfbfbfa" } krishna_start = "fbfbfbfb" reset() speed(0) tracer(3,0) ht() left(45) drawing = replace(krishna_start, krishna_replacementRules, 3) draw(drawing, krishna_rules) tracer(1) return "Done!" if __name__=='__main__': msg = main() print(msg) mainloop() 29
  30. 08.minimal_hanoi.py 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 A B C #!/usr/bin/env python3 """ turtle-example-suite: tdemo_minimal_hanoi.py A minimal 'Towers of Hanoi' animation: A tower of 6 discs is transferred from the left to the right peg. An imho quite elegant and concise implementation using a tower class, which is derived from the built-in type list. Discs are turtles with shape "square", but stretched to rectangles by shapesize() --------------------------------------- To exit press STOP button --------------------------------------- """ from turtle import * class Disc(Turtle): 定義物類 「盤類」(Disk),繼承「龜類」(Turtle)。 def __init__(self, n): 定義方法 初始化,需傳入 n,代表盤的大小。 Turtle.__init__(self, shape="square", visible=False ) 將自身傳入龜類,以便繼承其初始化的所有設定。 self.pu() 自身提筆 self.shapesize(1.5, n*1.5, 2) # square-->rectangle自身設定形狀大小 self.fillcolor(n/6., 0, 1-n/6.) 自身設定顏色 self.st() 自身隱身 >>> d1= Disc(1) class Tower(list): 定義物類 「塔類」(Tower),繼承「列表類」(list)。 30
  31. 08.minimal_hanoi.py 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 A B C "Hanoi tower, a subclass of built-in type list" def __init__(self, x): 定義方法 初始化,需傳入 x,代表塔的x坐標。 "create an empty tower. x is x-position of peg" self.x = x 把傳入的x坐標保存在自身的x屬性中。 def push(self, d): 定義方法 「壓」(push),傳入 一個盤 d。 d.setx(self.x) d.sety(-150+34*len(self)) self.append(d) def pop(self): 定義方法 「彈」(push),傳出 一個盤 d。 d = list.pop(self) d.sety(150) return d def hanoi(n, from_, with_, to_): 定義方法 解河內塔多層(n, 起點, 中間, 終點) if n > 0: 若 n > 0: 執行以下遞迴指令,直到n==0為止。直接跳出本遞迴函數。 hanoi(n-1, from_, to_, with_) 解河內塔多層(n-1, 起點, 終點, 中間 ) to_.push(from_.pop()) 從起點彈1個出來,壓到終點。 hanoi(n-1, with_, from_, to_) 解河內塔多層(n-1, 中間, 起點, 終點 ) def play(): 定義方法 玩(play) onkey(None ,"space") clear() try : hanoi(6, t1, t2, t3) 執行解多層河內塔,傳入6層,以及t1, t2, t3三個塔。 write("press STOP button to exit", 解完後,寫下訊息。 align="center", font=("Courier", 16, "bold")) except Terminator: pass # turtledemo user pressed STOP def main(): 31
  32. 08.minimal_hanoi.py 61 62 63 64 65 66 67 68 69

    70 71 72 73 74 75 76 77 78 79 A B C global t1, t2, t3 ht(); penup(); goto(0, -225) # writer turtle t1 = Tower(-250) 在x坐標 -250, 0, 250 三處,各製造一個塔,名為 t1, t2, t3 t2 = Tower(0) t3 = Tower(250) # make tower of 6 discs for i in range(6,0,-1): t1.push(Disc(i)) 製造 6 個 盤,將它們依大小壓入 t1 中。 # prepare spartanic user interface ;-) write("press spacebar to start game", 寫下訊息告知使用者按 空白鍵 開始玩。 align="center", font=("Courier", 16, "bold")) onkey(play, "space") 設定按鍵(空白鍵)與 玩 函數之連結。 listen() 開始傾聽使用者的按鍵。 return "EVENTLOOP" if __name__=="__main__": msg = main() print(msg) mainloop() 32
  33. 09.nim.py 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 A B C D E """ turtle-example-suite: tdemo_nim.py Play nim against the computer. The player who takes the last stick is the winner. Implements the model-view-controller design pattern. """ import turtle import random import time SCREENWIDTH = 640 SCREENHEIGHT = 480 MINSTICKS = 7 MAXSTICKS = 31 HUNIT = SCREENHEIGHT // 12 WUNIT = SCREENWIDTH // ((MAXSTICKS // 5) * 11 + (MAXSTICKS % 5) * 2) SCOLOR = (63, 63, 31) HCOLOR = (255, 204, 204) COLOR = (204, 204, 255) def randomrow(): 33
  34. 09.nim.py 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 A B C D E return random.randint(MINSTICKS, MAXSTICKS) def computerzug(state): xored = state[0] ^ state[1] ^ state[2] if xored == 0: return randommove(state) for z in range(3): s = state[z] ^ xored if s <= state[z]: move = (z, s) return move def randommove(state): m = max(state) while True : z = random.randint(0,2) if state[z] > (m > 1): break rand = random.randint(m > 1, state[z]-1) return z, rand class NimModel(object): def __init__(self, game): self.game = game def setup(self): if self.game.state not in [Nim.CREATED, Nim.OVER]: return self.sticks = [randomrow(), randomrow(), randomrow()] 34
  35. 09.nim.py 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 A B C D E self.player = 0 self.winner = None self.game.view.setup() self.game.state = Nim.RUNNING def move(self, row, col): maxspalte = self.sticks[row] self.sticks[row] = col self.game.view.notify_move(row, col, maxspalte, self.player) if self.game_over(): self.game.state = Nim.OVER self.winner = self.player self.game.view.notify_over() elif self.player == 0: self.player = 1 row, col = computerzug(self.sticks) self.move(row, col) self.player = 0 def game_over(self): return self.sticks == [0, 0, 0] def notify_move(self, row, col): if self.sticks[row] <= col: return self.move(row, col) class Stick(turtle.Turtle): def __init__(self, row, col, game): 35
  36. 09.nim.py 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 A B C D E turtle.Turtle.__init__(self, visible=False ) self.row = row self.col = col self.game = game x, y = self.coords(row, col) self.shape("square") self.shapesize(HUNIT/10.0, WUNIT/20.0) self.speed(0) self.pu() self.goto(x,y) self.color("white") self.showturtle() def coords(self, row, col): packet, remainder = divmod(col, 5) x = (3 + 11 * packet + 2 * remainder) * WUNIT y = (2 + 3 * row) * HUNIT return x - SCREENWIDTH // 2 + WUNIT // 2, SCREENHEIGHT // 2 - y - HUNIT // 2 def makemove(self, x, y): if self.game.state != Nim.RUNNING: return self.game.controller.notify_move(self.row, self.col) class NimView(object): def __init__(self, game): self.game = game self.screen = game.screen self.model = game.model 36
  37. 09.nim.py 121 122 123 124 125 126 127 128 129

    130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 A B C D E self.screen.colormode(255) self.screen.tracer(False ) self.screen.bgcolor((240, 240, 255)) self.writer = turtle.Turtle(visible=False ) self.writer.pu() self.writer.speed(0) self.sticks = {} for row in range(3): for col in range(MAXSTICKS): self.sticks[(row, col)] = Stick(row, col, game) self.display("... a moment please ...") self.screen.tracer(True ) def display(self, msg1, msg2=None ): self.screen.tracer(False ) self.writer.clear() if msg2 is not None : self.writer.goto(0, - SCREENHEIGHT // 2 + 48) self.writer.pencolor("red") self.writer.write(msg2, align="center", font=("Courier",18,"bold")) self.writer.goto(0, - SCREENHEIGHT // 2 + 20) self.writer.pencolor("black") self.writer.write(msg1, align="center", font=("Courier",14,"bold")) self.screen.tracer(True ) def setup(self): self.screen.tracer(False ) for row in range(3): for col in range(self.model.sticks[row]): self.sticks[(row, col)].color(SCOLOR) 37
  38. 09.nim.py 151 152 153 154 155 156 157 158 159

    160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 A B C D E for row in range(3): for col in range(self.model.sticks[row], MAXSTICKS): self.sticks[(row, col)].color("white") self.display("Your turn! Click leftmost stick to remove.") self.screen.tracer(True ) def notify_move(self, row, col, maxspalte, player): if player == 0: farbe = HCOLOR for s in range(col, maxspalte): self.sticks[(row, s)].color(farbe) else : self.display(" ... thinking ... ") time.sleep(0.5) self.display(" ... thinking ... aaah ...") farbe = COLOR for s in range(maxspalte-1, col-1, -1): time.sleep(0.2) self.sticks[(row, s)].color(farbe) self.display("Your turn! Click leftmost stick to remove.") def notify_over(self): if self.game.model.winner == 0: msg2 = "Congrats. You're the winner!!!" else : msg2 = "Sorry, the computer is the winner." self.display("To play again press space bar. To leave press ESC.", msg2) def clear(self): if self.game.state == Nim.OVER: 38
  39. 09.nim.py 181 182 183 184 185 186 187 188 189

    190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 A B C D E self.screen.clear() class NimController(object): def __init__(self, game): self.game = game self.sticks = game.view.sticks self.BUSY = False for stick in self.sticks.values(): stick.onclick(stick.makemove) self.game.screen.onkey(self.game.model.setup, "space") self.game.screen.onkey(self.game.view.clear, "Escape") self.game.view.display("Press space bar to start game") self.game.screen.listen() def notify_move(self, row, col): if self.BUSY: return self.BUSY = True self.game.model.notify_move(row, col) self.BUSY = False class Nim(object): CREATED = 0 RUNNING = 1 OVER = 2 def __init__(self, screen): self.state = Nim.CREATED 39
  40. 09.nim.py 211 212 213 214 215 216 217 218 219

    220 221 222 223 224 225 226 A B C D E self.screen = screen self.model = NimModel(self) self.view = NimView(self) self.controller = NimController(self) def main(): mainscreen = turtle.Screen() mainscreen.mode("standard") mainscreen.setup(SCREENWIDTH, SCREENHEIGHT) nim = Nim(mainscreen) return "EVENTLOOP" if __name__ == "__main__": main() turtle.mainloop() 40
  41. 10.paint.py 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 A B C D E F G #!/usr/bin/env python3 """ turtle-example-suite: tdemo_paint.py A simple event-driven paint program - left mouse button moves turtle - middle mouse button changes color - right mouse button toogles betweem pen up (no line drawn when the turtle moves) and pen down (line is drawn). If pen up follows at least two pen-down moves, the polygon that includes the starting point is filled. ------------------------------------------- Play around by clicking into the canvas using all three mouse buttons. ------------------------------------------- To exit press STOP button ------------------------------------------- """ from turtle import * def switchupdown(x=0, y=0): if pen()["pendown"]: end_fill() up() else : down() begin_fill() 41
  42. 10.paint.py 31 32 33 34 35 36 37 38 39

    40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 A B C D E F G def changecolor(x=0, y=0): global colors colors = colors[1:]+colors[:1] color(colors[0]) def main(): global colors shape("circle") resizemode("user") shapesize(.5) width(3) colors=["red", "green", "blue", "yellow"] color(colors[0]) switchupdown() onscreenclick(goto,1) onscreenclick(changecolor,2) onscreenclick(switchupdown,3) return "EVENTLOOP" if __name__ == "__main__": msg = main() print(msg) mainloop() 42
  43. 11.peace.py 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 A B C D E F G H #!/usr/bin/env python3 """ turtle-example-suite: tdemo_peace.py A simple drawing suitable as a beginner's programming example. Aside from the peacecolors assignment and the for loop, it only uses turtle commands. """ from turtle import * def main(): peacecolors = ("red3", "orange", "yellow", "seagreen4", "orchid4", "royalblue1", "dodgerblue4") reset() Screen() up() goto(-320,-195) width(70) for pcolor in peacecolors: color(pcolor) down() forward(640) up() backward(640) 43
  44. 11.peace.py 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 A B C D E F G H left(90) forward(66) right(90) width(25) color("white") goto(0,-170) down() circle(170) left(90) forward(340) up() left(180) forward(170) right(45) down() forward(170) up() backward(170) left(90) down() forward(170) up() goto(0,300) # vanish if hideturtle() is not available ;-) return "Done!" if __name__ == "__main__": main() 44
  45. 12.penrose.py 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 A B C D E F G #!/usr/bin/env python3 """ xturtle-example-suite: xtx_kites_and_darts.py Constructs two aperiodic penrose-tilings, consisting of kites and darts, by the method of inflation in six steps. Starting points are the patterns "sun" consisting of five kites and "star" consisting of five darts. For more information see: http://en.wikipedia.org/wiki/Penrose_tiling ------------------------------------------- """ from turtle import * from math import cos, pi from time import clock, sleep f = (5**0.5-1)/2.0 # (sqrt(5)-1)/2 -- golden ratio d = 2 * cos(3*pi/10) def kite(l): fl = f * l lt(36) fd(l) rt(108) fd(fl) 46
  46. 12.penrose.py 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 A B C D E F G rt(36) fd(fl) rt(108) fd(l) rt(144) def dart(l): fl = f * l lt(36) fd(l) rt(144) fd(fl) lt(36) fd(fl) rt(144) fd(l) rt(144) def inflatekite(l, n): if n == 0: px, py = pos() h, x, y = int(heading()), round(px,3), round(py,3) tiledict[(h,x,y)] = True return fl = f * l lt(36) inflatedart(fl, n-1) fd(l) rt(144) inflatekite(fl, n-1) 47
  47. 12.penrose.py 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 A B C D E F G lt(18) fd(l*d) rt(162) inflatekite(fl, n-1) lt(36) fd(l) rt(180) inflatedart(fl, n-1) lt(36) def inflatedart(l, n): if n == 0: px, py = pos() h, x, y = int(heading()), round(px,3), round(py,3) tiledict[(h,x,y)] = False return fl = f * l inflatekite(fl, n-1) lt(36) fd(l) rt(180) inflatedart(fl, n-1) lt(54) fd(l*d) rt(126) inflatedart(fl, n-1) fd(l) rt(144) def draw(l, n, th=2): 48
  48. 12.penrose.py 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 A B C D E F G clear() l = l * f**n shapesize(l/100.0, l/100.0, th) for k in tiledict: h, x, y = k setpos(x, y) setheading(h) if tiledict[k]: shape("kite") color("black", (0, 0.75, 0)) else : shape("dart") color("black", (0.75, 0, 0)) stamp() def sun(l, n): for i in range(5): inflatekite(l, n) lt(72) def star(l,n): for i in range(5): inflatedart(l, n) lt(72) def makeshapes(): tracer(0) begin_poly() kite(100) end_poly() 49
  49. 12.penrose.py 121 122 123 124 125 126 127 128 129

    130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 A B C D E F G register_shape("kite", get_poly()) begin_poly() dart(100) end_poly() register_shape("dart", get_poly()) tracer(1) def start(): reset() ht() pu() makeshapes() resizemode("user") def test(l=200, n=4, fun=sun, startpos=(0,0), th=2): global tiledict goto(startpos) setheading(0) tiledict = {} a = clock() tracer(0) fun(l, n) b = clock() draw(l, n, th) tracer(1) c = clock() print("Calculation: %7.4f s" % (b - a)) print("Drawing: %7.4f s" % (c - b)) print("Together: %7.4f s" % (c - a)) nk = len([x for x in tiledict if tiledict[x]]) 50
  50. 12.penrose.py 151 152 153 154 155 156 157 158 159

    160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 A B C D E F G nd = len([x for x in tiledict if not tiledict[x]]) print("%d kites and %d darts = %d pieces." % (nk, nd, nk+nd)) def demo(fun=sun): start() for i in range(8): a = clock() test(300, i, fun) b = clock() t = b - a if t < 2: sleep(2 - t) def main(): #title("Penrose-tiling with kites and darts.") mode("logo") bgcolor(0.3, 0.3, 0) demo(sun) sleep(2) demo(star) pencolor("black") goto(0,-200) pencolor(0.7,0.7,1) write("Please wait...", align="center", font=('Arial Black', 36, 'bold')) test(600, 8, startpos=(70, 117)) return "Done" if __name__ == "__main__": msg = main() 51
  51. 13.planet_and_moon.py 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 A B C D E #!/usr/bin/env python3 """ turtle-example-suite: tdemo_planets_and_moon.py Gravitational system simulation using the approximation method from Feynman-lectures, p.9-8, using turtlegraphics. Example: heavy central body, light planet, very light moon! Planet has a circular orbit, moon a stable orbit around the planet. You can hold the movement temporarily by pressing the left mouse button with the mouse over the scrollbar of the canvas. """ from turtle import Shape, Turtle, mainloop, Vec2D as Vec from time import sleep G = 8 class GravSys(object): def __init__(self): self.planets = [] self.t = 0 self.dt = 0.01 def init(self): 53
  52. 13.planet_and_moon.py 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 A B C D E for p in self.planets: p.init() def start(self): for i in range(10000): self.t += self.dt for p in self.planets: p.step() class Star(Turtle): def __init__(self, m, x, v, gravSys, shape): Turtle.__init__(self, shape=shape) self.penup() self.m = m self.setpos(x) self.v = v gravSys.planets.append(self) self.gravSys = gravSys self.resizemode("user") self.pendown() def init(self): dt = self.gravSys.dt self.a = self.acc() self.v = self.v + 0.5*dt*self.a def acc(self): a = Vec(0,0) for planet in self.gravSys.planets: if planet != self: v = planet.pos()-self.pos() a += (G*planet.m/abs(v)**3)*v return a 54
  53. 13.planet_and_moon.py 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 A B C D E def step(self): dt = self.gravSys.dt self.setpos(self.pos() + dt*self.v) if self.gravSys.planets.index(self) != 0: self.setheading(self.towards(self.gravSys.planets[0])) self.a = self.acc() self.v = self.v + dt*self.a ## create compound yellow/blue turtleshape for planets def main(): s = Turtle() s.reset() s.getscreen().tracer(0,0) s.ht() s.pu() s.fd(6) s.lt(90) s.begin_poly() s.circle(6, 180) s.end_poly() m1 = s.get_poly() s.begin_poly() s.circle(6,180) s.end_poly() m2 = s.get_poly() planetshape = Shape("compound") planetshape.addcomponent(m1,"orange") planetshape.addcomponent(m2,"blue") 55
  54. 13.planet_and_moon.py 91 92 93 94 95 96 97 98 99

    100 101 102 103 104 105 106 107 108 109 110 111 112 A B C D E s.getscreen().register_shape("planet", planetshape) s.getscreen().tracer(1,0) ## setup gravitational system gs = GravSys() sun = Star(1000000, Vec(0,0), Vec(0,-2.5), gs, "circle") sun.color("yellow") sun.shapesize(1.8) sun.pu() earth = Star(12500, Vec(210,0), Vec(0,195), gs, "planet") earth.pencolor("green") earth.shapesize(0.8) moon = Star(1, Vec(220,0), Vec(0,295), gs, "planet") moon.pencolor("blue") moon.shapesize(0.5) gs.init() gs.start() return "Done!" if __name__ == '__main__': main() mainloop() 56
  55. 14.round_dance.py 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 A B C D E F G H """ turtle-example-suite: tdemo_round_dance.py (Needs version 1.1 of the turtle module that comes with Python 3.1) Dancing turtles have a compound shape consisting of a series of triangles of decreasing size. Turtles march along a circle while rotating pairwise in opposite direction, with one exception. Does that breaking of symmetry enhance the attractiveness of the example? Press any key to stop the animation. Technically: demonstrates use of compound shapes, transformation of shapes as well as cloning turtles. The animation is controlled through update(). """ from turtle import * def stop(): global running running = False 57
  56. 14.round_dance.py 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 A B C D E F G H def main(): global running clearscreen() bgcolor("gray10") tracer(False ) shape("triangle") f = 0.793402 phi = 9.064678 s = 5 c = 1 # create compound shape sh = Shape("compound") for i in range(10): shapesize(s) p =get_shapepoly() s *= f c *= f tilt(-phi) sh.addcomponent(p, (c, 0.25, 1-c), "black") register_shape("multitri", sh) # create dancers shapesize(1) shape("multitri") pu() setpos(0, -200) dancers = [] for i in range(180): fd(7) tilt(-4) lt(2) 58
  57. 14.round_dance.py 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 A B C D E F G H update() if i % 12 == 0: dancers.append(clone()) home() # dance running = True onkeypress(stop) listen() cs = 1 while running: ta = -4 for dancer in dancers: dancer.fd(7) dancer.lt(2) dancer.tilt(ta) ta = -4 if ta > 0 else 2 if cs < 180: right(4) shapesize(cs) cs *= 1.005 update() return "DONE!" if __name__=='__main__': print(main()) mainloop() 59
  58. 15.tree.py 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 A B C #!/usr/bin/env python3 """ turtle-example-suite: tdemo_tree.py Displays a 'breadth-first-tree' - in contrast to the classical Logo tree drawing programs, which use a depth-first-algorithm. Uses: (1) a tree-generator, where the drawing is quasi the side-effect, whereas the generator always yields None. (2) Turtle-cloning: At each branching point the current pen is cloned. So in the end there are 1024 turtles. """ from turtle import Turtle, mainloop from time import clock def tree(plist, l, a, f): 定義 樹函數,傳入 根,莖長,分支角度,縮減比例。 """ plist is list of pens l is length of branch a is half of the angle between 2 branches f is factor by which branch is shortened from level to level.""" if l > 3: lst = [] for p in plist: p.forward(l) 60
  59. 15.tree.py 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 A B C q = p.clone() p.left(a) q.right(a) lst.append(p) lst.append(q) for x in tree(lst, l*f, a, f): yield None def maketree(): 定義 造樹函數 p = Turtle() 由 龜類造一隻龜,名為 p p.setundobuffer(None ) p 設定動作回覆暫存器為「空」 p.hideturtle() p 隱身 p.speed(0) p 設速度為0,那是最快的。 p.getscreen().tracer(30,0) p 取得所在的螢幕,設追蹤器為 30 p.left(90) p 左轉 90 度。 p.penup() p 提筆 p.forward(-210) p 前進 -210,亦即倒退 210 p.pendown() p 下筆。 t = tree([p], 200, 65, 0.6375) 由 p 開始,呼叫 遞迴函數 tree 來長出小樹枝。 for x in t: pass print(len(p.getscreen().turtles())) def main(): a=clock() maketree() b=clock() return "done: %.2f sec." % (b-a) if __name__ == "__main__": 61
  60. 15.tree.py 61 62 63 A B C msg = main()

    print(msg) mainloop() 62
  61. 16.two_canvases.py 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 A B C D E F G H """turtledemo.two_canvases Use TurtleScreen and RawTurtle to draw on two distinct canvases in a separate windows. The new window must be separately closed in addition to pressing the STOP button. """ from turtle import TurtleScreen, RawTurtle, TK def main(): root = TK.Tk() cv1 = TK.Canvas(root, width=300, height=200, bg="#ddffff") cv2 = TK.Canvas(root, width=300, height=200, bg="#ffeeee") cv1.pack() cv2.pack() s1 = TurtleScreen(cv1) s1.bgcolor(0.85, 0.85, 1) s2 = TurtleScreen(cv2) s2.bgcolor(1, 0.85, 0.85) p = RawTurtle(s1) q = RawTurtle(s2) p.color("red", (1, 0.85, 0.85)) p.width(3) q.color("blue", (0.85, 0.85, 1)) q.width(3) 63
  62. 16.two_canvases.py 31 32 33 34 35 36 37 38 39

    40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 A B C D E F G H for t in p,q: t.shape("turtle") t.lt(36) q.lt(180) for t in p, q: t.begin_fill() for i in range(5): for t in p, q: t.fd(50) t.lt(72) for t in p,q: t.end_fill() t.lt(54) t.pu() t.bk(50) return "EVENTLOOP" if __name__ == '__main__': main() TK.mainloop() # keep window open until user closes it 64
  63. 17.wikipedia.py 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 A B C D E F G """ turtle-example-suite: tdemo_wikipedia3.py This example is inspired by the Wikipedia article on turtle graphics. (See example wikipedia1 for URLs) First we create (ne-1) (i.e. 35 in this example) copies of our first turtle p. Then we let them perform their steps in parallel. Followed by a complete undo(). """ from turtle import Screen, Turtle, mainloop from time import clock, sleep def mn_eck(p, ne,sz): 定義本繪圖主函數 mn_eck turtlelist = [p] 建立龜列表 #create ne-1 additional turtles for i in range(1,ne): 重複執行 ne-1 次 q = p.clone() 複製龜 q.rt(360.0/ne) 每隻龜右轉一下 turtlelist.append(q) 存入龜列表 p = q for i in range(ne): 以下重複ne次: c = abs(ne/2.0-i)/(ne*.7) 運用數學公式設定顏色值c # let those ne turtles make a step # in parallel: 65
  64. 17.wikipedia.py 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 A B C D E F G for t in turtlelist: 針對每隻龜執行以下動作 t.rt(360./ne) 每隻龜右轉一下 t.pencolor(1-c,0,c) 顏色值c在此運用於筆色 t.fd(sz) 每隻龜前進一下 def main(): s = Screen() 取得龜作圖螢幕,名為s s.bgcolor("black") s 設定背景色為黑 p=Turtle() 由龜類製造一隻龜,命名為 p p.speed(0) p 設定速度為 0,最快的速度。 p.hideturtle() p 隱身 p.pencolor("red") p 筆色為紅色 p.pensize(3) p 筆大小為 3 s.tracer(36,0) s 設定螢幕追蹤 at = clock() 取得當前時間 mn_eck(p, 36, 19) 執行本繪圖主函數 mn_eck et = clock() 取得當前時間 z1 = et-at 計算前後時間差 sleep(1) 睡 1 秒 at = clock() while any([t.undobufferentries() for t in s.turtles()]): 當螢幕上的任一隻龜尚有動作存於暫存器中時 for t in s.turtles(): 針對螢幕上的任一隻龜 t.undo() 動作回復 et = clock() return "runtime: %.3f sec" % (z1+et-at) 66
  65. 17.wikipedia.py 61 62 63 64 65 A B C D

    E F G if __name__ == '__main__': msg = main() print(msg) mainloop() 67
  66. 18.yinyang.py 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 A B C D E F #!/usr/bin/env python3 """ turtle-example-suite: tdemo_yinyang.py Another drawing suitable as a beginner's programming example. The small circles are drawn by the circle command. """ from turtle import * def yin(radius, color1, color2): 定義 陰函數,傳入半徑,主色,副色 width(3) 設定筆寬為3 color("black", color1) 設定顏色,筆色為黑,龜內填色為主色 begin_fill() 開始填色 circle(radius/2., 180) 畫圓 circle(radius, 180) 畫圓 left(180) 左轉 circle(-radius/2., 180) 畫圓 end_fill() 結束填色 left(90) 左轉 up() 提筆 forward(radius*0.35) 前進 right(90) 右轉 down() 下筆 color(color1, color2) 設定顏色,筆色為主色,龜內填色為副色 68
  67. 18.yinyang.py 31 32 33 34 35 36 37 38 39

    40 41 42 43 44 45 46 47 48 49 A B C D E F begin_fill() 開始填色 circle(radius*0.15) 畫圓 end_fill() 結束填色 left(90) 左轉 up() 提筆 backward(radius*0.35) 後退 down() 下筆 left(90) 左轉 def main(): reset() 重設 yin(200, "black", "white") 陰(半徑為200,主色為黑,副色為白) yin(200, "white", "black") 陰(半徑為200,主色為白,副色為黑) ht() 隱身 return "Done!" if __name__ == '__main__': main() mainloop() 69