C# 入門指南

單元 15 - 實作 SetCode()

~~學習進度表~~

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

setCode()

012345678910111213141516171819202122232425
qzirajsbktcludmvenwfoxgpyh

先來溫習一下用來編碼的數學公式

y = a * x + b
m = y % n
r = m + diff

ab 預定是 09 之間的隨機整數,要取得隨機整數的話, .NET 有程式可用,倒是現在先不用急著一次到位,我們先把 a 設定成 3b 設定成 5 測試看看好了,如此 SetCode() 的實作如下

// 建立密碼表
public void SetCode()
{
    // 宣告變數
    int a, b, x, y, m;
    char c = 'a';
    // a 、 b 初始化
    a = 3;
    b = 5;
    code = "";
    // 建立密碼表的迴圈
    for (int i = 0; i < 26; i++)
    {
        x = c;
        y = x * a + b;
        m = y % 26;
        code += Convert.ToChar(m + 97);
        c++;
    }
}

code 欄位的初值設定為空字串 (empty string)

code = "";

另外設定兩個控制變數 (control variable) ,字元型態的 c 為記錄目前處理的字母

char c = 'a';

for 迴圈中的 i 則是記錄迴圈 (loop) 進行的次數

for (int i = 0; i < 26; i++)

因為英文字母表的小寫字母共有 26 個,因此公式用迴圈跑了 26

// 建立密碼表的迴圈
for (int i = 0; i < 26; i++)
{
    x = c;
    y = x * a + b;
    m = y % 26;
    code += Convert.ToChar(m + 97);
    c++;
}

控制變數 c 最初的值為起始字元,也就是英文字母表的第一個字母 'a' ,這裡並沒有直接拿變數 c 進行計算,而是把變數 c 的值指派給整數型態的 x

x = c;

會這樣做的原因很簡單,因為需要一個變數表示目前處理的字元,而字元型態的變數可以如同整數型態進行加減乘除,因此迴圈的最後利用遞增將變數 c 轉移到下一個字元,例如迴圈從 'a' 開始,第二個處理的字元為 'b' ,第三個為 'c' ,以此類推

c++;

由於 C# 的字元型態其實就是範圍較小的整數,因此也可以直接將迴圈的控制變數 i 設定為 97 ,讓 i 依次遞增到 97 + 26 為止。

迴圈中逐次利用 SystemConvertToChar() 方法,將整數直接轉換成字元,再用 += 將字元附加到 code 欄位之後

code += Convert.ToChar(m + 97);

建構子就是呼叫 SetCode() 設定 code 欄位,目前的實作版本如下

using System;

namespace EncryptDemo02
{
    class EncryptDemo02
    {
        // 宣告密碼表欄位
        public string code;

        // 建構子,呼叫建立密碼表的 SetCode() 方法
        public EncryptDemo02()
        {
            SetCode();
        }

        // 建立密碼表
        public void SetCode()
        {
            // 宣告變數
            int a, b, x, y, m;
            char c = 'a';
            // a 、 b 初始化
            a = 3;
            b = 5;
            code = "";
            // 建立密碼表的迴圈
            for (int i = 0; i < 26; i++)
            {
                x = c;
                y = x * a + b;
                m = y % 26;
                code += Convert.ToChar(m + 97);
                c++;
            }
        }

        // 編碼方法
        public string ToEncode(string s)
        {
            return s;
        }

        // 解碼方法
        public string ToDecode(string s)
        {
            return s;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // 建立密碼物件
            EncryptDemo02 e = new EncryptDemo02();
            // 印出密碼表
            Console.WriteLine(e.code);
        }
    }
}

//《程式語言教學誌》的範例程式
// http://kaiching.org/
// 專案:EncryptDemo02
// 檔名:Program.cs
// 功能:示範利用 C# 設計 Encrypt 類別
// 作者:張凱慶

測試部分就是印出密碼表,執行結果如下

C:\EncryptDemo02> dotnet run
knqtwzcfiloruxadgjmpsvybeh
C:\EncryptDemo02>

結果如預期,一個英文小寫字母恰恰好對應到另外一個英文小寫字母,這樣我們的公式就 ok 了嗎? a 等於 3b 等於 5 是沒問題的,可是我們希望 ab 可以是 09 之間的任意整數,這樣就有 100 種組合說,所以我們接下來要繼續測試,看看是不是每一種組合都 ok 囉!

相關教學影片

上一頁 單元 14 - Encrypt 類別
回 C# 入門指南首頁
下一頁 單元 16 - 繼續測試
回 C# 教材首頁
回程式語言教材首頁
中英文術語對照
控制變數control variable
空字串empty string
迴圈loop
參考資料
1. C# 程式設計手冊 | Microsoft Docs - 類別
重點整理
1. 實作 SetCode() 是先將公式中的 a 設成 3b 設成 5 ,然後用迴圈利用兩個控制變數 ic 逐一計算每個字元。
2. 字元型態就是範圍較小的整數,因此可直接進行算術運算。
3. 計算完利用 SystemConvertToChar() 方法,將整數直接轉換成字元,再用 += 將字元附加到 code 欄位之後。
問題與討論
1. 為什麼不把建立對換表格直接寫在建構子裡就好了?
2. 為什麼數字要用 ConvertToChar() 方法轉轉換成字元,才可以用 += 附加到字串物件的最後?
練習
1. 承接上一個單元的猜數字遊戲,另建立一個專案 Exercise1501 ,在 Program 類別的 Main() 方法接受使用者輸入,加入判斷使用者是否猜對的邏輯及提示訊息。
2. 承上題,另建立一個專案 Exercise1502 ,將 answer 改為字串。