首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >弗莱斯纳-格栅/转弯-格栅

弗莱斯纳-格栅/转弯-格栅
EN

Code Review用户
提问于 2020-06-04 17:44:30
回答 2查看 386关注 0票数 6

背景

关于弗莱斯纳的

-格莱尔

Fleissner是一种很容易加密文本的方法。您只需使用一个n*n大小的网格,其中包含(n*n)/4孔(示例)。然后你只需在一个洞里写一封信。在你用字母填完每个洞后,你只需把格栅转90度,然后重新开始。这样做的一个要求是格栅不对称。否则你会覆盖信件。

要创建这样一个格栅,你只需填补四分之一的格栅与数字1-4。然后你把这个季度旋转90°,并将公式z = z \% 4 + 1应用于每一个数字。关于如何工作的一个示例是可用的这里.1。

关于这个项目的

这个项目的基础已经涵盖了这里,但是自从我问了这个问题之后,我做了很多改变:

  • 添加了GUI:这个项目的最后一个版本只是在终端上运行。我现在添加了以下GUI:
  • 更改代码结构:在上一个版本中,我只是以一种非常程序化的方式解决了这个问题。我现在尝试用更好的方式构造我的代码:我使用了类和更多的方法。
  • 格栅尺寸不再固定:输入的文字越长,格栅就越大。

Control.java

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
/* 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);
  }
}

问题

  • 一般情况下,如何改进代码?
  • 在GUI方面有哪些改进?
  • 如何改进代码结构?

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世界协调时

EN

回答 2

Code Review用户

回答已采纳

发布于 2020-06-05 13:02:56

在我看来,代码是伟大的和良好的分离(ui和逻辑),好工作!

我有一些建议。

使用java.lang.StringBuilder连接.

循环中的字符串。

在循环中使用构建器通常更有效,因为编译器无法使其在循环中有效;因为它每次迭代都会创建一个新字符串。关于这个问题有很多很好的解释和更多的细节。

在可能的情况下使用增强的for循环

在这种情况下,它将使代码更短。

Fleissner#fleissnerEncryption

先于

代码语言:javascript
复制
for (int i = 0; i < out.length; i++) {
   //[...]
   result += out[i][j] + " ";
}

代码语言:javascript
复制
for (char[] chars : out) {
   //[...]
   result += chars[j] + " ";
}

您可以简化Fleissner#encrypt中的数组,因为"0 * n = 0“和"1 * n = n"

先于

代码语言:javascript
复制
int[] ar = {0 * substringSize, 1 * substringSize, 2 * substringSize, 3 * substringSize, 4 * substringSize};

代码语言:javascript
复制
int[] ar = {0, substringSize, 2 * substringSize, 3 * substringSize, 4 * substringSize};
票数 1
EN

Code Review用户

发布于 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格栅;您可以通过以下方式获得同样的结果:

代码语言:javascript
复制
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方法并进行如下重写:

代码语言:javascript
复制
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,您可以通过以下方式重写它:

代码语言:javascript
复制
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可以这样重写:

代码语言:javascript
复制
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重写:

代码语言:javascript
复制
int[] ar = IntStream.rangeClosed(0, 5).map(i -> i * substringSize).toArray();

Fleissner的名称应该是fleissner。按照惯例,包名通常以小写字母开头。

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/243388

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档