Рандомизация текстового файла, читаемого на Java


Я пытаюсь прочитать текстовый файл на Java, в основном набор вопросов. С четырьмя вариантами и одним ответом. Структура выглядит следующим образом:

Вопрос

Вариант А

Вариант b

Вариант c

Вариант d

Ответ

Я без труда читаю его таким образом:

public class rar{
public static String[] q=new String[50];
public static String[] a=new String[50];
public static String[] b=new String[50];
public static String[] c=new String[50];
public static String[] d=new String[50];
public static char[] ans=new char[50];
public static Scanner sr= new Scanner(System.in);


public static void main(String args[]){
int score=0;
try {
             FileReader fr;
      fr = new FileReader (new File("F:\questions.txt"));
      BufferedReader br = new BufferedReader (fr);
int ar=0;
      for(ar=0;ar<2;ar++){
      q[ar]=br.readLine();
      a[ar]=br.readLine();
      b[ar]=br.readLine();
      c[ar]=br.readLine();
      d[ar]=br.readLine();
    String tempo=br.readLine();
    ans[ar]=tempo.charAt(0);






        System.out.println(q[ar]);
        System.out.println(a[ar]);
        System.out.println(b[ar]);
        System.out.println(c[ar]);
        System.out.println(d[ar]);
        System.out.println("Answer: ");
        String strans=sr.nextLine();
char y=strans.charAt(0);
if(y==ans[ar]){
    System.out.println("check!");
score++;
System.out.println("Score:" + score);
}else{
System.out.println("Wrong!");
}

      }
      br.close();
    } catch (Exception e) { e.printStackTrace();}


}




}
Приведенный выше код предсказуем. Цикл for просто увеличивается. И он отображает вопросы, основанные на порядке.

Что я хочу сделать это, чтобы иметь возможность рандомизировать через текстовый файл, но все еще сохраняя ту же структуру. (q, a, b, c, d, ans). Но когда я пытаюсь сделать это:

int ran= random(1,25);
   System.out.println(q[ran]);
        System.out.println(a[ran]);
        System.out.println(b[ran]);
        System.out.println(c[ran]);
        System.out.println(d[ran]);
        System.out.println("Answer: ");
        String strans=sr.nextLine();
char y=strans.charAt(0);
if(y==ans[ran]){
    System.out.println("check!");
score++;
System.out.println("Score:" + score);
}else{
System.out.println("Wrong!");
}

И это метод, который я использую для рандомизации:

public static int random(int min, int max){
    int xx;
    xx= (int) ( Math.random() * (max-min + 1))+ min;
    return xx;
    }

Есть вероятность, что я получу нуль. Что вы можете посоветовать мне сделать, чтобы я не получал null при попытке рандомизировать вопросы?

Можете ли вы увидеть что-нибудь еще, что не так с моей программой?
4 6

4 ответа:

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

public static String[] q=new String[50]; //why make an array to hold 50 questions?

//... 

for(ar=0;ar<2;ar++){ //why read 2 questions?

//...

int ran= random(1,25); //why take one of 25 questions?
System.out.println(q[ran]);

Это должно быть одно и то же число, верно? Если у нас есть 25 вопросов, мы должны иметь место для 25, читать 25 и использовать 25.

Как это исправить:

1 Сделать константу

public final static int NUMBER_OF_QUESTIONS = 25;

Затем используйте это при создании массива, чтении вопросов и при выборе случайного:

public static String[] q=new String[NUMBER_OF_QUESTIONS];

for(ar=0;ar<NUMBER_OF_QUESTIONS;ar++){

int ran= random(1,NUMBER_OF_QUESTIONS);

2 Используйте q. length

public static String[] q=new String[NUMBER_OF_QUESTIONS];

for(ar=0;ar<q.length;ar++){

int ran= random(1,q.length);

3 Используйте список / Коллекция

public static List<String> q=new List<String>();

for(ar=0;ar<q.size();ar++){

int ran= random(1,q.size());

Вариант 3 был бы лучшим выбором, это java в конце концов. Смотрите ответ Майка для получения более подробной информации в создании этой более Java.

Я думаю, что небольшие структурные изменения очень помогут и сделают это намного проще для вас. Определите новые классы: Question и Answer. Пусть Question имеет варианты и Answer внутри него. Это композиция объекта.

Загляните вCollection API . С помощью набора вопросов, вы можете использовать метод перемешивания, чтобы рандомизировать их в одну строку. Пусть Java сделает всю работу за вас.

Таким образом, вы могли бы:

Collection<Question> questions = new ArrayList<Question>();

questions.add(...);
questions.add(...);
questions.add(...);

questions.shuffle();

Чтобы приукрасить немного больше о том, почему вы хотели бы сделать это так почему?... Вы хотите отделить свои проблемы как можно лучше. Вопросы, ответы и варианты-все это разные проблемы. Реакция пользователя вызывает беспокойство. Рандомизация вопросов вызывает беспокойство. Ответ на ответ пользователя вызывает беспокойство.

Будучи хорошим разработчиком программного обеспечения, вы захотите разделить все эти вещи. Конструкция Java для выполнения этого является классом. Вы можете развивать свои идеи относительно самостоятельно внутри своих собственных класс. Когда вы удовлетворены своими занятиями, все, что вам нужно сделать, это соединить их. Определите их интерфейсы , как они разговаривают друг с другом. Мне нравится сначала определять интерфейсы, но когда я начал, мне было немного легче беспокоиться об этом позже.

Может показаться, что много работы, со всеми этими классами и интерфейсами, а что нет. Это займет часть времени, чтобы сделать это таким образом, когда вы получите хорошо. И ваша награда-это возможность повторного использования тестируемости.

Другие люди (Майк, Эрик) уже предложили лучшие подходы к этой проблеме, создав новый класс Question, добавив вопросы в коллекцию и используя метод shuffle для их рандомизации.

Относительно того, почему вы "получаете null" в своем коде: насколько я могу видеть в вашем примере кода, Вы читаете только два вопроса из файла:

for (ar=0;ar<2;ar++) {
    [...]
}

Это означает, что позиции 0 и 1 в ваших массивах будут иметь действительные данные, в то время как позиции от 2 до 49 будут содержать null.

Позже, когда вы пытаетесь рандомизировать вопросы, вы называете свой метод random следующим образом:

int ran = random(1,25);

Возвращает значение от 1 до 25,которое затем используется в качестве индекса массива.

Если этот индекс окажется "1", все будет в порядке. Во всех остальных случаях (от 2 до 25) вы будете получать доступ к значениям null в ваших массивах и получать исключения при попытке играть с этими значениями.

Создайте класс для хранения вопроса и считайте файл в массив этих объектов.

Разбить проблему на три шага. Первым шагом является чтение файла данных и сохранение всех данных в объектах. Второй шаг-рандомизировать порядок этих объектов. Последний шаг-распечатать их.

ArrayList questions = new ArrayList();
for(ar=0;ar<2;ar++){
  q=br.readLine();
  a=br.readLine();
  b=br.readLine();
  c=br.readLine();
  d=br.readLine();
  String tempo=br.readLine();
  ans=tempo.charAt(0);

  questions.add(new Question(q, a, b, c, d, ans));
}

Рандомизируйте массив следующим образом:

Collections.shuffle(questions);

Затем просто перебирайте вопросы и выводите их.

for (Question q: questions) {
  q.write();
  System.out.println(); // space between questions
}

Создайте класс вопросов типа это для хранения ваших данных:

public class Question {
  private String question;
  private String option1;
  private String option2;
  private String option3;
  private String option4;
  private String answer;

  public Question(String question, String option1, String option2, String option3,
                  String option4, String answer) {
    this.question = question;
    this.option1 = option1;
    this.option2 = option2;
    this.option3 = option3;
    this.option4 = option4;
    this.answer = answer;
  }

  public void write() {
    System.out.println(this.question);
    System.out.println(this.option1);
    System.out.println(this.option2);
    System.out.println(this.option3);
    System.out.println(this.option4);
    System.out.println("Answer: "+this.answer);
  }
}