
setCode() 的工作就是建立密碼表,我們需要的密碼表就是一個攪亂順序的英文字母表

先來溫習一下用來編碼的數學公式
y = a * x + b
m = y % n
r = m + diff
a 與 b 預定是 0 到 9 之間的隨機整數,要取得隨機整數的話, API 有程式可用,倒是現在先不用急著一次到位,我們先把 a 設定成 3 , b 設定成 5 好了, setCode() 的實作如下
| 010 | // setter |
| 011 | public void setCode() { |
| 012 | int a = 3; |
| 013 | int b = 5; |
| 014 | |
| 015 | int x, y, m, i; |
| 016 | char c = 'a'; |
| 017 | for (i = 0; i < 26; i++) { |
| 018 | x = c; |
| 019 | y = x * a + b; |
| 020 | m = y % 26; |
| 021 | code[i] = (char) (m + 97); |
| 022 | c++; |
| 023 | } |
| 024 | } |
因為英文字母表的小寫字母共有 26 個,因此公式用迴圈 (loop) 跑了 26 次
| 017 | for (i = 0; i < 26; i++) { |
| 018 | x = c; |
| 019 | y = x * a + b; |
| 020 | m = y % 26; |
| 021 | code[i] = (char) (m + 97); |
| 022 | c++; |
| 023 | } |
我們多用了除了公式外的變數 (variable) c , c 為起始字元 (character) ,初值設定成英文字母表的第一個字母 'a' ,這裡並沒有直接拿變數 c 進行計算,而是把變數 c 的值指派給整數型態的 x
| 018 | x = c; |
會這樣做的原因很簡單,因為需要一個變數表示目前處理的字元,而字元型態的變數可以如同整數型態進行加減乘除,因此迴圈的最後利用遞增將變數 c 轉移到下一個字元,例如迴圈從 'a' 開始,第二個處理的字元為 'b' ,第三個為 'c' ,以此類推
| 022 | c++; |
Java 的字元型態其實就是 Unicode 編碼,因此可做算術運算。
然後當計算完的餘數 m 要加上 97 ,這才恢復成 Unicode 編碼中英文小寫字母的範圍,同時用小括弧進行強制型態轉換
| 021 | code[i] = (char) (m + 97); |
然後直接將計算結果指派當作 code 的元素,逐一跑完 26 次就得到密碼表字元陣列了。
建構子就是呼叫 setCode() 設定 code ,另外 getCode() 也就是回傳 code ,我們把 Encrypt01 改成 Encrypt02 如下
| 001 | public class Encrypt02 { |
| 002 | // 密碼表字元陣列 |
| 003 | private char[] code = new char[26]; |
| 004 | |
| 005 | // 建構子 |
| 006 | public Encrypt02() { |
| 007 | setCode(); |
| 008 | } |
| 009 | |
| 010 | // setter |
| 011 | public void setCode() { |
| 012 | int a = 3; |
| 013 | int b = 5; |
| 014 | |
| 015 | int x, y, m, i; |
| 016 | char c = 'a'; |
| 017 | for (i = 0; i < 26; i++) { |
| 018 | x = c; |
| 019 | y = x * a + b; |
| 020 | m = y % 26; |
| 021 | code[i] = (char) (m + 97); |
| 022 | c++; |
| 023 | } |
| 024 | } |
| 025 | |
| 026 | // getter |
| 027 | public char[] getCode() { |
| 028 | return code; |
| 029 | } |
| 030 | |
| 031 | // 編碼的方法 |
| 032 | public String toEncode(String s) { |
| 033 | return s; |
| 034 | } |
| 035 | |
| 036 | // 解碼的方法 |
| 037 | public String toDecode(String s) { |
| 038 | return s; |
| 039 | } |
| 040 | |
| 041 | // 測試的 main() |
| 042 | public static void main(String[] args) { |
| 043 | Encrypt02 e = new Encrypt02(); |
| 044 | System.out.println(e.getCode()); |
| 045 | String s = "There is no spoon"; |
| 046 | System.out.println(s); |
| 047 | String s1 = e.toEncode(s); |
| 048 | System.out.println(s1); |
| 049 | String s2 = e.toDecode(s1); |
| 050 | System.out.println(s2); |
| 051 | } |
| 052 | } |
| 053 | |
| 054 | /* 檔名: Encrypt02.java |
| 055 | 作者: Kaiching Chang |
| 056 | 時間: September, 2014 */ |
編譯執行,結果如下

結果如預期,一個英文小寫字母恰恰好對應到另外一個英文小寫字母,這樣我們的公式就 ok 了嗎?嗯,因為我們希望 a 與 b 可以是 0 到 9 之間的任意整數,這樣就有 100 種組合說,所以我們接下來要繼續測試,看看是不是每一種組合都 ok 囉!
中英文術語對照
| 迴圈 | loop |
| 變數 | variable |
| 字元 | character |
重點整理
- setCode() 為 code 的 setter ,用數學公式設定 code 。
- 字元型態就是 Unicode 編碼,因此可做算術運算
問題與討論
- 公式中取得餘數後,可以不做強制型態轉換嗎?
- 想一想公式會不會有問題?公式有可能會出什麼樣的錯?
the end
沒有留言:
張貼留言