For the implementation of the Playfair encryption I needed a custom struct called Cell. This is because I not only need an array of characters I also want to get Elements in a matrix based on their "cartesian" position.
public struct Cell
{
public char character;
public int X;
public int Y;
public Cell(char _character,int _X, int _Y)
{
this.character = _character;
this.X = _X;
this.Y = _Y;
}
}
Then I implement the method which calculates the cipher.
public static string PlayfairCipher(string keyWord,string plainText)
{
//Define alphabet
//There is no J in the alphabet instead I is used
char[] alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ".ToCharArray();
#region Adjust Key
keyWord = keyWord.Trim();
keyWord = keyWord.Replace(" ", "");
keyWord = keyWord.Replace("J", "I");
keyWord = keyWord.ToUpper();
StringBuilder keyString = new StringBuilder();
foreach(char c in keyWord)
{
if(!keyString.ToString().Contains(c))
{
keyString.Append(c);
alphabet = alphabet.Where(val => val != c).ToArray();
}
}
#endregion
#region Adjust plain text
plainText = plainText.Trim();
plainText = plainText.Replace(" ", "");
plainText = plainText.Replace("J", "I");
plainText = plainText.ToUpper();
//If the Length of the plain text is odd add X
if((plainText.Length % 2 > 0))
{
plainText += "X";
}
List<string> plainTextEdited = new List<string>();
//Split plain text into pairs
for (int i = 0; i < plainText.Length;i += 2)
{
//If a pair of chars contains the same letters replace one of them with X
if (plainText[i].ToString() == plainText[i + 1].ToString())
{
plainTextEdited.Add(plainText[i].ToString() + 'X');
}
else {
plainTextEdited.Add(plainText[i].ToString() + plainText[i + 1].ToString());
}
}
#endregion
#region Create 5 x 5 matrix
List<Cell> matrix = new List<Cell>();
int keyIDCounter = 0;
int alphabetIDCounter = 0;
//Fill the matrix. First with the key characters then with the alphabet
for (int x = 0; x < 5;x++)
{
for (int y = 0; y < 5; y++)
{
if (keyIDCounter < keyString.Length)
{
Cell cell = new Cell(keyString[keyIDCounter],x,y);
matrix.Add(cell);
keyIDCounter++;
}
else {
Cell cell = new Cell(alphabet[alphabetIDCounter], x, y);
matrix.Add(cell);
alphabetIDCounter++;
}
}
}
#endregion
#region Write cipher
StringBuilder cipher = new StringBuilder();
foreach(string pair in plainTextEdited)
{
int indexA = matrix.FindIndex(c => c.character == pair[0]);
Cell a = matrix[indexA];
int indexB = matrix.FindIndex(c => c.character == pair[1]);
Cell b = matrix[indexB];
//Write cipher
if (a.X == b.X)
{
cipher.Append(matrix[matrix.FindIndex(c => c.X == (a.X + 1)%5 && c.Y == a.Y)].character);
cipher.Append(matrix[matrix.FindIndex(c => c.X == (b.X + 1)%5 && c.Y == b.Y)].character);
}
else if(a.Y == b.Y)
{
cipher.Append(matrix[matrix.FindIndex(c => c.X == a.X && c.Y == (a.Y + 1) % 5)].character);
cipher.Append(matrix[matrix.FindIndex(c => c.X == b.X % 5 && c.Y == (b.Y + 1) % 5)].character);
}else
{
cipher.Append(matrix[matrix.FindIndex(c => c.X == a.X && c.Y == b.Y)].character);
cipher.Append(matrix[matrix.FindIndex(c => c.X == b.X % 5 && c.Y == a.Y)].character);
}
}
#endregion
return cipher.ToString();
}
Should I split this into more separate methods? Do I really need the Cell struct or is there another way to get an element's coordinates? Also how is the overall implementation and code readability? What should I improve regarding future implementations?