顯示具有 Java 標籤的文章。 顯示所有文章
顯示具有 Java 標籤的文章。 顯示所有文章

2008年9月23日 星期二

就是愛計較 (Java版)

記得在幾個月前,曾經也動手要寫一個記帳的程式,來記錄每一天的開銷。但寫了一小部份後,開始對於該如何存放資料感到煩惱,感覺用一般的檔案讀寫,不是很符合程式的需求,因為隨時都可能須要對過去的資料做查詢、刪除及一些處理,用資料庫系統來管理會比較適合。但說到資料庫,若要求每個使用者都自己先建好一個可用的資料庫又不太可能,所以這個程式就開始停擺沒寫了。

前些日子,看到昔日的強者同學剛好也寫了一個記帳程式,發現他是用一種嵌入式的資料庫SQLite,也就是可以和所開發的程式包在一起,程式啟動時同時也啟動資料庫,感覺蠻適合用來開發程式的。但由於SQLite是用C寫的,所以便開始想找找看有沒有用Java寫的嵌入式資料庫系統,很幸運的被我找到了,原來在Java 6本身就已經包含一個名為Java DB(Apache Derby)的資料庫系統,所以就開始著手找一些相關的文件,學學如何使用Java DB。

既然資料庫的問題解決了,所以便打算重新繼續開發記帳程式,在寫程式之前,有先參考了這位強者同學寫的記帳軟體,因為我使用者介面的設計能力真的很差,所以介面就有點模仿他的,但功能還是沒有他寫的完整就是了,大家可以到下面網址使用他的軟體。

豬頭記帳


接下來就來簡介一下自己寫的程式,當然是不能和強者同學寫的相提並論,我只是單純練習用的。

程式下載區

程式外觀主要有四個分頁

  • 新增記錄 - 可用來新增每一筆的收入與支出,類別的部分可以自行修改,下面會列出最近十筆的輸入資料。

  • 資料統計 - 列出本日、本月、本年以及全部的收入支出總額,另外以圓餅圖來顯示所有支出中,各類別所佔的比例。


  • 檢視/刪除 - 可以用來查詢任何一天的記錄,並刪除該筆記錄。



  • 類別設定 - 可以修改、新增、刪除類別與子類別項目,若修改或刪除的類別或子類別包含已存在的記錄,則該筆記錄的類別或子類別項目會變成不分類。




第一次寫程式用到資料庫系統,雖然研究所時修過資料庫系統,但真的都忘的差不多了。害我趕緊把書給挖了出來,但由於我把系統寫的很單純,所以也沒有用到什麼複雜的查詢。資料庫系統真是一門很深的學問,我還要再多學學才行。

在寫這一個程式時,漸漸發覺當程式功能愈多的時候,還是多人一起開發會比較輕鬆吧,雖說這個程式沒有很大,但因為很多東西都第一次碰,所以寫到最後,開始有點討厭程式。其實本來預期的功能應該不只這些,只是有點累了,就先寫到這樣吧!

2008年9月14日 星期日

防禦SQL Injection

SQL Injection一般指使用者藉由輸入的資料內嵌的SQL指令來攻擊系統。

例:一個登入系統要求使用者輸入帳號密碼

若程式碼為下:
String sql = "select * from user where username='" + username +"' and password='" + password + "'";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);


若使用者已知某帳號如admin,可輸入admin'--。或是用未知的使用者登入,可輸入'or 1=1--,密碼欄位亂填,則SQL語法將變成:

select * from user where username='admin'-- and password='xxxx'
select * from user where username=''or 1=1-- and password=' '

即可成功登入系統,--為註解。

Java程式語言可以用Prepared Statements來解決,也就是預先參數化你想要的SQL語法。

例:
String sql = "select * from user where userId = ? ";
PreparedStatement preparedStmt = con.prepareStatement(sql);
preparedStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();

如此便不用擔心userId變數包含SQL語法了。

2008年9月8日 星期一

樂透機(Java版)

最近怎麼開始都在寫簡單的程式了呢?主要是因為恰巧有這個需求,所以就順手來寫了一個。像若是單純只寫文字介面的話,只要短短幾行就寫好了。不過,我想或許其它人也有這個需求,所以就把它寫成視窗程式,有興趣的可以下載使用看看。

程式下載區 (若不能執行表示你的系統未安裝JRE 6)

IE好像下載時會將以.zip儲存,若要正確執行,請將附檔名改成.jar。


例:希望從1到1000中,隨機產生5組號碼,且這5組號碼可以重複。

執行畫面如下:




所以,功能很單純。就是使用者可以自己設定一個範圍,並選擇想要產生幾組數字,按下好運氣,結果會產生在下面。像大樂透的玩法是1到49任選六個號碼,所以就可以在程式中輸到1和49,選擇6組數字,千萬別勾選可重複號碼喔!

p.s. 要是真的那麼好中就好了,所以千萬別這樣就簽下去了,除非你是抱著做公益的心態去簽^__^

2008年8月21日 星期四

單字王(Java版)

自從高中畢業後,就發現自己的英文程度每況愈下。除了文法忘光光外,這幾年在大學或是研究所,增加的英文字彙就僅止於電腦領域。所以,就突發奇想,寫了一個小程式來幫助自己多記憶一些單字。

這次寫的這一個程式(單字王)相當簡單,所以整個程式連一行註解都沒寫,但我知道這是個很不好的習慣啦。

程式下載區 (若不能執行表示你的系統未安裝JRE 6)

程式的功能很單純,主要有三個:

  • 新增:將想背的單字與中文解釋加到單字庫裡。
  • 刪除:可以將單字從單字庫移除。
  • 隨堂考:可隨機從單字庫挑出單字來測驗。

程式執行畫面如下:


註:一開始我有先在單字庫加上一個scarf的字彙在單字庫裡,使用者可以自行刪除。由於隨堂考是採取隨機選取,所以若單字庫的字彙很少的話,很容易會出現複的單字出現。相信隨著時間,大家的單字庫也會滿滿滿的。

2008年7月14日 星期一

Arrays.asList()

我們可以利用java.util.Arrays.asList()來將陣列轉成List。

例:若要初始化一個ArrayList name,包括Howard、Ashley、John

ArrayList name = new ArrayList(Arrays.asList("Howard", "Ashley", "John"));

2008年5月26日 星期一

讀取JAR裡的檔案

可以利用getResourceAsStream()來達成,例:

InputStream instream = this.getClass().getResourceAsStream("file");
BufferedReader br = new BufferedReader(new InputStreamReader(instream));

2008年5月12日 星期一

Java連MySQL中文亂碼

最近用Java連MySQL,發現中文會產生亂碼,這個問題主要是編碼的問題,不只是MySQL要有一點小改變,Java連資料庫的程式碼也要改一些東西:

先修改MySQL部份:
修改my.cnf檔案:
[client]
default-character-set=utf8

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

重新啟動MySQL。此後建立的資料庫都會用UTF8編碼

修改JDBC連線方式:
原本連線只是單純的輸入url, username, password。
要用UTF8編碼,要加上以下兩個參數:
useUnicode=true
characterEncoding=UTF-8

為了方便,可以將jdbc連線的設定值寫在一個檔案裡。用Properties來讀取:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/accounting2
user=howard
password=howardgogogo
useUnicode=true
characterEncoding=UTF-8


連線方式就變成
ppts.load(new FileInputStream("config.ini"));
Connection conn = DriverManager.getConnection(url, ppts);

2008年5月8日 星期四

Java連MySQL

要連線到MySQL必須先有MySQL JDBC的Driver。可以到此下載

String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/accounting";
String user = "howard";
String password = "howardgogogo";

try {
Class.forName(driver);
Connection connection = Driver.Manager.getConnection(url, user, password);
}
catch (ClassNotFoundException ...
...

2008年4月21日 星期一

貪食蛇新功能

貪食蛇又有新功能了,為了讓遊戲更刺激,因此多加了排行榜的功能,程式會把你每次的分數記錄下來,然後會列出目前分數最高的前十名,大家如果有興趣的話,可以來挑戰一下,成為武林盟主吧~~~



此外,感謝小書書的協助,讓版本一下子從1.1跳到2.0

2008年3月29日 星期六

取得Java版本

由於每個使用者所使用的Java版本可能都不一致,因此在程式裡也可以加入判斷使用者所使用的版本有不同的實作方法。

String version = System.getProperty("jave.version");
System.out.println(version);

2008年3月23日 星期日

Volatile關鍵字

Java Memory Model (JMM)讓每一個Thread都可以擁有local memory,將變數複製到register,讓這些變數可以更快速的被處理。然而在multi-thread的環境下,則可能會造成不同步的問題。
因此,thread共用的成員變數會加上volatile關鍵字,目的是要避免將這個變數複製到local memory,而是讓這些變數留在main memory上。

2008年3月20日 星期四

Double Buffering

在寫動畫的程式時,最常發生的問題就是畫面會閃爍了。會發生這個問題的主要原因是每一個裝置都有它的更新頻率。每隔一段時間就會重新顯示畫面,如果在這一定的時間內來不及將整個圖畫上去,就會造成只畫了部份,因此就產生了閃爍。所以,若要保證每次都在這時間內畫好整張圖,就必須將繪圖的動作與更新頻率同步。然而在短時間內能畫出的圖有限,所以通常會將圖先畫在記憶體裡,然後再一次畫在螢幕上。如此便可有效抑制閃爍。

首先,宣告一個Image來當作緩衝區。用createImage的函式來取得緩衝區的物件。呼叫getGraphics可以取得緩衝區的Graphics 物件。接著便和一般用法一樣,用drawImage將圖畫上去。例:

private Image bufferImage = null;
private Graphics bufferGraphics;
public void imageRender() {
if(bufferImage == null) {
bufferImage = createImage(WIDTH, HEIGHT);
bufferGraphics = bufferImage.getGraphics();

bufferGraphics.setColor.white);
bufferGraphics.fillRect(0, 0, WIDTH, HEIGHT);
....
}


再覆載paintComponent
public void paintComponent(Graphics g) {
super.paingComponent(g);
if(bufferImage != null)
g.drawImage(bufferImage, 0, 0, null);
}


如此便可有效抑制閃爍。此外要注意的一點就是儘量保持paintComponent()簡單。因為他可能會JVM呼叫,例如當視窗被別的遮住後又移開。

2008年3月16日 星期日

小丸子之暗棋連線 (Java版)

花了將近兩個星期終於完成了。由於對網路程式的部份比較不熟悉,一度覺得應該寫不出來了,好在,終於完成了,雖然還有很多地方不是寫的很完美。

程式下載區

為了讓遊戲畫面生動一點,所以就把我最喜歡的小丸子給加了進來。遊戲一進入時,就可以為自己選一個角色。最後那一張帥哥當然不是我,是我可愛的學弟,測試員獨享的權利。選完角色後,可以從遊戲選單選擇要當Server還是Client。



當兩方都連線時,即可看見對方所選的角色,如下圖。按兩下可以翻開棋子,移動或吃棋子只要先點一下自己再點目的地即可。最下面會顯示所吃掉對方的棋子。




每次寫程式都有個大毛病,就是邊寫邊想邊改。明明知道這是很沒效率的,應該要一開始先拿紙筆好好規畫後,再動筆。所以,每次看到自己寫的程式碼,真的是難看死了。

上次的踩地雷和這次的暗棋都是自己胡亂寫的,接下來就要開始好好研讀之前買的兩本遊戲設計的書,看可不可以寫出漂亮的程式囉~~~

2008年3月8日 星期六

Java Game Programming

最近突然對寫遊戲很有興趣,之前胡亂寫了一個踩地雷,現在在寫的是連線的暗棋。然而這些都僅止於簡單靜態的遊戲。

於是我又敗了兩本書,至於會不會看完,又是另外一回事了~~~

2008年3月1日 星期六

踩地雷(Java版)

花了幾天的時間,終於把踩地雷寫好了。
一直覺得我的程式能力很弱,所以說想找些題目來寫寫。踩地雷感覺高中生就寫的出來的東西,我當然也要來寫一下,所以決定了這個題目。

整個程式是用Java寫的,主要是因為我比較會的視窗程式也只有Java而已。
程式下載區

我的寫法是先寫好地圖產生器,接著設定GUI,最後再來做事件處理。其實GUI應該要最後才寫的,但我比較喜歡先看到樣子。

整個程式寫完,花我最長時間的地方也是GUI的部分,LayoutManager好難用, 好在有發現用null可以自己設定絕對位置,才讓我能順利的排版每個物件。其次就是左鍵加右鍵的功能,凹下去的功能我是沒做啦,但是有做到能翻開周圍不是地雷的地方。

程式執行的畫面如下



比較有問題的是左鍵加右鍵一起按時,沒辦法像windows判斷那麼快,要先按左鍵(右鍵)再點右鍵(左鍵),然後一起放。按太快有時會偵測不到。還有重新開始的時候,畫面重設部份會有展開的感覺,無法瞬間換圖,但我同學都說這是特效,也不錯。

最後,感謝大鳥測試員~~~

2008年2月28日 星期四

內部類別存取外部類別

內部類別可以直接存取外部類別的成員變數以及函式,然而若要存取外部類別的參考,如:

class outer {
class inner {}
}

inner這個類別需要外部類別的參考
outer.this

2008年2月24日 星期日

陣列排序

我們可以透過實作java.lang.Comparable介面來建立比較的函式。實作此介面的好處可以很方便的使用sort的函式來幫我們排序。

例:假設AccessPoint有三個參數(x, y, strength),x、y為座標,strength為訊號強度。若我們有一個AccessPoint的陣列,希望將它依訊號強度大小排序:

public class AccessPoint implements Comparable {
public double x, y, strength;

public AccessPoint(double x, double y, double strength) {
this.x = x;
this.y = y;
this.strength = strength;
}
public int compareTo(AccessPoint ap) {
return (strength < strength ="="">

AccessPoint[] ap = {new AccessPoint(1, 2, 5), new AccessPoint(2, 3, 2)};
//遞增排序
Arrays.sort(ap);
//反向排序
Arrays.sort(ap, Collections.reverseOrder());

2008年2月20日 星期三

Layout Manger

每個在Layout上的Component都有四個size(height, width)

  • Component.getMinimumSize() - 最小的極限值
  • Component.getMaximumSize() - 最大的極限值
  • Component.getPreferredSize() - 理想的大小
  • Component.getSize() - 目前實際的大小
而Layout Manager做的事就是決定每一個Component的大小以及放置的位子。當呼叫Container.validate(),則Container的Layout manager就會經由getMinimumSize()、getMaximumSize()、getPreferredSize()的提示,透過setBounds(x, y, width, height)來設定每一個Component真正的大小以及位置。而Layout manager所做的這些事是透過呼叫
  • layoutContainer(Container c)
然而,container也需要有getMiniumumSize()、getMaximumSize、getPreferredSize()這些函式,因為他也是個Component包住整個Container。所以Layout manager也必須考量Container內所有的Component的總大小來容納它們。這些事情是間接透過更上層的Layout manger來做到的
  • preferredLayoutSize(Container c)
  • maximumLayoutSize(Container c)
  • minimumLayoutSize(Container c)

2008年2月14日 星期四

UVa Online Judge System

UVa Online Judge System是一個線上解題的系統,系統裡收集了許多比賽的題目,如ACM。可以用C、C++或是JAVA來寫,是一個練功的好地方。
許多人在高中就開始碰了,我實在是太落伍了,所以趁現在來插花一下。
挑了簡單的Volume I 100 - The 3n + 1 problem寫寫看,這樣挫折才不會那麼大。
寫完和測試完之後,題目的右上角有一個submit的按扭,即可把我們的程式碼貼上去。接著就可以看到結果了。

2008年1月31日 星期四

Fields in interface

所有field宣告在interface,都會是static和final。在Java SE5前,由於沒有enum,所以都會用interface來宣告一組constant,例:

public interface Days {
int
MONDAY = 1, TUESDAY = 2, WEDNESDAY =3,
THURSDAY = 4, FRIDAY = 5, SATURDAY =6, SUNDAY =7
}