You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现Playfair密码:矩阵位置逆置换功能技术求助

别慌!我来帮你一步步搞定这个Playfair密码的变种实现,咱们把问题拆成几个小模块,逐个击破就简单多了~

实现步骤拆解

咱们的需求可以分成四个核心环节:生成无重复字符集、构建5×5矩阵、快速查找字符位置、消息字符替换。下面逐个讲清楚代码怎么写:

1. 生成密钥+消息的无重复字符集

首先要把密钥和消息合并,过滤掉非字母字符,然后去重。如果字符数不够25个,还要补充剩下的字母(注意:传统Playfair会把I和J合并,如果你需要这个规则,可以在代码里加个判断把J替换成I,我会在注释里标出来)。

private static List<char> GenerateUniqueCharSet(string key, string message)
{
    // 统一转为大写,避免大小写干扰
    string combinedContent = (key + message).ToUpperInvariant();
    HashSet<char> uniqueChars = new HashSet<char>();
    List<char> charSet = new List<char>();

    foreach (char c in combinedContent)
    {
        // 只保留字母字符
        if (char.IsLetter(c))
        {
            // 可选:合并I和J,把J替换成I
            // char processedChar = c == 'J' ? 'I' : c;
            char processedChar = c;
            
            // HashSet.Add返回bool,只有字符不存在时才添加到列表
            if (uniqueChars.Add(processedChar))
            {
                charSet.Add(processedChar);
            }
        }
    }

    // 补充剩余字母,凑够25个
    for (char c = 'A'; c <= 'Z'; c++)
    {
        // 可选:如果合并I/J,跳过J
        // if (c == 'J') continue;
        
        if (!uniqueChars.Contains(c))
        {
            charSet.Add(c);
            if (charSet.Count == 25) break;
        }
    }

    return charSet;
}

2. 构建5×5二维矩阵

把上面生成的无重复字符集,按行优先的顺序填充到5×5数组里就行:

private static char[,] BuildPlayfairMatrix(List<char> charSet)
{
    char[,] playfairMatrix = new char[5, 5];
    int charIndex = 0;

    for (int row = 0; row < 5; row++)
    {
        for (int col = 0; col < 5; col++)
        {
            playfairMatrix[row, col] = charSet[charIndex++];
        }
    }

    return playfairMatrix;
}

3. 构建字符-位置映射字典

为了避免每次查找字符位置都遍历整个矩阵(效率太低),咱们提前做一个字典,记录每个字符对应的(行, 列)坐标,这样查找就是O(1)的速度:

private static Dictionary<char, (int row, int col)> BuildCharPositionMap(char[,] matrix)
{
    Dictionary<char, (int row, int col)> positionMap = new Dictionary<char, (int row, int col)>();

    for (int row = 0; row < 5; row++)
    {
        for (int col = 0; col < 5; col++)
        {
            char currentChar = matrix[row, col];
            if (!positionMap.ContainsKey(currentChar))
            {
                positionMap[currentChar] = (row, col);
            }
        }
    }

    return positionMap;
}

4. 处理消息,替换为逆序位置的字符

遍历消息里的每个字符,找到它的位置(row, col),然后取矩阵里(col, row)位置的字符作为替换值。非字母字符可以选择保留或者过滤,这里我做了保留处理:

private static string TransformMessage(string message, char[,] matrix, Dictionary<char, (int row, int col)> positionMap)
{
    StringBuilder resultBuilder = new StringBuilder();
    string upperMessage = message.ToUpperInvariant();

    foreach (char c in upperMessage)
    {
        if (!char.IsLetter(c))
        {
            // 保留非字母字符(比如空格、标点),不需要转换
            resultBuilder.Append(c);
            continue;
        }

        // 可选:如果合并I/J,把消息里的J转成I再查找
        // char lookupChar = c == 'J' ? 'I' : c;
        char lookupChar = c;

        if (positionMap.TryGetValue(lookupChar, out var charPosition))
        {
            // 核心操作:原位置(row, col) → 逆序位置(col, row)
            char replacementChar = matrix[charPosition.col, charPosition.row];
            resultBuilder.Append(replacementChar);
        }
        else
        {
            // 理论上不会走到这里,因为我们的字符集包含所有字母
            resultBuilder.Append(c);
        }
    }

    return resultBuilder.ToString();
}
整合测试示例

把上面的方法放到一个类里,写个Main方法测试效果:

using System;
using System.Collections.Generic;
using System.Text;

class PlayfairTransformer
{
    static void Main(string[] args)
    {
        string secretKey = "PLAYFAIR";
        string inputMessage = "HELLOWORLD!";

        // 按步骤执行
        var uniqueCharSet = GenerateUniqueCharSet(secretKey, inputMessage);
        var playfairMatrix = BuildPlayfairMatrix(uniqueCharSet);
        var charPositionMap = BuildCharPositionMap(playfairMatrix);
        string transformedMessage = TransformMessage(inputMessage, playfairMatrix, charPositionMap);

        // 输出结果
        Console.WriteLine("生成的Playfair矩阵:");
        PrintMatrix(playfairMatrix);
        Console.WriteLine($"\n原消息:{inputMessage}");
        Console.WriteLine($"转换后消息:{transformedMessage}");
    }

    // 辅助方法:打印矩阵,方便查看
    private static void PrintMatrix(char[,] matrix)
    {
        for (int row = 0; row < 5; row++)
        {
            for (int col = 0; col < 5; col++)
            {
                Console.Write(matrix[row, col] + " ");
            }
            Console.WriteLine();
        }
    }

    // 把上面四个方法(GenerateUniqueCharSet、BuildPlayfairMatrix、BuildCharPositionMap、TransformMessage)放在这里
}
额外说明
  • I/J合并规则:如果需要遵循传统Playfair的这个规则,只需要在生成字符集和处理消息的代码里,把所有J替换成I就行,我已经在代码里加了注释提示。
  • 大小写保留:上面的代码统一转成大写输出,如果需要保留原消息的大小写,可以在遍历的时候记录每个字符的大小写状态,替换后再转回去。
  • 非字母处理:如果不需要保留非字母字符,直接跳过就行,把resultBuilder.Append(c);改成continue;即可。

内容的提问来源于stack exchange,提问作者user9647560

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:03:48