Java-шифровальная игра

#java

#java

Вопрос:

Я создаю игру с шифрованием, и я так застрял. Итак, у меня есть список массивов из 6 предложений и массив символов алфавита. Программа должна распечатать зашифрованную версию предложений, но каждый раз исходным буквам присваивается другая буква. Например, слово «Привет» станет «Ipiiu» (h < I, p<e, l<i, o<u).

Я понятия не имею, как это сделать. Приведенный ниже код постоянно заменяет буквы, но я хочу, чтобы каждый раз, когда пользователь воспроизводит буквы, они были разными. Как мне это сделать?

    public static void replaceString(ArrayList<String> arr, char[] alphabet) {
    
    Random r = new Random();
    
    String s1 = arr.get(0);
    
    String sentence1 = s1.toLowerCase()
            .replace("a", "t")
            .replace("r", "m")
            .replace("t", "p")
            .replace("n", "h")
            .replace("s", "u")
            .replace("f", "b")
            .replace("u", "n")
            .replace("w", "l")
            .replace("v", "a")
            .replace("y", "r")
            .replace("o", "j")
            .replace("h", "d");
    
            
}
 

Комментарии:

1. Я не собираюсь писать код, но я дам вам совет: создайте Map<char, char> и используйте его для преобразования ваших слов 😉

2. p.s. Если вы хотите перейти в жесткий режим, вы можете написать довольно сложные правила в выражении регулярных выражений и использовать их для изменения ваших слов. #жесткий режим

3. .relpace() возвращает объект String, который служит в качестве входных данных для следующей replace() команды. Это означает «нет».replace(«n», «h»).replace(«h», «d») заменит все ‘n’ на ‘h’, а затем в результирующей строке ‘ho’ заменит все ‘h’ на ‘d’ .

4. Для чего нужен alphabet массив?

5. @AKSingh каждый раз, когда пользователь играет, должны использоваться новые буквы алфавита, поэтому, если a было присвоено «x», в следующий раз, когда пользователь сыграет «a», не может быть снова присвоено «x»

Ответ №1:

То, что вы пытаетесь сделать, в основном называется шифром подстановки.

Чтобы сделать эту работу, вам нужно сначала создать таблицу подстановок, которая сопоставляет символ с другим (например, h с l, p с e и так далее)

После чего шифрование и дешифрование так же просто, как поиск в таблице подстановки.

Я сделал короткую попытку сделать это, и код выглядит следующим образом:

 import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;

public class CipherTest {
    public static void main(String[] args) {
        List<Character> characters = new ArrayList<Character>();
        for(int i='a'; i<='z'; i  )
            characters.add((char)i);
        Collections.shuffle(characters);
        
        //Generate Substitution Table
        Map<Character, Character> substitutionTable = new HashMap<Character, Character>();
        int listIndex = 0;
        for(int i='a'; i<='z'; i  )
            substitutionTable.put((char)i,characters.get(listIndex  ));
        substitutionTable.put(' ' , ' ');
        
        //Print Substitution table
        System.out.println("Substitution Table:");
        substitutionTable.entrySet().forEach(entry->{
            System.out.print(entry.getKey()   ":"   entry.getValue()   " ; ");  
         });
        System.out.println();
        
        //Encrypt
        String plaintext = "hello world";
        String encrypted = encrypt(substitutionTable,plaintext);
        System.out.println("Encrypted "   plaintext   " to "   encrypted);
        
        
        //Decrypt
        String decrypted = decrypt(substitutionTable, encrypted);
        System.out.println("Decrypted "   encrypted   " to "   decrypted);
   }
    
    public static String encrypt(Map<Character,Character> substitutionTable, String plaintext){
       StringBuilder sb = new StringBuilder();
        for(char character : plaintext.toCharArray())
            sb.append(substitutionTable.get(character));
        String encrypted = sb.toString();
       return encrypted;
    }
    
    public static String decrypt(Map<Character,Character> substitutionTable, String encrypted){
        Map<Character,Character> substitutionTableInversed = substitutionTable.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
        StringBuilder sb2 = new StringBuilder();
        for(char character : encrypted.toCharArray())
            sb2.append(substitutionTableInversed.get(character));
        String decrypted = sb2.toString();
        return decrypted;
    }
}
 

Вывод приведенного выше кода будет выглядеть примерно так:

 Substitution Table:
 :  ; a:d ; b:r ; c:u ; d:g ; e:s ; f:f ; g:c ; h:b ; i:y ; j:q ; k:x ; l:p ; m:k ; n:z ; o:i ; p:e ; q:v ; r:a ; s:l ; t:n ; u:m ; v:h ; w:w ; x:o ; y:t ; z:j ;
Encrypted hello world to bsppi wiapg
Decrypted bsppi wiapg to hello world
 

При каждом запуске игры выходные данные будут меняться так, как вы хотели, потому что таблица поиска динамически генерируется при каждом запуске

Комментарии:

1. есть ли способ сделать это, просто используя списки массивов?

2. Я продолжаю получать «нулевой» текст между предложениями

3. Для null: смотрите Мой отредактированный ответ. В принципе, вам нужно иметь сопоставление для ‘ ‘ —> ‘ ‘. Пробел должен соответствовать пробелу.

4. Вы можете использовать arraylist наверняка, но, вероятно, не стоит. Это будет сделано путем сохранения кортежа в каждом элементе списка. <персонаж, персонаж> также. При поиске по таблице вам необходимо многократно перебирать список. При вставке вы не получаете никаких гарантий в отношении дубликатов. Так что да, вы можете, но, вероятно, не должны

Ответ №2:

В этом случае проблема основана на методе шифрования текста с помощью exchange table. Поскольку цель состоит в том, чтобы каждый раз получать разный обмен буквами, правильный способ сделать это — каждый раз использовать другую таблицу обмена.

Вы должны создать отдельный ключ для каждого шифра, иначе ваш код не будет работать так, как вы хотите.