最近一直在翻譯有點悶,總想著玩點什麼來解放一下腦袋,有時你的心中就是會有這樣的蠢動,這時需要的就是踏出第一步,直接把頭洗下去,就對了,還記得任務解除那一瞬間的成就感嗎?我們最初跨入程式設計,不都是因為這一類的爽度嗎?

想要創作的蠢動

工作就是工作,有時很難找到什麼樂趣,我很明白這點,最近我的工作是翻譯《jQuery in action》第三版,前兩版都是我翻的,因此第三版還是接下來了,即使我先作好了先前專欄〈技術翻譯從己出發〉說過的心態準備,然而翻譯本身辛苦這件事,本質上並不會改變,為了避免翻譯過程的單調與苦悶,在進度尚且滿足的情況下,我還會學學Go語言,玩一下3D列印的東西,轉換一下焦點與心情。

隨著翻譯進度超過全書的一半,自己都可以感受到心情逐漸變得浮躁了,好一些日子沒有寫些正經(好玩)的程式,心裡開始覺得像是一大堆的螞蟻在爬來爬去,癢得很是難受,最近在玩3D建模,也試著用OpenSCAD寫了個手機顯微鏡頭的固定夾,在成果還不錯的情況下,反而讓心情更浮躁了,更想寫個什麼有挑戰性的東西,而且是手動建模無法完成、只有程式建模可以做到的東西。

那麼來做個迷宮產生器如何?如果成功,就可以產生隨機可列印的迷宮,後續還可以應用在各式3D建模上,應該滿酷的!

在Thingiverse網站上略略搜尋了一陣,雖然有一些迷宮產生器,不過,多半是配合其他程式語言產生OpenSCAD檔案,然後才用OpenSCAD匯出STL模型檔,純OpenSCAD實作的迷宮產生器我沒找到,這就有了挑戰的價值!某一天就擱下了當日應該完成的翻譯進度,找了個迷宮演算法,嘗試開始用OpenSCAD來實現看看!

我想得太簡單了!

原本我的構想很單純,不過就是將一門語言的實作,改以OpenSCAD實現嘛!應該不難!OpenSCAD沒有畫線的函式,這沒問題,內建的square函式可以繪四邊形,只要寬度設小一些,就可以當成直線繪製了,因此我簡單地實現x_line與y_line兩個module,打算用來繪製迷宮的牆壁,接著我開始想要實作迷宮陣列了。

咦?怎麼迴圈中的變數行為怪怪的?跟我預期的結果不太一樣?

關於學東西要從做中學,還是打好基礎再動手做這件事,一直以來總有不同的聲音與爭論。對我來說,這沒什麼好爭論的,無論選擇哪個,都有人因此而進入大門,也總有人受挫而停止,我本身的話就是看情況或看心情,對於OpenSCAD就是屬於後者,我承認一開始並沒有很認真地看待它,想用到什麼就翻翻線上文件,試幾個簡單的範例確定特性,然後就動手套用。

因為迷宮產生時要需要有反覆的流程,第一個想到的就是迴圈(長久以來受到命令式語言的訓練,就是如此),然而,其中變數的特性令人狐疑了,腦海中浮現了某種典範的可能性,帶著懷疑的心情建立了一個向量,然後試著想改變其中的向量值,中獎了,果然得到一個大大的錯誤,它是Immutable的!我很快地調查了線上迴圈,有關於module、function、for迴圈等語法……

印象中確實曾經看過,OpenSCAD之所以會有不同語言的Porting,是因為OpenSCAD語言表述能力的問題,忽然之間我就懂了「表述能力」某些部份是指什麼了,這(幾乎)是函數式語言啊?!一些看似命令列中才會有的元素,像是for迴圈等,其實只能在module中使用,就像函數式語言中非純粹的部份,function中就是一堆無副作用的運算,相當於函數式語言中純粹的部份。

失敗也是養分

從做中學這回事,本來就是遇上什麼困難,就想辦法加以解決,因此而獲得解決任務中最關鍵的知識,而不是那些用不上的枝微末節。

然而,付出的代價,就是搜尋答案與自行試誤的時間,而且,你必須有把過程中每個失敗都當成養分的心理準備!

我寫的迷宮演算法其實本身並不難,如果用Java寫,加上畫圖大概半小時就可以寫完,程式也只需要幾十行,然而,使用OpenSCAD實作,卻花了我十幾個小時!

會花那麼久的時間,是因為OpenSCAD的特性,實際把頭洗下去才發現,它幾乎就是純函數式語言的風格,對迷宮演算過程經常需要記錄與修改迷宮走訪狀態來說,它的Immutable與function中沒有迴圈的特性,對習慣命令式思維的人來說就會傷透腦筋,絕大多數的時間,我都花在翻轉命令式流程成為函數式流程之上。

中間的小挫折就不說了,即使我對函數式語言有著一定程度的認識,實作的過程中,幾度因為最終結果不正確,而產生了放棄的念頭,歸根究底,多半是對流程想得不夠清楚,命令式一行就可以解決的事,函數式可能得拆成四、五個步驟,在用OpenSCAD寫迷宮演算法的過程中,思緒被整個翻轉過來了,再簡單的運算都得轉成函式,沒有修改狀態這回事,只有直接建立新狀態,而整個腦袋就是一直遞迴、遞迴、遞迴……

第一個晚上初次的失敗,還在預料之內,想說休息一下,明天再試試;第二天重新做更細部的分解,結果更令人沮喪,我發現自己設計的資料結構方向完全錯誤,這代表著至今寫的module與function,幾乎都要砍掉重練。

於是,我開始想著乾脆手動設置迷宮向量好了,只是,這太蠢了,而且根本就不是隨機迷宮了,該放棄嗎?時間都花了,頭都洗下去了,沒弄出來好可惜,這樣的念頭,讓我想先放著,轉換一下心情,試著隔日再來挑戰。

一個字,就是「爽」

靈光一現的感覺,開發者一定都曾有過,我在晚上睡覺時就又還是想著隨機迷宮這件事(對健康來說不是個好習慣),想著想著,竟然想到了另一個方向,對於睡前的靈光一現,我都下意識地命令自己,躺著就躺著了,一切等明早起床再說,這樣才會有個清楚的腦袋。

不過,實際上,隔天再戰的結果又失敗──迷宮產生了,但是,有些牆不見了!

然而,產生出來的迷宮非常接近成品,我知道整體方向是對的,一定只有一、兩個地方運算錯誤,才會導致重複拆除了某些牆面,我從頭逐一測試了每個function,確保它們如預期地運作,實際上修正的bug超過一、兩個,然後就突然在某次按下存檔的那一刻,出現了完美的迷宮,此時,心中第一個浮現的,反而是問句「我成功了?」

接著下一秒鐘,就完全是個「爽」字了,突然間,之前的挫折感都變成了成就感,而先前翻譯時累積下來的苦悶,也隨著這結果的產生,而整個紓解了。

我在Thingiverse及Twitter等Social Media上,分享了我的作品,看著一堆人轉推、按like,說「好酷」、「問這是怎麼做到」之類的時候,突然,就讓我想起第一次用Java寫出記事本時的開心與喜悅!

有個算耳熟能詳的廣告樣詞,大致上是「在追求完美的過程,別忘了最初的單純」,說實在地,這個迷宮產生器寫得很亂,效率也一定沒有很好(需要重構一下,不過,那是改天的事了),然而帶來的一個字,就是「爽」!

回想一下,當初的你,是不是也是因為這樣的爽度,而跨入程式設計這個領域呢?

現在的你在做些什麼呢?很久沒有這種感覺了嗎?如果是的話,找個時間、找個題目,直接把頭洗下去就對了!

專欄作者

熱門新聞

Advertisement