有好一段時間沒來貼文章啦,最近找資料剛好有看到一篇還不錯的,在此奉上。
最近有讀者問到我學寫程式的方法和經驗,讓我一下掉入時光隧道回想起當初用VB寫出自己第一個遊戲時的成就感,但當初沒料到的是我真的就此迷上了電腦和寫程式的快感,不知不覺也過了10年的光陰…。在這篇文章中,我想寫出我對程式設計的看法和我一路學習上來的歷程和經驗。寫程式是一條無止境的道路,不只是科學和工程,更是一種藝術。而我還在追求「神乎其技」的半路上,雖然還有很多要學的,但我也希望能讓初學者更容易看清楚這條路是什麼樣子,避免陷入盲目追求新技術的死巷中。
一切的開始
如果是從DOS時代開始玩電腦的玩家,應該都知道當初DOS有兩個內建的QBASIC小遊戲:貪食蛇和猩猩丟香蕉。這兩個小遊戲是許多人兒時共同的回憶,我還記得我國小時曾有幾堂電腦課,當時老師在台上嘰哩瓜啦的不知道在教什麼,而台下每台電腦都是貪食蛇或丟香蕉的畫面(老師對不起,其實我就是帶頭做亂的罪魁禍首…)。
微軟把這兩個QBASIC遊戲附在DOS內對我產生了莫大的影響,那是我第一次發現到原來QBASIC和不只是像PE2能打打字而已,QBASIC竟然能把一堆看起來像咒語的文字變成遊戲!幸運的是我家剛好有本第三波的QBASIC入門書,沒事我就自己拿起來翻著看,雖然當時太小,即使把整本都看完了還是搞不懂貪食蛇是怎麼寫出來的,但也誤打誤撞知道了原來這就是程式設計,原來我能直接把貪食蛇檔案內的一個數字改掉就能有幾百條命可以死,原來學寫程式就能做出電腦遊戲…。對小孩子而言,知道這些事就像告訴他魔術師袖子裡的秘密一樣,我一天到晚興奮地要老爸帶我去書局看電腦書,彷彿真的可以搞懂電腦螢幕背後的一切魔法一樣,我也夢想著有一天能寫出自己的遊戲。但當時我沒想到的是,我還真的花了十幾年的時間在探索電腦的魔法…。
MUD與黑白棋
升上國中後,家裡裝了一台28.8kbps的modem,當時的internet還沒完全成形,在沒有Google的時代internet是沒什麼價值的。當時的modem最常被我拿來上一些撥接式的BBS,那時候的撥接BBS站台還不少,最棒的是還能從站上抓到很多軟體和各式各樣的教學文章,像是如何用組合語言寫電腦病毒,如何破解大富翁2之類的文章。這些文章對當時的我就像武林密籍一樣,雖然沒辦法完全看懂,但我也是從中得到很多零碎的概念,像是16進位的換算、組合語言、中斷向量、常駐程式….。
在國二時,我還不小心迷上當時一個超熱門的MUD – 萬王之王(KK),每天放學回家都急著連上線,讓家裡電話整晚都忙線中,玩到每個月電話費都是上千元,搞得我媽數次警告要把modem收起來再也不讓我上網了。(還好她沒真的這麼做,不然我現在就沒辦法寫這篇文章了。)
MUD是現在MMORPG的純文字版,整個虛擬世界都用文字描述,並且只要用telnet就可以連上去玩了。但內行的玩家都知道,玩MUD應該要用zMud或是UNIX下的tintin++,因為這兩個軟體可以設定所謂的trigger,偵測到某些事件的發生,就能自動採取事先指定好的動作。因為一切的訊息都是由文字呈現,所以偵測事件非常簡單,只要看看有沒有特定字串出現就可以了;而要做特定的動作也很簡單,就是送出文字指令而已。(眼尖的人一定會發現,這其實就是現在MMORPG外掛的最原始形式。)嚴格說起來,zMud是我首次寫「實用程式」的平台,我學會透過trigger在MUD的世界中寫自動化的機器人,自動在迷宮中遊走,自動換裝備打怪練功..。這時的我突然體會到,會寫程式真是太棒了,我在MUD中簡直跟神一樣。其實當時我也不過只會用最基本的變數、if、迴圈而已,但透過在虛擬世界中寫機器人的練習,讓我的邏輯思考概念有飛快的進步,也給我了非常強烈的動力想好好學一個正統的程式語言。
升上國三後,很幸運的透過推薦甄試提早上了台中一中,升學壓力解除後,老師和父母就完全不管我要幹麻了。這時我終於有了一段完整的時間可以好好的再把BASIC重新學過,無奈的是在我國三時QBASIC已經快滅絕了,取而代之的是Windows上的Visual Basic,我只好硬著頭皮買本新書來從頭學起VB。當時我看的是王國榮的VB 5入門書,整本書有六七百頁吧,比我國三所有課本疊起來都還厚,現在想想小時候真的有點不知天高地厚竟然相信自己能看完這麼厚的磚頭書。那時候我每天上課就帶著這本磚頭去學校,這樣看了幾個禮拜下來,沒想到我這時突然都看得懂了,很多原本不知道有什麼用途的概念突然都相互連結起來了。(多虧了在MUD裡的訓練!)就這樣,某天突然有種打通任督二脈的感覺,我發現我全搞懂了,迴圈、陣列、Windows GUI控制項、去背貼圖…,我突然想通要怎麼用程式語言寫出遊戲了。
從那之後,每天回家就是打開VB寫程式,我想寫個黑白棋來檢驗自己的想法,我把自己知道的所有概念都放進去,有GUI元件、有貼圖、有動畫、有音效..,這是我第一個完整的程式,從頭到尾每一行都是自己寫出來的。(以現在的眼光來說只能說是一個期末project規模的小程式,但對當時的我可是意義非凡)
這個黑白棋讓我印象最深的其實是debug的痛苦經驗。我花了一個禮拜把程式的核心部分完成,但在吃子的時候卻跑出一個不明的bug會打亂整個盤面。為了找這個bug,我又花了一個禮拜,每天從早到晚都在想哪裡寫錯了,後來慢慢trace了好久,才發現竟然只是一個變數忘了歸零!!!
這種bug很常見,不過只是programmer最容易犯的無心之過之一,但這件事對我的影響非常大,它讓我花了很長時間在想以後要怎麼避免犯同樣的錯。我後來才知道一個普通的programmer和厲害的programmer從這裡就會分出高下:普通programmer犯了這種錯會覺得很平常,並提醒自己下次別再這麼笨了,但實際上不久後一定又會再犯同樣的錯;厲害的programmer會反省自己寫程式的方法,並改變原有的方法或習慣來避免以後再度產生同樣的bug。
古老的程式設計教材(尤其是C語言),都說要把變數宣告在函式的一開頭,並且因為變數宣告完還得經過初始化,所以很多人習慣是在函式開頭宣告並初始化所有變數。這不是錯的,可是,這其實就是會導致bug的元兇。
因為變數在開頭就被初始化,這樣在真正要用到它的時候就能直接拿來用,但是如果這個變數需要被歸零(也就是重新初始化)並在迴圈中重複利用,就很容易會忘記要再多做這一步。(在多層迴圈中更容易發生)
我為這個bug苦惱了幾天,後來才意識到這是coding style的問題,只要改變宣告變數的習慣,就能避免犯這種錯誤。如果一開始就在迴圈內宣告並給定變數的初始值,而不是在函式開頭宣告,就不會有這種bug跑出來了。有了這個經驗後,我歸納出一個原則:「永遠在變數需要被用到的最內層區塊才宣告並初始化該變數。」這種原則很重要,我日後一直放在心裡,它也幫助我避免掉未來再犯同樣錯誤的可能。(事實上,我後來再寫了十年的程式,再也沒有比這更痛苦更長久的debug經驗了…)
轉貼來源:
留言列表