追求神乎其技的程式設計之道(一)

分享Share on Facebook457Share on Google+5Tweet about this on Twitter0Email this to someone

最近有讀者問到我學寫程式的方法和經驗,讓我一下掉入時光隧道回想起當初用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經驗了…)

(待續)

分享Share on Facebook457Share on Google+5Tweet about this on Twitter0Email this to someone

46 thoughts on “追求神乎其技的程式設計之道(一)

  1. 謝謝你!給現在的我一些省思~

    學習東西就是要有個目標,才會學得快又好
    不過你那時玩mud怎麼沒去學lpc咧?

    我也很期待下集!加油~

  2. Pingback: 祖母綠菜園

    • 我很小的时候玩任天堂卡带。我问我爸,卡带怎么做的。我爸只知道芯片是激光雕刻的,就说卡带是刻出来的。之后我就经常幻想着有一天能拿着刻刀,刻出一块布满密密麻麻电路板的卡带来。
      再后来,我终于当上一个游戏程序员……

  3. Pingback: 追求神乎其技的程式設計之道(六) | vgod’s blog

  4. 冒昧打擾~從”鳥毅的Blog”那看到你的文章真是有感而發
    因為我也是qbsic出身+1996台灣北區第三名 比賽內容就是用qbasic 做很多項目 包含”3D”,
    QBASIC國內書籍很少 要靠各方面資訊不斷 研究出可行的功能 很多數學函式才建構成3D函式.
    因該你也還記得svga下畫面 不再是單張畫面 而是程式運行下的動畫 的感動..
    mode當然要搞個bbs交流哈啦唯一途徑.
    當初我記得並沒有ioi…………..有話要更努力.
    寫程式真的要有興趣,想當初我成績是放牛班而且是倒數前三名+還好有個肯欣賞有用氣的老師提拔.
    想當初熱血少年程式語法過目不忘書都可以不用翻…現在都翻書比較快
    當屆北區(1.開南+2.大安+3.開平)如果可以我也想出國阿~~~~~~~~~~(窮 英文又爛 下輩子吧)
    感覺自己不孤單了 至少還有個類似我一樣的心路歷程(所有同好一起努力的都沒再摸程式了..一堆mis++剩小弟孤軍)
    打擾啦~(國文很差+請見諒)

  5. Pingback: 追求神乎其技的程式設計之道(七) | vgod’s blog

  6. Pingback: 追求神乎其技的程式設計之道(八) | vgod’s blog

  7. Vgod先生 您好:
    最近剛學C(學校課程),從別的網站連結到這篇文章,剛看完第一篇忍不住有問題想請教一下^^”

    文章中有提到”古老的程式設計教材(尤其是C語言),都說要把變數宣告在函式的一開頭”、”我歸納出一個原則:「永遠在變數需要被用到的最內層區塊才宣告並初始化該變數。」”

    一開始老師介紹C語言時,有提到一個程式分為兩個區塊:”資料宣告定義”和”執行程式碼”(傳統C是分開的,不過C++是可以混的)。
    所以我不太懂”在變數需要被用到的最內層區塊才宣告並初始化該變數”的意思。是說可以在程式碼裡再定義變數嗎?還是指一個程式裡有很多function,每個function有用到的變數在function裡定義而不要在程式最初定義?

    剛巧前不久碰到的小習題也是需要初始化變數。不過那時候function剛教,還不是很熟悉(雖然距現在沒多久也不是很熟XD),所以我是把輸入、處理、輸出全寫在同一個程式裡(後來老師有強調程式應該清楚分這三部分,其中只有輸入輸出在主程式,處理要用function)。而我選擇的方式正是在最後(迴圈之前)讓它初始化,所以看到這篇真的是心有戚戚焉^^”

    這篇文章真的喚起很多記憶,從DOS(不過我沒看過貪食蛇,也許有,不過印象深刻的是一堆英文字(指令)、非常大的磁碟片和三國的格鬥遊戲、泡泡龍XD)、蘋果、windows系列,還有網頁的純文字RPG冒險遊戲。不過那時還小,每個時期都是眼巴巴地看著哥哥們在玩XD。小五、六還是國中時也曾有雄心壯志想學程設,結果VB自學沒多久就放棄了。後來又因為哥哥讀資工,想說不要走同一條路。沒想到大學有這門必修,也幸好有^^
    嗯,廢話不多說,繼續往下看^^”

  8. Hi ginny,

    C的變數宣告位置有兩種, 一個是function外的global variable,一種是任何block(也就是上面講的區塊)內的local variable。一般會被忽略的是,所謂的block是指任何由大括號{}包起來的範圍,而不是只有function而已。所以,不管是for、if、while的大括號開頭其實都能宣告變數。我所說的在最內層的區塊需告也就是在你真的需要用那個變數的最內層大括號裡在宣告就好。

  9. Pingback: 網站製作學習誌 » [Web] 連結分享

  10. 大大!!
    恕我說話較直接~

    從您的文章來看...
    從一開始您就踏錯了第一步~
    之後還步步錯!
    為什麼呢?

    因為...
    如果您開始是學c語言的話...
    basic這樣的語言,這玩意兒根本就被您當玩具呀!
    因為最難的已經學會...
    之後再看這個已經不算什麼了...

  11. 大大
    恕我說話比較直接…

    從大大的這一篇文章看來…
    一開始就是錯誤的開始~
    而且之後還步步錯~
    為什麼呢?

    因為…
    如果大大從C語言開始接觸的話…
    Basic這樣的語言,根本就是被您當玩具玩呀!!
    因為最難的都已經學會…
    在來看這樣的語言已經是小菜一碟了~

  12. 您好!我是在噗浪上偶然發現您的~^o^
    我正在自製遊戲~不過我是個完全沒有寫程式基礎的人~
    專長只在劇本和插圖方面, 但還是很努力地想在不需太多妥協的情況下獨力完成一件完整作品^_^
    目前選用的軟體是最容易入門的Nscripter~也有在學吉里吉里~
    但即使是使用像這樣易懂易用的工具也還是體認到如果有程式的概念的話會更好>_<
    雖然一直有想學的念頭, 但又總是為了太晚起步而裹足不前~
    今天看了您的文章之後又重新燃起了熱血的心情~
    雖然大概還是不會去從頭學寫程式啦哈哈哈XD
    不過對於目前碰到的瓶頸似乎更有勇氣去追根究底的解決它了呢!^o^
    所以想要對您說聲謝謝喔!^_^

  13. Pingback: 追求神乎其技的程式設計之道(九) | vgod’s blog

  14. 你好!
    偶然看到你這文章~
    我也跟你一樣有這樣子的執著力,
    但要像你有這樣子的本事…我還差的很遠…
    推廣你的文讓更多人看唷~~

  15. 我寫程式二十多年了,一度被大陸人稱為黑客之神,在俄羅斯排名第五,
    你寫了十多年,為何好像跟剛入門的Programmer一樣,追求一項根本不存在的事物.
    神乎其技的程式設計之道,根本不存在,原因在於你忘了Programming的目的.
    Computer就是計算機,也就是工具.適當的工具用於適當的用途,
    過之則不當.二十多年來,我累積的Source Code高達五百八十萬行,
    從來以實用為主,爛Code產生好結果,漂亮的Code產生爛結果,我天天見到,
    我絕對有幾百種技巧可以達成你說的那些目的.

    但是你忘記了本質,所以捨本逐末,追求Programming技巧,而不問為何要去Programming.
    寫程式是因為我的本業(天體物理)很需要這項技能,結果許多好事者,把我這項技能誇大了.
    我們Programming是為了要解決實際的問題,你追求技巧目的是為何呢?

    • 我寫程式一向是以實用為主,也就是為了解決問題、或是滿足人類需求而寫。
      我不知道神乎其技的程式設計之道到底是什麼或是它存不存在,這其實也不是那麼重要,
      但我想如果我持續對programming這個「工具」本身做思考,工具也是能夠持續進化,
      並且從根本改變programming的方法。反之,如果一昧的使用工具不去思考工具和使用方法的好壞,
      那豈不像是coding monkey一樣在鍵盤上敲敲打打,即使敲了百萬行的程式碼也仍是隻monkey。

      簡單的說,我追求的不是在某種程式語言或是寫某個程式所需要的技巧,我追求的是從
      源頭顛覆寫程式這件事的方法。或是換一個說法,我覺得現有的programming方法和工具仍然不夠好,
      我想解決的問題就是讓每個人都能更輕易更有效率的寫程式。

      • Hi vgod, 我也是從小開始學寫程式,7 歲的時候學 GWBASIC,而你說的剛好也是我想追求的 🙂
        只不過你在學術的殿堂做研究,而我在台灣一家小公司上班 -.- 悶~ 我也好想做研究啊~~

  16. (刚才reply错地方了,重发)

    我很小的时候玩任天堂卡带。我问我爸,卡带怎么做的。我爸只知道芯片是激光雕刻的,就说卡带是刻出来的。之后我就经常幻想着有一天能拿着刻刀,刻出一块布满密密麻麻电路板的卡带来。

    再后来,我终于当上一个游戏程序员……

  17. Pingback: 追求神乎其技的程式設計之道(十) | vgod’s blog

  18. Pingback: 轉錄-追求神乎其技的程式設計之道 | nota

  19. Pingback: 追求神乎其技的程式設計之道(十一)- 抽象化與命名 | vgod’s blog

  20. Pingback: GWeekly[9] = 程序猿生活开始 – 我住包子山

  21. Pingback: Teach Yourself Programming in Ten Years & 追求神乎其技的程式設計之道 | CE1001 計算機概論

  22. Pingback: 好文: 追求神乎其技的程式設計之道 | 當代科技 TechNow.com.hk

  23. 沒想到竟然會看到KK這個名字,實在太懷念了, 我會開始寫程式就是從zMUD的練功機器人開始呀!

  24. vgod,請問您在追求神乎其技的系列當中,
    有提到您花了一個月學習c語言,
    可以請教您當時是讀哪一本嗎? 謝謝您 🙂

  25. 我當時讀了很多本書耶.. 因為我看一本書都沒辦法完全吸收, 所以習慣一次大量閱讀同主題的書再自己截長補短。那時也不懂得分辨好書和壞書,所以基本上台中圖書館找得到的C語言的書籍我全都看過了..

    • 謝謝vgod 🙂
      那請問是原文和中文都有嗎?
      我正在煩惱該看原文還是中文..有人說沒差 有人又說原文比較好..

      • C語言我只看了中文的, 那時看英文太慢了.. 學C的話看中文書沒什麼差別, 因為C本身存在很久了, 不是什麼新東西一定要看英文的才行

  26. hello, Vgod…

    I wondered if you could share your algorithm analysis of sikuli image recognition… what could we do if we wanted to adjust the precision of image matching?

    looking forward for your reply ^^

  27. 當小弟在寫程式或玩解ACM題, 來這朝聖使得動力奮發向上!!!!
    希望未來能有VGOD的1成功力就好QQ

  28. 神乎其技呀~~
    恩,其實我是認為像程式這種東西沒有所謂的完美,
    大概也是受我男朋友影響的吧?

  29. Pingback: pinoy comedy movies

  30. Pingback: 追求神乎其技的程式設計之道(一) | vgod's blog - 熱點新聞網

留言給我吧!