关于弗莱斯纳的
Fleissner是一种很容易加密文本的方法。您只需使用一个n*n大小的网格,其中包含(n*n)/4孔(示例)。然后你只需在一个洞里写一封信。在你用字母填完每个洞后,你只需把格栅转90度,然后重新开始。这样做的一个要求是格栅不对称。否则你会覆盖信件。
要创建这样一个格栅,你只需填补四分之一的格栅与数字1-4。然后你把这个季度旋转90°,并将公式z = z \% 4 + 1应用于每一个数字。关于如何工作的一个示例是可用的这里.1。
关于这个项目的
这个项目的基础已经涵盖了这里,但是自从我问了这个问题之后,我做了很多改变:


Control.java
package Fleissner;
import javax.swing.SwingUtilities;
public class Control {
// Just to start GUI
public static void main(String[] args) {
SwingUtilities.invokeLater(Gui::new);
}
}Fleissner.java
package Fleissner;
import java.lang.Math; // needed for sqrt()
public class Fleissner {
private int grilleSize; // size of the grille: if the grille has a size of 6x6, this variable
// equals to 36.
private int substringSize; // grilleSize / 4
private int sizeSqrt; // sqrt(grilleSize)
private String text; // text that will be encrypted
private char[][] out; // output
private int[][] grille; // The turning grille
public Fleissner(String text) {
this.text = text;
// determine needed grille-size
int length = text.length();
if (length == 0) {
length++;
}
while (true) {
// grilles with size > 64 cannot be displayed
if (length > 64) {
grilleSize = 64;
substringSize = grilleSize / 4;
sizeSqrt = (int) Math.sqrt((double) grilleSize);
break;
}
// conditions for grille-size-numbers.
// Possible are - for example - 2x2, 4x4, 6x6 and 8x8
if (Math.sqrt((double) length) % 2 == 0 && length % 4 == 0) {
grilleSize = length;
substringSize = grilleSize / 4;
sizeSqrt = (int) Math.sqrt((double) grilleSize);
break;
}
length++;
}
}
public String fleissnerEncryption() {
// If text is too short for grille, the grille will be filled up with random chars ('a' - 'z')
if (text.length() < grilleSize) {
while (text.length() < grilleSize) {
text = text + (char) ('a' + (int) (Math.random() * (('z' - 'a') + 1)));
}
}
// Case that text is too long
if (text.length() != grilleSize) {
text = safeSubstring(text, 0, grilleSize);
}
out = encrypt();
//Convert array "out" to String in desired format
String result = "Encrypted: ";
int length = result.length();
result += "| Grille:\n";
for (int i = 0; i < out.length; i++) {
for (int j = 0; j < out[0].length; j++) {
if (j == sizeSqrt) {
for (int k = 0; k < length - 2 * sizeSqrt; k++) {
result += " ";
}
result += "| ";
}
result += out[i][j] + " ";
}
result += "\n";
}
return result;
}
private char[][] encrypt() {
grille = creategrille();
//The text now gets split up to substrings with length substringSize.
//Then the grille gets filled up with the chars.
String subText = safeSubstring(text, 0, substringSize);
int[] ar = {0 * substringSize, 1 * substringSize, 2 * substringSize, 3 * substringSize,
4 * substringSize};
out = new char[sizeSqrt][sizeSqrt * 2];
int count = 0;
while (count < grilleSize / substringSize) {
int row = 0;
int col = 0;
int i = 0;
//Filling grille with transposed chars
while (i < subText.length()) {
if (grille[row][col] == 1) {
out[row][col] = subText.charAt(i);
i = i + 1;
if (col < sizeSqrt - 1) {
col = col + 1;
} else if (row < sizeSqrt - 1) {
row = row + 1;
col = 0;
}
} else if (col < sizeSqrt - 1) {
col = col + 1;
} else if (row < sizeSqrt - 1) {
row = row + 1;
col = 0;
}
}
count = count + 1;
int m = ar[count];
int n = m + substringSize;
subText = safeSubstring(text, m, n);
grille = rotate(grille);
}
//Filling 2nd part of the array with the grille (needed for decrypting)
for (int k = 0; k < out.length; k++) {
for (int l = sizeSqrt; l < out[0].length; l++) {
int radix = 10;
out[k][l] = Character.forDigit(grille[k][l - sizeSqrt], radix);
}
}
return out;
}
// This method creates a random grille
private int[][] creategrille() {
final int n = sizeSqrt / 2;
int[][] a2 = new int[n][n];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
a2[i][j] = (int) ((Math.random()) * 4 + 1);
}
}
int[][] a3 = getMatrix(a2);
int[][] a4 = getMatrix(a3);
int[][] a5 = getMatrix(a4);
int[][] result = new int[sizeSqrt][sizeSqrt];
/*
* Filling result-array like this:
* [ (a2), (a3) ]
* [ (a5), (a4) ]
*/
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
result[i][j] = a2[i][j];
result[i + n][j] = a5[i][j];
result[i][j + n] = a3[i][j];
result[i + n][j + n] = a4[i][j];
}
}
return result;
}
//Rotates the matrix and applies formula
private int[][] getMatrix(int[][] a2) {
int[][] result = rotate(a2);
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result.length; j++) {
result[i][j] = result[i][j] % 4 + 1;
}
}
return result;
}
// This method rotates the "grille" clockwise 45 degrees
private int[][] rotate(int[][] a1) {
int n = a1.length;
int[][] rotated = new int[n][n];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
rotated[i][j] = a1[n - j - 1][i];
}
}
return rotated;
}
// Method to divide String into smaller substrings.
private String safeSubstring(String str, int start, int end) {
String out = "";
if (end > str.length() - 1) {
end = str.length();
}
while (start < end) {
out = out + str.charAt(start);
start = start + 1;
}
return out;
}
}Gui.java
/* Attribution:
* Question by shareef(https://stackoverflow.com/users/944593/shareef):
* https://stackoverflow.com/questions/30370220/how-to-diable-break-line-keystroke-enter-e-g-in-jtextarea-in-swing-java
* Answer by Normal design (https://stackoverflow.com/users/4919947/normal-design)
*/
package Fleissner;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Gui {
private JTextArea outputArea;
public Gui() {
//JFrame
JFrame frame = new JFrame("Fleissner-Encryption");
frame.setSize(500, 300);
frame.setMinimumSize(new Dimension(500, 300));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JPanel
JPanel panel = new JPanel(new GridBagLayout());
//Creating textArea for input
JTextArea inputArea = new JTextArea();
inputArea.setColumns(50);
inputArea.setRows(4);
inputArea.setLineWrap(true);
inputArea.getDocument().putProperty("filterNewlines", Boolean.TRUE); //Make line-breaks impossible
inputArea.setFont(new Font("monospaced", Font.PLAIN, 12));
JScrollPane input = new JScrollPane(inputArea);
//Creating button
JButton button = new JButton("Encrypt");
button.setFont(new Font("Arial", Font.PLAIN, 20));
button.addActionListener(e -> encrypt(inputArea.getText()));
//Creating textArea for output
outputArea = new JTextArea();
outputArea.setEditable(false);
outputArea.setColumns(50);
outputArea.setRows(10);
outputArea.setLineWrap(true);
outputArea.setFont(new Font("monospaced", Font.PLAIN, 12));
JScrollPane output = new JScrollPane(outputArea);
//Layout
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 5;
gbc.gridwidth = GridBagConstraints.REMAINDER;
//Add everything to panel
panel.add(input, gbc);
panel.add(button, gbc);
panel.add(output, gbc);
//Add everything to frame
frame.add(panel);
frame.setVisible(true);
}
//Connection to class Fleissner
private void encrypt(String text) {
Fleissner fleissner = new Fleissner(text);
String result = fleissner.fleissnerEncryption();
outputArea.setText(result);
}
}1维基百科撰稿人。(2019年,3月13日,05:57世界协调时),弗莱尼什沙布龙。在维基百科中,Die Enzykop die。从https://de.wikipedia.org/w/index.php?title=Flei%C3%9Fnersche_Schablone&oldid=186533989检索2020年6月4日17:20世界协调时
发布于 2020-06-05 13:02:56
在我看来,代码是伟大的和良好的分离(ui和逻辑),好工作!
我有一些建议。
java.lang.StringBuilder连接.循环中的字符串。
在循环中使用构建器通常更有效,因为编译器无法使其在循环中有效;因为它每次迭代都会创建一个新字符串。关于这个问题有很多很好的解释和更多的细节。
for循环在这种情况下,它将使代码更短。
Fleissner#fleissnerEncryption
for (int i = 0; i < out.length; i++) {
//[...]
result += out[i][j] + " ";
}for (char[] chars : out) {
//[...]
result += chars[j] + " ";
}Fleissner#encrypt中的数组,因为"0 * n = 0“和"1 * n = n"int[] ar = {0 * substringSize, 1 * substringSize, 2 * substringSize, 3 * substringSize, 4 * substringSize};int[] ar = {0, substringSize, 2 * substringSize, 3 * substringSize, 4 * substringSize};发布于 2020-06-08 15:58:36
代码结构很好,数学核心和gui之间的划分很整洁,我对数学部分有一些想法。您的Fleissner构造函数如下:
如果( this.text > 64) { grilleSize = 64;substringSize = grilleSize / 4;sizeSqrt = ( int ) Math.sqrt((双重)grilleSize),则不能显示public (String text) {grilleSize= text;//确定所需的格栅尺寸int length = text.length();if (length == 0) { length++;}而(true) { // length++> 64。} //格栅的条件-尺寸-数字。//可能是-例如- 2x2、4x4、6x6和8x8如果(Math.sqrt(双)长度)%2 == 0& length %4 == 0) { grilleSize = length;substringSize = grilleSize / 4;sizeSqrt = (int) Math.sqrt((double) grilleSize);break;} length++;}
您可以构造一个最大的8×8字符的格栅,根据所使用的字符串的长度,可以选择2 X2、4 X4、6 X6和8 X8格栅;您可以通过以下方式获得同样的结果:
public Fleissner(String text) {
this.text = text;
final int l = text.length();
int length = 2;
for (;l > length * length && length < 8; length += 2);
this.grilleSize = length * length;
this.substringSize = grilleSize / 4;
this.length = length;
}在您的方法fleissnerEncryption中,您有以下几行:
if (text.length() < grilleSize) { while (text.length() < grilleSize) { text = text + (char) ('a‘+ (int) (Math.random() * (('z’- 'a') +1));}
您可以使用Random.ints方法并进行如下重写:
int l = text.length();
if (l < grilleSize) {
new Random().ints(grilleSize - l, 'a', 'z' + 1)
.forEach(i -> { text = text + (char)i; });
}最复杂的部分是编写字符串结果;您有以下几行:
字符串结果=“加密:";int长度= result.length();结果+=”\n ";for (int i= 0;i< out.length;i++) { for (int j= 0;j< out0.length;j++) { if (j == sizeSqrt) { for (int k= 0;k< length 2* sizeSqrt;k++) { result += ";} result +=“;}结果+= out我 +“";}结果+= "\n";}
使用String.join方法和Collections.nCopies,您可以通过以下方式重写它:
String result = "Encrypted: ";
l = result.length();
String spaces = String.join("", Collections.nCopies(l - 2 * length, " "));
result += "| Grille:\n";
for (char[] row : out) {
result += String.join(" ", new String(Arrays.copyOfRange(row, 0, length)).split(""));
result += spaces;
result += " | ";
result += String.join(" ", new String(Arrays.copyOfRange(row, length, row.length)).split(""));
result += "\n";
}
return result;方法fleissnerEncryption可以这样重写:
public String fleissnerEncryption() {
// If text is too short for grille, the grille will be filled up with random chars ('a' - 'z')
int l = text.length();
if (l < grilleSize) {
new Random().ints(grilleSize - l, 'a', 'z' + 1)
.forEach(i -> { text = text + (char)i; });
}
if (l != grilleSize) {
text = safeSubstring(text, 0, grilleSize);
}
out = encrypt();
//Convert array "out" to String in desired format
String result = "Encrypted: ";
l = result.length();
String spaces = String.join("", Collections.nCopies(l - 2 * length, " "));
result += "| Grille:\n";
for (char[] row : out) {
result += String.join(" ", new String(Arrays.copyOfRange(row, 0, length)).split(""));
result += spaces;
result += " | ";
result += String.join(" ", new String(Arrays.copyOfRange(row, length, row.length)).split(""));
result += "\n";
}
return result;
}代码中的以下一行:
int[] ar = {0 * substringSize,1* substringSize,2* substringSize,3* substringSize,4* substringSize};
它可以用IntStream重写:
int[] ar = IntStream.rangeClosed(0, 5).map(i -> i * substringSize).toArray();包Fleissner的名称应该是fleissner。按照惯例,包名通常以小写字母开头。
https://codereview.stackexchange.com/questions/243388
复制相似问题