利用 Java 寫程式 (program) ,著重在設計類別 (class) ,然後規劃物件 (object) 的使用、物件與物件間的互動,同時要注意,一個物件專心做好一件事情就好,類別的設計不應該太過複雜
我們打算發展的一個替英文句子編密碼的軟體,主要功能是做小寫字母的替換,例如 "There is no spoon." 可能變成以下任一個
Tfqdq ki jo itooj.
Tcnan hf gl fqllg.
Tczmz dn ij nkjji.
Tgfsf pb ir barri.
Tdcpc my fo yxoof.
首先,我們要發展 Encrypt 類別,主要功能是建立一個英文小寫字母的對換表格,藉由這個表格,我們可以將英文句子中的小寫英文字母進行對換,最終開發圖形使用者介面 (graphical user interface) 的 Encryptor 專案 (project) 。
GUI 的外觀如下圖
GUI 的部份採用 JavaFX 設計,這需要用到 NetBeans 及 JavaFX Scene Builder 兩個隨 JDK 下載的軟體,其中 NetBeans 為官方提供的整合開發環境 (integrated development environment) ,而 JavaFX Scene Builder 則可直接在軟體視窗中拉出 JavaFX 的 GUI 外觀。
有兩個可供輸入的文字欄位 (text field) ,其中一個我們作為輸出的顯示訊息之用,另有三個標籤 (label) ,顯示文字的提示訊息,七個按鈕 (button) ,提供「新建」、「開啟」、「儲存」 Encrypt 物件,與「編碼」、「解碼」所輸入的英文句子,「清除」所有輸入欄位,以及「拷貝」輸出結果等的功能。
現在我們先來看看所有功能的核心,也就是 Encrypt 類別,我們的目的是,建立一個小寫英文字母的轉換表格,然後編碼、解碼都可直接依據這個表格。我們打算用下面的數學公式建立表格
y = a * x + b
m = y % n
r = m + diff
這裡的概念是利用字元的 Unicode 編碼順序,假設 x 為字元的原始編碼, Unicode 編碼中 'a' 為 97 ,然後將 x 乘上變數 (variable) a , 再加上變數 b ,假設兩者均是 0 到 9 的隨機整數,這樣便得到 y 的值。
然後將 y 除以 n 取得餘數 m , n 為所要轉換的字元數量,英文小寫字母共有 26 個,所以這裡 n 等於 26 ,因此 m 等於 0 到 25 之間的整數值。最後將 m 加上 diff , diff 也就是編碼系統的差值,由於 Unicode 中 'a' 為 97 ,所以這裡 diff 要以 97 代入。
因此,餘數 0 的字元會替換成 'a' ,餘數 1 的字元會被替換成 'b' ,餘數 2 的字元會被替換成 'c' ,餘下 23 個字元類推。這樣的計算需要進行 n 次,也就是 26 次,我們最後得到一組餘數與相對應字元的表格,這就是我們需要的表格了。
重複 n 次,我們需要一個迴圈 (loop) ,由於重複次數確定,因此 for 迴圈 (for loop) 很適合,那我們要用什麼東西來儲存這個表格呢? API 中有許多的資料結構 (data structure) ,可以依資料特性有效率的處理資料,簡單一點,我們利用陣列 (array) 就可以了。
陣列是一種儲存可以多個相同型態資料的資料結構,索引值 (index) 從 0 開始,這也完全符合我們計算餘數從 0 開始的需求。
我們先寫一個 Encrypt 的試做版本 Encrypt01 來看看吧
001 | public class Encrypt01 { |
002 | // 密碼表字元陣列 |
003 | private char[] code = new char[26]; |
004 | |
005 | // 建構子 |
006 | public Encrypt01() { |
007 | setCode(); |
008 | } |
009 | |
010 | // setter |
011 | public void setCode() { |
012 | char c = 'a'; |
013 | for (int i = 0; i < 26; i++) { |
014 | code[i] = c++; |
015 | } |
016 | } |
017 | |
018 | // getter |
019 | public char[] getCode() { |
020 | return code; |
021 | } |
022 | |
023 | // 編碼的方法 |
024 | public String toEncode(String s) { |
025 | return s; |
026 | } |
027 | |
028 | // 解碼的方法 |
029 | public String toDecode(String s) { |
030 | return s; |
031 | } |
032 | |
033 | // 測試的 main() |
034 | public static void main(String[] args) { |
035 | Encrypt01 e = new Encrypt01(); |
036 | System.out.println(e.code); |
037 | String s = "There is no spoon"; |
038 | System.out.println(s); |
039 | String s1 = e.toEncode(s); |
040 | System.out.println(s1); |
041 | String s2 = e.toDecode(s1); |
042 | System.out.println(s2); |
043 | } |
044 | } |
045 | |
046 | /* 檔名: Encrypt01.java |
047 | 作者: Kaiching Chang |
048 | 時間: September, 2014 */ |
首先宣告 private 的密碼表字元陣列屬性 code
002 | // 密碼表字元陣列 |
003 | private char[] code = new char[26]; |
這裡用 new 建立陣列物件,目的是宣告完直接分配記憶體空間。
下面除了建構子 (constructor) 及 setCode() 、 getCode() 外,還有需要一個 String 參數 (parameter) 也回傳 String 的 toEncode() 與 toDecode() ,這兩個都暫時回傳參數,待稍候的單元再實作。
建構子簡單的呼叫 setCode() ,目前 setCode() 的版本為建立二十六個英文小寫字母表
010 | // setter |
011 | public void setCode() { |
012 | char c = 'a'; |
013 | for (int i = 0; i < 26; i++) { |
014 | code[i] = c++; |
015 | } |
016 | } |
這也是個暫時的版本,讓我們測試的 main() 可以正常運作
033 | // 測試的 main() |
034 | public static void main(String[] args) { |
035 | Encrypt01 e = new Encrypt01(); |
036 | System.out.println(e.code); |
037 | String s = "There is no spoon"; |
038 | System.out.println(s); |
039 | String s1 = e.toEncode(s); |
040 | System.out.println(s1); |
041 | String s2 = e.toDecode(s1); |
042 | System.out.println(s2); |
043 | } |
編譯執行,結果如下
接下來我們要在 setCode() 中實作製作密碼表的公式囉!
中英文術語對照
程式 | program |
類別 | class |
物件 | object |
圖形使用者介面 | graphical user interface |
專案 | project |
整合開發環境 | integrated development environment |
文字欄位 | text field |
標籤 | label |
按鈕 | button |
變數 | variable |
迴圈 | loop |
for 迴圈 | for loop |
資料結構 | data structure |
陣列 | array |
索引值 | index |
建構子 | constructor |
參數 | parameter |
重點整理
- Java 寫程式著重在設計類別,規劃物件的使用及物件與物件之間的互動。
- Encrypt 類別利用數學公式進行英文小寫字母的替換, Encrypt01 則是第一個試做版本。
- 陣列是一種簡單的資列結構,可以儲存有限個相同資料型態的資料。
問題與討論
- 類別應該怎麼設計才不會太過複雜?
- 除了數學公式外,有其他的方式可以建立對換表格嗎?
- 為什麼要用到強制型態轉換?如果不做強制型態轉換會發生什麼結果?
the end
沒有留言:
張貼留言