Java 入門指南
單元 13 - Encrypt 類別
利用 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) 的 EncryptGUI 專案 (project) 。
GUI 的外觀如下圖
GUI 的部份採用 JavaFX 設計,我們會直接編輯 FXML 檔案, FXML 檔案是 XML 檔案的一種,利用 FXML 設計 GUI 外觀。
Oracle 官方有提供 JavaFX Scene Builder ,利用 JavaFX Scene Builder 可直接在軟體視窗中拉出 JavaFX 的 GUI 外觀,然後由於 Android 開發大量使用 XML ,因此先熟悉編輯 XML ,有助於往後學習 Android 開發。
有兩個可供輸入的文字欄位 (text field) ,其中一個我們作為輸出的顯示訊息之用,另有三個標籤 (label) ,顯示文字的提示訊息,七個按鈕 (button) ,提供新建、載入、儲存 Encrypt 物件,與編碼、解碼所輸入的英文句子,清空所有輸入欄位,以及拷貝輸出結果等的功能。
最後在 Android App 篇,改成直接在手機頁面輸入英文句子,然後點擊編碼按鈕顯示編碼結果
現在我們先來看看所有功能的核心,也就是 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 也就是編碼系統的差值,由於 ASCII 中 '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 來看看吧
/*
* 檔名:Encrypt01.java
* 作者:張凱慶
* 網站:http://kaiching.org
*/
package encrypt01;
public class Encrypt01 {
// 密碼表字元陣列
private char[] code = new char[26];
// 建構子
public Encrypt01() {
setCode();
}
// setter
public void setCode() {
char c = 'a';
for (int i = 0; i < 26; i++) {
code[i] = c++;
}
}
// getter
public char[] getCode() {
return code;
}
// 編碼的方法
public String toEncode(String s) {
return s;
}
// 解碼的方法
public String toDecode(String s) {
return s;
}
// 測試的 main()
public static void main(String[] args) {
Encrypt01 e = new Encrypt01();
System.out.println(e.code);
String s = "There is no spoon.";
System.out.println(s);
String s1 = e.toEncode(s);
System.out.println(s1);
String s2 = e.toDecode(s1);
System.out.println(s2);
}
}
首先宣告 private 的密碼表字元陣列屬性 code
// 密碼表字元陣列
private char[] code = new char[26];
這裡用 new 建立陣列物件,目的是宣告完直接分配記憶體空間。
下面除了建構子 (constructor) 及 setCode() 、 getCode() 外,還有需要一個 String 參數 (parameter) 也回傳 String 的 toEncode() 與 toDecode() ,這兩個都暫時回傳參數,待稍候的單元再實作。
建構子簡單的呼叫 setCode() ,目前 setCode() 的版本為建立二十六個英文小寫字母表
// setter
public void setCode() {
char c = 'a';
for (int i = 0; i < 26; i++) {
code[i] = c++;
}
}
這也是個暫時的版本,讓我們測試的 main() 可以正常運作
// 測試的 main()
public static void main(String[] args) {
Encrypt01 e = new Encrypt01();
System.out.println(e.code);
String s = "There is no spoon.";
System.out.println(s);
String s1 = e.toEncode(s);
System.out.println(s1);
String s2 = e.toDecode(s1);
System.out.println(s2);
}
Encrypt01.java 也可看成是列出 Encrypt 類別的軟體規格。
執行結果如下
abcdefghijklmnopqrstuvwxyz |
There is no spoon. |
There is no spoon. |
There is no spoon. |
接下來我們要在 setCode() 中實作製作密碼表的公式囉!
相關教學影片
中英文術語對照 | |
---|---|
array | 陣列 |
button | 按鈕 |
class | 類別 |
constructor | 建構子 |
data structure | 資料結構 |
for loop | for 迴圈 |
graphical user interface | 圖形使用者介面 |
index | 索引值 |
label | 標籤 |
loop | 迴圈 |
object | 物件 |
parameter | 參數 |
program | 程式 |
project | 專案 |
text field | 文字欄位 |
variable | 變數 |
重點整理 |
---|
1. Encrypt 類別的主類功能是轉換句子中的英文小寫字母,最後作為 GUI 軟體的核心部分。 |
2. Encrypt 類別以數學公式建立英文字母的轉換表格,用字串當欄位儲存表格。 |
3. Unicode 中, 'a' 的整數值為 97 。 |
4. 軟體通常是逐步發展而成。 |
問題與討論 |
---|
1. 為什麼 Encrypt 類別是要當作 GUI 軟體的核心?不能讓 Encrypt 類別直接成為大展神威的 GUI 軟體嗎? |
2. 除了數學公式外,有其他的方式可以建立轉換表格嗎? |
3. 為什麼程式的發展要逐步來?不能一次到位嗎? |
4. 字串是什麼樣的資料結構?對於儲存資料有什麼方便性? |
練習 |
---|
1. 建立一個專案 Exercise1301 ,設定一個含有數字 0 到 9 的字串,然後利用字串的 substring() 方法,印出 substring(6) 及 substring(0, 4) 。 |
2. 猜數字遊戲是一種猜測四位不重複數字的小遊戲,依猜測答案給 A 及 B 的數量, A 為對的數字及位置, B 為對的數字錯的位置,建立一個專案 Exercise1302 ,加入新的類別 GGuess 類別,自訂答案整數型態的 answer 欄位,然後在 Exercise1302 類別的 main() 印出 answer 值。 |