0

I'm developing a simple quiz in my android studio. I'm using a database but I would like to randomize the questions every time the user clicks on the quiz button. I have created 5 sample questions so far.

2 Answers2

1

I suggest doing:

Option1: If you don't want duplicate Questions

  1. Use collections, since Sets doesn't allow duplicates and lists can be shuffled

  2. Adapt (if not already) your class Question, so you can used in the Set and so not allowing duplicates...(by this override equals AND hashcode)

  3. populate the Collection, shuffle it, get a random element of it


Option2: If you only want one of the questions at random

this is quite the same,

  1. instead of using a set use a list...
  2. omit step 2 since duplicated questions are no a big deal...
  3. but still populate the Collection, shuffle it, get a random element of it

and there you are :)

Community
  • 1
  • 1
ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
1

Use Collections.shuffle on your List<Question>, then use an Iterator<Question> to pick out the questions as you click a button.

Assuming you implemented both equals and hashcode for your Question class, then a LinkedHashSet will remove the duplicates, so repetition won't happen.

Here is an Activity based on your class that should show these concepts.

public class QuizActivityMarketing extends Activity {

    private Iterator<Question> questionIterator;
    private TextView txtQuestion;
    private RadioButton rda, rdb, rdc, rdd;
    private Button butNext;

    private Question currentQ;
    private int score = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Define your views
        txtQuestion = (TextView) findViewById(R.id.textView1);
        rda = (RadioButton) findViewById(R.id.radio0);
        rdb = (RadioButton) findViewById(R.id.radio1);
        rdc = (RadioButton) findViewById(R.id.radio2);
        rdd = (RadioButton) findViewById(R.id.radio3);
        butNext = (Button) findViewById(R.id.button1);

        // Get and randomize the questions
        DbHelperMarketing db = new DbHelperMarketing(this);
        final List<Question> questions = db.getAllQuestions();
        Collections.shuffle(questions);
        questionIterator = new LinkedHashSet<Question>(questions).iterator();

        // Setup the first question
        if (questionIterator.hasNext()) {
            currentQ = questionIterator.next();
            setQuestionView(currentQ);
        }

        // Hook up the button-clicking
        butNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // Check the correct answer
                RadioGroup grp = (RadioGroup) findViewById(R.id.radioGroup1);
                RadioButton answer = (RadioButton) findViewById(grp.getCheckedRadioButtonId());
                Log.d("yourans", currentQ.getANSWER() + " " + answer.getText());
                if (currentQ.getANSWER().equals(answer.getText())) {
                    score++;
                    Log.d("score", "Your score" + score);
                }

                // Load the next question, if there are any
                if (questionIterator.hasNext()) {
                    currentQ = questionIterator.next();
                    setQuestionView(currentQ);
                } else { // Done asking questions
                    setQuestionView(null);

                    Intent intent = new Intent(QuizActivityMarketing.this, ResultActivity.class);
                    Bundle b = new Bundle();
                    b.putInt("score", score); //Your score
                    intent.putExtras(b); //Put your score to your next Intent
                    startActivity(intent);
                    finish();
                }
            }
        });
    }

    private void setQuestionView(Question currentQuestion) {
        if (currentQuestion != null) {
            txtQuestion.setText(currentQuestion.getQUESTION());
            rda.setText(currentQuestion.getOPTA());
            rdb.setText(currentQuestion.getOPTB());
            rdc.setText(currentQuestion.getOPTC());
            rdd.setText(currentQuestion.getOPTD());
        } else {
            txtQuestion.setText("");
            rda.setText("");
            rdb.setText("");
            rdc.setText("");
            rdd.setText("");
        }
    }

}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • Thanks for your response. I'm actually new to Java, so I was just wondering if you can explain what this means? – Pranjan Gandhi Mar 02 '16 at 21:17
  • Sure. Before I go too far, you are returning a List from your SQLite `getAllQuestions` method. I assume you know how to use that method and where to call it? – OneCricketeer Mar 02 '16 at 21:22
  • Yes, I am calling it in another class. QuizActivityMarketing.java This is the class is called when the user clicks the "quiz button" – Pranjan Gandhi Mar 02 '16 at 21:32
  • If you include that Activity code with [an edit to your question](http://stackoverflow.com/posts/35756604/edit), I could explain it better – OneCricketeer Mar 02 '16 at 21:34
  • Read the edits, then let me know if you would like more of an explanation – OneCricketeer Mar 02 '16 at 21:56
  • Any reason you removed int qid=0? – Pranjan Gandhi Mar 02 '16 at 22:05
  • Do you need it? The only thing I saw it being used for was an index in the list. – OneCricketeer Mar 02 '16 at 22:12
  • I seem to be getting an error. It says "Incompatible types. Required: Iterator Found: " The error appears at this code " questionIterator = new LinkedHashSet(questions).iterator(); – Pranjan Gandhi Mar 02 '16 at 22:12
  • Ooops, sorry, check again. I changed the `Iterator` at the top – OneCricketeer Mar 02 '16 at 22:14
  • You can keep `qId` if you only want to ask 5 questions, but this code will ask every question from the SQLite database. – OneCricketeer Mar 02 '16 at 22:15
  • Thanks so much! It worked. Your help is very much appreciated. I know this is asking too much, but do you have an idea of how I can display the users score after they answer the 5 questions? – Pranjan Gandhi Mar 02 '16 at 22:23
  • From `ResultActivity`, in `onCreate`, you should be able to use `getIntent` to get the data that you passed into it from `QuizActivityMarketing`. You just need to do something like `int score = getIntent().getIntExtra("score", 0)` where 0 is the "default value" if the "score" key was not found in the Intent. – OneCricketeer Mar 02 '16 at 22:25
  • Would that display the score? And If I want to give different comments depending on their score, I just use a simple if and else statement correct? – Pranjan Gandhi Mar 02 '16 at 22:29
  • That would get the value of the score. You would still need to put it into a TextView with `setText(""+score)` (be careful with setText, since it also allows int parameters). And yup, regular if-else for any conditions you want to set on the scores – OneCricketeer Mar 02 '16 at 22:31
  • For some reason, the score displayed is always "0". Even if I answer the questions corretly – Pranjan Gandhi Mar 02 '16 at 22:34
  • Like I said, if the Intent does not contain the key "score", it will default to 0. – OneCricketeer Mar 02 '16 at 22:35
  • So how would I fix that? Would you like to see the ResultActivity class? – Pranjan Gandhi Mar 02 '16 at 22:36
  • If the process demonstrated here doesn't fix it, then sure. http://stackoverflow.com/a/7325248/2308683 – OneCricketeer Mar 02 '16 at 22:39
  • The link you posted has a great solution, but unfortunately, I'm not sure what I should be putting in my code. What do I input as the value? Any way you can explain more? – Pranjan Gandhi Mar 02 '16 at 23:41
  • The first code block is already in your onClick method for starting the next activity and sending the score with a `Bundle`. The second code block should be placed in `onCreate` of ResultActivity and use `getInt` as I mentioned before, instead of `getString` – OneCricketeer Mar 02 '16 at 23:45
  • You make Intent, then put extras into it, then start the next activity, and get extras out. That is the simplest explanation I can provide. The only other reason you should be getting 0 is if this condition isn't actually true. `currentQ.getANSWER().equals(answer.getText())` – OneCricketeer Mar 02 '16 at 23:48
  • The new variable name would be "score"? – Pranjan Gandhi Mar 02 '16 at 23:50
  • Name it whatever is easiest for you... You have `b.putInt("score", score);`, so doing `int score = extras.getInt("score");` makes sense to me. ` – OneCricketeer Mar 02 '16 at 23:52
  • I edited my question to show a little of the ResultActivity.java class. I am not sure how to output the score as it says "Variable score is never used" – Pranjan Gandhi Mar 02 '16 at 23:57
  • Did you make a field named score? Remove `int` from the front of `int score = extras.getInt("score");` or move the `setText` inside the if-statement. – OneCricketeer Mar 03 '16 at 00:06
  • The score displayed is still "0". I have posted the entire ResultActivity class for you – Pranjan Gandhi Mar 03 '16 at 00:14
  • Well, the problem lays in the Question asking code for when you do `score++`, then. If you can't see `Log.d("score", "Your score"+score);` in the Logcat, then that is a sign that it isn't working – OneCricketeer Mar 03 '16 at 00:17
  • How would I fix that? Could the problem be that my DbHelperMarketing class is wrong and it can't find the answer? The only place I have put the answer for the question is in the "Add Question" method in the DbHelperMarketing class. The answer is the last part of the question, ie. "B", or "C". Is that wrong? – Pranjan Gandhi Mar 03 '16 at 00:19
  • Yes, the logcat does not show that. It only shows the yourans (which is the value chosen by the user) – Pranjan Gandhi Mar 03 '16 at 00:20
  • Do the strings look the same on the yourans line? There may be additional spacing, so you could do `currentQ.getANSWER().trim()` – OneCricketeer Mar 03 '16 at 00:23
  • The problem still persists. I have edited my entire question to match the code that I have in front of me. Maybe you can spot the error? – Pranjan Gandhi Mar 03 '16 at 00:33
  • `getANSWER()` looks like it returns `"B"`, for example. That **does not equal** the string that would be returned by `getOPTB()`. When I asked "Do the strings look the same on the yourans line?" I meant you should be seeing `answer answer`, and **not** `B answer` – OneCricketeer Mar 03 '16 at 01:12
  • Ohh I apologize. That was my fault. Do you have any suggestions on how to fix the issue? – Pranjan Gandhi Mar 03 '16 at 01:41
  • Change the last parameter of the Question object to the string that is the actual answer instead of "B", for example – OneCricketeer Mar 03 '16 at 01:48
  • Thanks! That worked. I really appreciate all your help. You were amazing! Thanks – Pranjan Gandhi Mar 03 '16 at 02:46