2009年1月10日

Java輕鬆玩 - 認識更多Groovy的語法

Java輕鬆玩(Java for Fun)」 系列文章,想要讓一些有電腦基礎、但不太會寫程式的朋友,也能夠在喝杯咖啡的午後時光,悠閒地利用Java創作電腦程式。寫程式是件有趣的事,就像小時候 玩的積木,能夠訓練邏輯思考及培養創造力,也純粹就是為了好玩而已。有趣的前提必須是「為自己的樂趣寫程式(Coding for Fun)」,自己能夠做出工具解決問題,將會有充滿成就感的快樂。我們假設你每天都能有30分鐘的時間可以"玩樂",先花個10分鐘把我們的教學短文看 完,跟著完成設定及範例程式碼,接著就能用20分鐘把它重新組合,用您獨特的想法創作出自己的程式。

如果你已經準備好

這篇文章準備帶你認識更多Groovy(或者應該說也包含Java)的語法,假設你已經安裝好JDK與Groovy,並且通過第一課的閱讀之後,確定你真的還是清醒的狀態。這裡將不會出現教你程式碼要貼在哪邊、按什麼可以執行之類的基礎,我們已經用第一課全部的篇幅來告訴你該怎麼做,如果還是不懂沒關係,請將我們的文章拿去請教隔壁那位念國中的大哥哥,或是對街那位已經退休的老爺爺。千萬要記得,別去問你那些心機很重的同學或朋友,他們看了之後會好心告訴你別去學這些東西,回家卻關起門來偷偷打開玩物尚誌,自己玩得不亦樂乎。

從一數到十

為了讓念小一的朋友也能輕鬆玩,我並不想教你怎麼從一數到一百,或是從一數到一千,那會讓沒唸過幼稚園的朋友很吃虧,我不想像那些小學老師一樣,假設大家都已經有基礎,所以跳過不教。

那我們開始寫程式吧!在你的GroovyConsole輸入以下的程式碼。

println 1
println 2
println 3
println 4
println 5
println 6
println 7
println 8
println 9
println 10


執行後你會看到畫面上真的從一數到十,如果你自己把這些程式碼從頭打到尾,你可能會認為這樣寫程式實在有點蠢,萬一真的要從一數到一千,那不就要花整晚時間才能寫完嗎?

我想告訴你一個好消息,如果你遇到一個用程式行數付你薪水的老闆,願意提供寫一行給一元的價碼,那你已經賺了十元。在某些軟體開發的評估方式下,你只要善用這樣子寫程式的技巧,將有機會成為生產力最高的那位程式達人。

很多教寫程式的書,會告訴你這種重複的事情,必須用迴圈來做,而有特定範圍、次數的事情,則可以用FOR迴圈,這種寫法讓你只用一行就可以取代上面的十行,以下這行程式碼跟很多程式語言的寫法很類似。

for (i=1; i<=10; i=i+1) println i

在括號中用分號區隔成三個項目,i=1意思是剛開始先把i設定為1,i<=10則是限制i不能大於10,i=i+1則是在這個限制下,每次都加上1。雖然我想告訴你i是個變數,但你不用去弄懂什麼叫做變數,或是for迴圈為甚麼要這樣寫,你唯一需要之到的事情,就是當你想從1數到1000,或是從1數到10000的時候該怎麼修改,以下的練習只花你五分鐘,但你會弄懂這一切。

練習一:從1數到11
練習二:從1數到11,跳過偶數(就是2的倍數,2、4、6、8…),你只能改程式中的一個數字
練習三:從3數到11,跳過偶數

如果Groovy只能這樣寫,那有什麼好玩的,只是比Java少了個行尾的分號。所以我們想教你的,就是遇到這種問題的時候,別再去用什麼標準的FOR迴圈,那是學校在教的事。學校沒教你的事,就是Groovy也可以像下面那樣做。

方法一:
for (i in [1,2,3,4,5,6,7,8,9,10]) println i

方法二:
for (i in (1..10)) println i

方法三:
[1,2,3,4,5,6,7,8,9,10].each {
  println it
}

方法四:
(1..10).each {
  println it
}

方法五:
1.upto(10) {
  println it
}

方法六:
10.times {
  println it+1
}

你只需要知道這些程式碼都有同樣的作用,並且試著照你的想法去修改,只要改完還是能夠執行就好。不必弄懂所有語法的細節,那些並不重要(It doesn't matter),除非你是想參加考試而不是玩樂。



你必須知道的事情還包括IF判斷式,它的語法構造如下。

if (1+1 == 2) println "一加一等於二"

如果你想判斷兩個東西是否相等,請記住要用兩個等於(==),這沒有為甚麼,因為一個等於(=)已經有其它用途,所以才需要變兩個,語法就是如此。

在上面的例子中,我們判斷1+1是否等於2,是的話就用中文白話顯示出來,很簡單的一個例子。那如果要處理不等於的情況,該怎麼做呢?

if (1+1 == 2) println "一加一等於二"
if (1+1 != 2) println "一加一不等於二"

沒錯,正如你所想的「!=」就是不等於的用法,但是上面的兩行程式碼,執行之後仍然只顯示「一加一等於二」,那第二行「一加一不等於二」跑到哪去了呢?只能說,如果1+1真的不等於2,那你就看到鬼了。

if (1+1 == 2) {
  println "一加一等於二"
  println "早就知道了"
}
else {
  println "你見鬼了"
  println "趕快去拜拜"
}

上面的else必須搭配if,意思就是當判斷的條件不成立時,就做另一件事情,這讓你不用像上上一個程式碼必須寫兩次判斷條件。在這個範例中我們還加上「{」、「}」的大括號,因此我們可以在條件成立或不成立時,多做幾件事情,例如範例中做兩次println的動作。

在FOR迴圈也可以搭配大括號,例如:

for (i in [7,6,5,4,1,2,3]) {
  if (i==1) println "星期一,猴子穿新衣"
  if (i==2) println "星期二,猴子肚子餓"
  if (i==3) println "星期三,猴子去爬山"
  if (i==4) println "星期四,猴子逛夜市"
  if (i==5) println "星期五,猴子在跳舞"
  if (i==6) println "星期六,猴子要開溜"
  if (i==7) println "星期七,猴子變北七"
}
小技巧:在GroovyConsole寫程式,每次執行之後,訊息輸出區會累積愈來愈多輸出結果,這時候請使用上方選單的「View」→「Clear Output」清除,也可以用快速鍵「Ctrl」+「w」。
別去想太多怎麼樣寫才是對的、才是好的,只要程式碼能夠照著你的想法執行,才是最重要的事。為了讓你可以理解FOR迴圈與IF判斷式怎麼組合應用,我們將以無名小站的相簿首頁為例,寫一個很短的小程式,可以將熱門相簿的名稱顯示出來。

//為了避免你打字錯誤,請盡量用複製貼上^^
for (i in (1..2)) {
    url = new URL("http://www.wretch.cc/album/?func=hot&hid=6&class_id=0&page=${i}")
    conn = url.openConnection()
    conn.setRequestProperty('User-Agent', 'Mozilla/5.0')
    conn.inputStream.eachLine 'UTF-8', {
        if (it.startsWith('                  <strong>')) {
            println it.replace('                  <strong>', '').replace('</strong>', '')
        }
    }
}


短短的十行程式碼,就已經滿足我們需要的功能。不必管程式碼中看不懂的部份,只要注意這篇教學中要告訴你的基礎語法,就是用粗體字標示的部份。請試著執行看看,它可以將無名熱門相簿首頁列出的相簿名稱全部顯示出來,而且還可以找到其它頁底下的資料。最外層的for迴圈,目的就是處理分頁,(1..2)就是顯示從第一頁到第二頁的內容,可以將數字修改成你想要的那些頁面,試著應用前面FOR迴圈教學告訴你的那幾種不同方法,改寫這個小程式,並讓它的功能維持正常。在if的判斷部份,則是用來偵測網頁原始碼中的某一行,是否包含相簿名稱,如果有則用println顯示出來。

這個範例程式只要再增加一些程式碼,就可以變成能夠顯示縮圖的視窗程式,為了回饋讀者辛苦地看完這篇教學,以下的程式碼送給大家。

import java.awt.*
import javax.swing.*
import groovy.swing.SwingBuilder

labels = []
images = []
for (i in (1..2)) {
    url = new URL("http://www.wretch.cc/album/?func=hot&hid=6&class_id=0&page=${i}")
    conn = url.openConnection()
    conn.setRequestProperty('User-Agent', 'Mozilla/5.0')
    conn.inputStream.eachLine 'UTF-8', {
        (it =~ /http:\/\/f[0-9]+\.wretch\.yimg\.com\/[A-Za-z0-9]+\/[0-9]+\/thumbs\/t[0-9]+\.jpg/).each {
            images << it
        }
        if (it.startsWith('                  <strong>')) {
            labels << it.replace('                  <strong>', '').replace('</strong>', '')
        }
    }
}
labels = labels.reverse()
images = images.reverse()
frame = new SwingBuilder().frame(
    title: '無名熱門相簿首頁',
    size: [800, 600]) {
    scrollPane {
        panel(layout: new GridLayout(0, 3)) {
            labels.size().times {
                label(icon: imageIcon(images.pop().toURL()), labels.pop())
            }
        }
    }
}
frame.show()


執行的結果如下圖。


這個程式碼除了IF及FOR語法的示範,還包含網路存取、SwingBuilder、RegularExpression等其他Groovy的功能,後續的教學將在適合的時機讓您弄懂這些。到目前為止,你只需要瞭解IF及FOR的語法即可。

* 本文發表於玩物尚誌,《Java輕鬆玩》系列文章的網址為「http://blog.lyhdev.com/search/label/JavaForFun」。版權所有,採用「創用CC授權」條款,歡迎非商業用途之分享與引用,並請保留作者或出處之標示。

5 則留言:

  1. 剛剛在玩『顯示縮圖的視窗程式』突然跳出令人臉紅心跳的縮圖.............XD

    我們的辦公室屬於開放式沒有隔間的那種~_~

    回覆刪除
  2. 這就站長的不對了!
    應該要註明,想fun鬆學,得回家關起門來學…ㄎ

    回覆刪除
  3. 是的,我們未來會比照電視分級將文章貼上標籤與警告標語,但基本上一律兒童不宜。

    回覆刪除

lyhcode by lyhcode
歡迎轉載,請務必註明出處!