#c6c6c6 Logo 小海龜實現碎形繪圖程序   在我去年編寫的碎形教材(被歸於複雜性科學的領域),介紹了繪製碎形的主要幾種方法,無論是哪一種方法都牽涉到疊代( iteration)、遞迴(遞歸,recursion)的概念,這些概念的重要性貫穿了整個計算機科
、數理邏輯與近來興起的複雜性科學,也是 Logo 小海龜之所以繪圖功力了得的主要關鍵。我曾在碎形教材裡 (L-System)提到過這隻小海龜,牠在美國的兒童教育界引領了一股海龜製圖法( Turtle Graphics ) 與海龜幾何學(Turtle Geometry)的風潮 。 牠到底有多嗆、多厲害,先來看看這些圖例吧。

  這些圖都是經驗老到的小海龜所畫的,每張圖小海龜都花不到十五行的 Logo 程式碼就完成了。等一下我再來談談,什麼是 Logo 電腦程式語言。我們以外觀看起來最困難的蕨葉為例,它的 Logo 程式碼如下,紅色字體的部分就是運用到遞迴方法的程序, 而分號開始的文字(灰色字體)便是註解:

to main         ; 主程序
 draw 305
end
             ; 定義子程序
to draw :size      ; 也是遞迴程序
 IF :size<5 [Stop]   ; 條件判斷後,結束
 FD :size/25      ; FD 是前進
 LT 80 draw :size*.3  ; LT 是左轉
 RT 82 FD  :size/25  ; RT 是右轉
 RT 80 draw :size*.3  ; RT 80 之後,遞迴自己
 LT 78 draw :size*.9  ; LT 78 之後,遞迴自己
 LT 2 BK  :size/25  ; BK 是後退
 LT 2 BK  :size/25  ; LT 2 之後,BK 長度(size/25)
end


  這裡的程式碼指令只用到條件判斷(IF)與前進( Forward,簡寫 FD
、後退(Backward,簡寫 BK)、左轉(Left,簡寫 LT)與右轉( Right
,簡寫 RT)
。 我們可以想像有一隻小海龜在螢幕上 ,按照遞迴的程序而一下前進、後退,一下轉轉身子,直到完成一幅蕨葉。這裡的遞迴程序就是被不斷呼叫的子程序 draw( 它的輸入引數是 :size,Logo 語言的變數前面都有冒號作為識別 ), draw 負責畫出不同大小的支葉, 同時小海龜也移動位置與角度,這使得整枝蕨葉呈現生動的弧度與絕妙的收尾。學習過碎形的網友一定知道這是樹狀碎形的一種,遞迴程序使得它在不同尺度上「自我相似」。是否注意到每一支葉其實都是全體的縮小版?是的,遞迴的意義就在於此,即反覆地疊代自身,然後再以不同的角度、方位與大小加入整體之中。上面另外兩張頗具知名度的碎形圖 Hilbert Curve 與 Dragon
Curve 也是這樣。大自然的幾何形塑更是非線性動力系統的遞迴結果

   這套程式碼是應用了 Logo 電腦程式語言 , 但是 Logo 語言有許多版本,包括 UCB Logo、Star Logo 與 Gerlabau Logo( 國內是由劉敬洲先生在 1997 年開發為「 葛拉堡中文小海龜 」, 目前作為許多中小學的推廣課程
,我在這裡所用的是 Microsoft Windows Logo(MSW Logo)。 為什麼它會與小海龜結下不解之緣呢? 這是因為 Logo 的前身在五O年代是一個像小海龜的機械裝置 ,到了六O年代,麻省理工學院設計了一套 Logo 編碼程序,可以讓小朋友輸入指令,讓這隻小海龜在地板上前進轉彎,後來個人電腦普及,小海龜也從地板「遷居」到了電腦螢幕上。專為兒童教育與激發兒童創造力, 所設計的 Logo 語言也因此在美國日益普遍,直到今日
,它仍然是建構式教育理念的重要教學工具。我會另外找個時間編寫教材
,介紹 Logo 語言、碎形幾何學與建構主義的教育哲學,等有關主題。

  Logo 程式語言相當簡單易學 , 它的直譯器使得程式除錯與撰寫更具有互動性 ,如果你只鍵入 FD 而沒有補上長度,它會馬上告訴你:小海龜不知道要前進多少距離!海龜製圖法的關鍵在於海龜的移動,我們最常用的指令集中在前進、後退、左轉、右轉,與下筆(PenDown,海龜移動留痕跡,簡寫 PD)與提筆(PenUp,海龜移動不留痕跡,簡寫 PU), 定位(SetPos)與定角(SetHead,把ㄣ頭擺到指定的角度)、迴圈(Reapeat、While 或 For)與條件指令(IF)等等。

  例如想畫正方形,只要依序輸入以下的指令:



?FD 100 RT 90  ; 前進 100 單位,右轉 90 度
?FD 100 RT 90
?FD 100 RT 90
?FD 100 RT 90  ; 最後一行,小海龜回到原位與原角度


  這些程式碼即可。有沒有注意到某些指令的組合重複了四次?如果利用迴圈指令,我們可以把畫正方形的程式碼簡要地改寫成:

  Repeat 4 [FD 100 RT 90]

  或者是

  For [i 1 4] [FD 100 RT 90]

  如果還是不瞭解,請參考葛拉堡中文小海龜的教學課程,或是 MSW Logo 的介紹網頁 http://www.southwest.com.au/~jfuller/logotut/menu.htm


***********************


  剛剛提到了繪製正方形的程式碼,我們就將它稱做子程序 square,寫成以下的格式。這種寫法方便我們只要用 square 就可以代替整個程序:

 to square
  Repeat 4 [FD 100 RT 90]
 end


  精采的部分要來了,如果我們鍵入指令 Repeat
36 [RT 10 square]
, 意思是〔 右轉 10,然後畫正方形〕括弧內重複 36 次 , 那麼,這個遞迴圖形就是像左上圖那樣。現在,我們將子程序 square 加上引數?:size 與 :angle,然後變成以下的寫法:

 to square :size :angle  ; 有引數的子程序
  IF :size > 100 [Stop]
  FD :size        ; 前進 :size 長度
  RT :angle        ; 右轉 :angle 角度
  square :size + 2 :angle ; 遞迴自己
 end            ; 同時引數改變


  針對有引數的子程序 square,我們只要鍵入簡單的指令 square 0 91 ,意思是子程序從大小 0 與角度 91 開始自我遞迴 ,小海龜就會畫出中間這個螺旋圖形。如果鍵入指令 square 0 93 ,小海龜就會畫出左邊這個漩渦圖形。這些圖形都是碎形的簡單例子,所謂碎形是指在結構與尺度上自我相似或自我相仿的圖案,而這些特徵就是某些規則(例如上述的子程序 square)的自我遞迴(疊代)的結果。看起來是簡單的規則,只需要些許的變形,即蘊涵了無限的潛力與複雜性 , Logo 小海龜正帶領我們進入這豐富景象的奧秘之中,那裡有段發揮創造力的旅程。海龜製圖法可以訓練小朋友一個步驟一個步驟地,觀察幾何圖形的片段如何組合成一個富有趣味的整體,也可以訓練像我這樣的老手,如何把複雜的整體拆解成類似單元的疊代結果,並且寫出它的結構方程式——就像是一位物理學家看到自然界雪花的六角結構,便推測得出它的內部非線性動力關係。

?  右邊圖案是一棵典型的碎形樹:

to tree :order :len
 IfElse :order = 1 [  ; 當
  FD :len
  LT 30 FD :len BK :len RT 30
  RT 30 FD :len BK :len LT 30
  BK :len
  Stop
 ] [          ; 否則
  FD :len
  LT 30 tree :order-1 :len*.75 RT 30
  RT 45 tree :order-1 :len*.75 LT 45
  BK :len
 ]
end


  以上是子程序 tree 的 MSW Logo 程式碼,當我們執行指令 tree 9 50
,便會畫出碎形樹( 二元樹 )的圖案。這已經相當接近 Visual Basic 的語法架構了,我們可以進一步改編成 Visual Basic 的子函數型態如下:

Private Sub 枯樹(ByVal 層次 As Single, ByVal 長度 As Single)
 If 層次 = 1 Then    ' 當
  前進 長度
  左轉 30: 前進 長度: 後退 長度: 右轉 30
  右轉 30: 前進 長度: 後退 長度: 左轉 30
  後退 長度
 Else          ' 否則
  前進 長度
  左轉 30: 枯樹 層次 - 1, 長度 * 0.75: 右轉 30
  右轉 45: 枯樹 層次 - 1, 長度 * 0.75: 左轉 45
  後退 長度
 End If
End Sub


  顯然這麼一改, 我們就知道該如何用 Visual Basic 來「翻譯」Logo 語言程式碼了,基本上可以完全的轉譯。我們必須處理的工作是撰寫 VB 版的 Logo 程式庫 , 即建立 ActiveX DLL 以物件型態呈現可重複使用的程式碼,當然你也可以寫成物件類別。這個程式庫 Logo.dll 至少要定義程式碼(函數)如:定位、定角、前進、後退、左轉、右轉。程式庫必須要有私有變數紀錄目前的小海龜位置與朝向角度,在處理左右轉的時候,需要使用到解析幾何的二維旋轉變換。如果不以矩陣形式表示,則函數如下:

Private Const pii = pi / 180    ' 圓週率 π/180

' 二維旋轉變換,對任意點 (Xo, Yo) 順時鐘旋轉 Angle 度
Private Sub Rotating2D(X, Y, ByVal Xo As Single, ByVal Yo As Single, ByVal Angle As Single)
 Dim Xe As Single, Ye As Single
 X = X - Xo: Y = Y - Yo
 Xe = X: Ye = Y
 Angle = Angle * pii
 X = Xe * Cos(Angle) + Ye * Sin(Angle)
 Y = -Xe * Sin(Angle) + Ye * Cos(Angle)
 X = X + Xo: Y = Y + Yo      ' 傳址回 X, Y
End Sub


  撰寫這樣的程式庫並不困難,不到六十行的程式碼,我們就可以完成
VB 版的 Logo 語言繪圖環境 。 然而這裡困難的是, 有了這樣簡易而富有彈性的開發環境,我們要如何發揮創意來使小海龜——以簡馭繁、不負眾望地發揮潛能?這需要你來動動腦筋,花時間來實地創作!


註:原寫於 2004/11/18
  http://www.atlas-zone.com/computer/talk/part_1/computer060.htm
  http://www.atlas-zone.com/computer/talk/part_1/computer061.htm


延伸閱讀:
〈碎形幾何內涵與 Logo 程式繪圖〉
http://blog.xuite.net/sinner66/blog/10141991
〈DBN 結合 Logo 觀念以實現碎形〉
http://blog.xuite.net/sinner66/blog/11579881
2007/03/03