Рандомизация текстового файла, читаемого на Java - PullRequest
6 голосов
/ 08 октября 2010

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

вопрос

опция a

опция 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;
    }

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

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

Ответы [ 4 ]

4 голосов
/ 08 октября 2010

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

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

Так что вы можете иметь:

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

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

questions.shuffle();

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

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

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

2 голосов
/ 08 октября 2010

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

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.

2 голосов
/ 08 октября 2010

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

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

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

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

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

int ran = random(1,25);

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

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

1 голос
/ 08 октября 2010

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

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

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);
  }
}
...