I'm trying to create a random multiple choice quiz for android. I want to display a random question from a stringarray, with the corresponding answer from another string array showing up in one of the four options. The other three options will come from another string array, which will be used provide the "wrong" answers for all the questions, randomly.
Two questions: Is there a better way to make a multiple choice quiz like this? -and- When the player selects an answer, how do I identify which array the answer came from?
This is the code I'm using to randomize:
String[] question = { //questions here// };
ArrayList<String> questionList = new ArrayList(Arrays.asList(question));
String[] answer = { //answers here// };
ArrayList<String> answerList = new ArrayList(Arrays.asList(answer));
String[] distractor = { //distractors here// };
ArrayList<String> distractorList = new ArrayList(Arrays.asList(distractor));
int i = 0;
Random r = new Random();
public void randomize() {
TextView word = (TextView) findViewById(R.id.textView1);
TextView choice1 = (TextView) findViewById(R.id.textView2);
TextView choice2 = (TextView) findViewById(R.id.textView3);
TextView choice3 = (TextView) findViewById(R.id.textView4);
TextView choice4 = (TextView) findViewById(R.id.textView5);
if (i < question.length) {
int remaining = r.nextInt(questionList.size());
String q = questionList.get(remaining);
word.setText(q);
questionList.remove(remaining);
String a = answerList.get(remaining);
int slot = r.nextInt(4);
TextView[] tvArray = { choice1, choice2, choice3, choice4 };
tvArray[slot].setText(a);
answerList.remove(remaining);
//an if/else statement here to fill the remaining slots with distractors
I suggest creating a new class called QuestionAndAnswer. The class should hold the question and the correct answer, it could also hold any customized wrong answers and the user's choice. The exact implementation is entirely up to you.
In your Activity have an Array of this QuestionAndAnswer class to cycle through the list asking the questions and tally up the points when done.
(I could be more specific if you include the relevant code of what you have tried.)
Addition
This is what I would start with:
(From your code I'm guessing the distractorList
contains the false answers that you want to display.)
public class QuestionAndAnswer {
public List<String> allAnswers; // distractors plus real answer
public String answer;
public String question;
public String selectedAnswer;
public int selectedId = -1;
public QuestionAndAnswer(String question, String answer, List<String> distractors) {
this.question = question;
this.answer = answer;
allAnswers = new ArrayList<String> (distractors);
// Add real answer to false answers and shuffle them around
allAnswers.add(answer);
Collections.shuffle(allAnswers);
}
public boolean isCorrect() {
return answer.equals(selectedAnswer);
}
}
For the Activity I changed your four answer TextViews into a RadioGroup, this way the user can intuitively select an answer. I also assume that there will be prev
and next
buttons, they will adjust int currentQuestion
and call fillInQuestion()
.
public class Example extends Activity {
RadioGroup answerRadioGroup;
int currentQuestion = 0;
TextView questionTextView;
List<QuestionAndAnswer> quiz = new ArrayList<QuestionAndAnswer>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
questionTextView = (TextView) findViewById(R.id.question);
answerRadioGroup = (RadioGroup) findViewById(R.id.answers);
// Setup a listener to save chosen answer
answerRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if(checkedId > -1) {
QuestionAndAnswer qna = quiz.get(currentQuestion);
qna.selectedAnswer = ((RadioButton) group.findViewById(checkedId)).getText().toString();
qna.selectedId = checkedId;
}
}
});
String[] question = { //questions here// };
String[] answer = { //answers here// };
String[] distractor = { //distractors here// };
ArrayList<String> distractorList = Arrays.asList(distractor);
/* I assumed that there are 3 distractors per question and that they are organized in distractorList like so:
* "q1 distractor 1", "q1 distractor 2", "q1 distractor 3",
* "q2 distractor 1", "q2 distractor 2", "q2 distractor 3",
* etc
*
* If the question is: "The color of the sky", you'd see distractors:
* "red", "green", "violet"
*/
int length = question.length;
for(int i = 0; i < length; i++)
quiz.add(new QuestionAndAnswer(question[i], answer[i], distractorList.subList(i * 3, (i + 1) * 3)));
Collections.shuffle(quiz);
fillInQuestion();
}
public void fillInQuestion() {
QuestionAndAnswer qna = quiz.get(currentQuestion);
questionTextView.setText(qna.question);
// Set all of the answers in the RadioButtons
int count = answerRadioGroup.getChildCount();
for(int i = 0; i < count; i++)
((RadioButton) answerRadioGroup.getChildAt(i)).setText(qna.allAnswers.get(i));
// Restore selected answer if exists otherwise clear previous question's choice
if(qna.selectedId > -1)
answerRadioGroup.check(qna.selectedId);
else
answerRadioGroup.clearCheck();
}
}
You may have noticed that QuestionAndAnswer has an isCorrect() method, when it is time to grade the quiz you can count the correct answers like this:
int correct = 0;
for(QuestionAndAnswer question : quiz)
if(question.isCorrect())
correct++;
This is my general idea. The code is a complete thought, so it will compile. Of course, you'll want to add a "next" Button to see the different questions. But this is enough for you to see one way to randomize your questions and answers while keeping them organized.