Home > Mobile >  How create a random answers in quiz, android studio(java)?
How create a random answers in quiz, android studio(java)?

Time:06-29

I am tring to do a quiz app, there is a random flag and random 4 answers, one of them should be a correct answer and random 3.

For now I have only been able to random answers, but sometimes I have the same answer several times. Fails to random 3 different answers that will not repeat themselves and add to that the correct answer.

package com.example.guesstheflag;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.media.Image;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class startGame extends AppCompatActivity {

    Integer[] flags ={
            R.drawable.france,
            R.drawable.england,
            R.drawable.brazil,
            R.drawable.belgium,
            R.drawable.germany,
            R.drawable.israel,
            R.drawable.russia,
            R.drawable.spain,
            R.drawable.ukrain,
    };

    String []answers = {
            "france",
            "england",
            "brazil",
            "belgium",
            "germany",
            "israel",
            "russia",
            "spain",
            "ukrain",
    };

    ListView listView;
    ImageView imageView;

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

        listView = findViewById(R.id.myList);
        imageView = findViewById(R.id.imagernd);

        MyAdapter myAdapter = new MyAdapter();
        listView.setAdapter(myAdapter);

        //rnd image
        Random rndImg = new Random();
        int img = rndImg.nextInt(flags.length);
        imageView.setImageResource(flags[img]);
    }

    // functions for answers list
    class MyAdapter extends BaseAdapter{
        @Override
        public int getCount() {

            return 4;
        }

        @Override
        public Object getItem(int i) {
            return answers[i];
        }

        @Override
        public long getItemId(int i) {

            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            LayoutInflater layoutInflater = getLayoutInflater();
            View row = layoutInflater.inflate(R.layout.custom, null);

            TextView textView = row.findViewById(R.id.myText);

            Random rnd = new Random();
            int name = rnd.nextInt(answers.length);

            textView.setText(answers[name]);

            return row;
        }
    }
}

CodePudding user response:

You can use Collections.shuffle.

List<String> answers = new ArrayList<>(Arrays.asList(
        "france",
        "england",
        "brazil",
        ...
));

Map<String, Integer> flags = new HashMap<>(){{
    put("france", R.drawable.france);
    put("england", R.drawable.england);
    put("brazil", R.drawable.brazil);
    ...
}};

At somewhere you want to shuffle the order of the ArrayList answers:

Collections.shuffle(answers);

To set answer text of i:

textView.setText(answers.get(i));

To set flag image of i:

imageView.setImageResource(flags.get(answers.get(i)));

The point is not to draw an index randomly but to shuffle the ArrayList itself.

CodePudding user response:

Assumptions

  1. The correct answer for a flags array is equal to the same index in the answers array.
  2. The random options (for an answer) also comes from the answers array.

Requirement

  1. For a given question, show 4 options. Out of which one has to be a correct answer and the other 3 has to be random options from the answers array.
  2. The random options should not repeat
  3. The random options should not include the correct answer

Solution

You need to change your MyAdapter class to be as follows

class MyAdapter extends BaseAdapter {
        // Internal variable to hold the options
        ArrayList<String> options = new ArrayList<>();

        // Function to call which generates the random options
        public void generateOptions(int correctAnswerIndex) {
            // Clear the internal options variable
            this.options = new ArrayList<>();
            // Start a random generator
            Random rnd = new Random();
            // Keep generating options till we have 4 random selected options
            while(this.options.size()<4) {
                // Get a random number
                int name = rnd.nextInt(answers.length);
                // Check if random number is equal to correctAnswerIndex, if so, skip this round
                if(name==correctAnswerIndex)
                    continue;
                // Get the text for the random option
                String optionText = answers[name];

                // A flag to indicate if the correct answer should be used for this option position
                int chanceToAddCorrectAnswer = 0;
                // Generate a random number from 0 to 100
                chanceToAddCorrectAnswer = rnd.nextInt(100);
                // Check if the random number is an odd number (divisible by 3) and
                // the correct answer is not already added to the options
                if(chanceToAddCorrectAnswer%3==0 && this.options.indexOf(answers[correctAnswerIndex])==-1) {
                    // Add the correct answer
                    this.options.add(answers[correctAnswerIndex]);
                }
                else {
                    // Check if we already have 3 random options selected and the correct answer has not be added, then add it 
                    if(this.options.size()==3 && this.options.indexOf(answers[correctAnswerIndex])==-1) {
                        // Add the correct answer as the last option
                        this.options.add(answers[correctAnswerIndex]);
                    }
                    else {
                        // Check if the current selected random option is already added or not
                        if (this.options.indexOf(optionText) == -1) {
                            // Add this random option
                            this.options.add(optionText);
                        }
                    }
                }
            }
        }

        @Override
        public int getCount() {

            return 4;
        }

        @Override
        public Object getItem(int i) {
            return this.options.get(i);
        }

        @Override
        public long getItemId(int i) {

            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            LayoutInflater layoutInflater = getLayoutInflater();
            View row = layoutInflater.inflate(R.layout.custom, null);
            TextView textView = row.findViewById(R.id.myText);
            textView.setText(this.options.get(i));
            return row;
        }
    }

Than change the onCreate method to do the following

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

        listView = findViewById(R.id.myList);
        imageView = findViewById(R.id.imagernd);

        MyAdapter myAdapter = new MyAdapter();
        listView.setAdapter(myAdapter);

        //rnd image
        Random rndImg = new Random();
        int img = rndImg.nextInt(flags.length);
        
        myAdapter.generateOptions(img); // Tell your adapter to generate random options

        imageView.setImageResource(flags[img]);
    }

Explanation

Basically you need to ensure the following conditions

  1. The correct answer is ignored while trying to pick random options from the answers array.
  2. The options which are already picked are also ignored for consecutive random option.

In the above MyAdapter we create a function to generate the random options called generateOptions whenever this function is called it will generate the random number while ensuring the above conditions are met.

I have extensively commented the code but if you need more clarity, feel free to comment.

Suggestions

  1. Always include the list inside the Adapter class to ensure your dependency is internal and not external, since usually these are to be declared in their own files. (try to stay with one class per file)
  2. For a game, performance is key and I would suggest to generate all the list of questions and it's associated random options before the game starts. Allowing the user to go from question to question quickly. This is to be done in the startGame class with a function like SetupGame which is called in the onCreate or whenever the user taps "Start" or "Restart"
  • Related