skip to Main Content

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;




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

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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"
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search