1

I'm creating a android project, a quiz application

and when I try to random the id it duplicates I don't know how to fix this I need my program to generate a random number without any duplication

hers my code Activity

    package com.example.testing;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.concurrent.TimeUnit;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Typeface;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class QuestionActivity extends Activity{

    ArrayList<Question> quesList;
    int score = 0;
    int qid = 0;
    int lives = 5;




    Question currentQ;
    TextView txtQuestion, times, scored, livess;
    Button button1, button2, button3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        QuizHelper db = new QuizHelper(this);  // my question bank class
        quesList = db.getAllQuestions();
        Random random = new Random();// this will fetch all quetonall questions
        currentQ = quesList.get( random.nextInt(quesList.size())); // the current question
        txtQuestion = (TextView) findViewById(R.id.txtQuestion);
        // the textview in which the question will be displayed
        // the three buttons,
        // the idea is to set the text of three buttons with the options from question bank
        button1 = (Button) findViewById(R.id.button1);
        button2 = (Button) findViewById(R.id.button2);
        button3 = (Button) findViewById(R.id.button3);

        livess = (TextView) findViewById(R.id.livess);
        // the textview in which  will be displayed
        scored = (TextView) findViewById(R.id.score);
        // the timer
        times = (TextView) findViewById(R.id.timers);
        // method which will set the things up for our game
        setQuestionView();
        times.setText("00:02:00");
        // A timer of 60 seconds to play for, with an interval of 1 second (1000 milliseconds)
        CounterClass timer = new CounterClass(60000, 1000);
        timer.start();
        // button click listeners
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // passing the button text to other method
                // to check whether the anser is correct or not
                // same for all three buttons
                getAnswer(button1.getText().toString());
            }
        });
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getAnswer(button2.getText().toString());
            }
        });
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getAnswer(button3.getText().toString());
            }
        });
    }
    public void getAnswer(String AnswerString) {
        if (currentQ.getANSWER().equals(AnswerString)) {
            // if conditions matches increase the int (score) by 1
            // and set the text of the score view
            score++;
            scored.setText("Score : " + score);




        } else if(lives > 1){
            lives--;
            livess.setText("Lives: " + lives);


        }

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

        }

        {


        }
        if (qid < 20) {
            // if questions are not over then do this
            Random random = new Random();
            currentQ = quesList.get( random.nextInt(quesList.size()));
            setQuestionView();
        } else {
            // if over do this
            Intent intent = new Intent(QuestionActivity.this,
                    ResultActivity.class);
            Bundle b = new Bundle();
            b.putInt("score", score); // Your score
            intent.putExtras(b); // Put your score to your next
            startActivity(intent);
            finish();
        }
    }
    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    @SuppressLint("NewApi")
    public class CounterClass extends CountDownTimer {
        public CounterClass(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
            // TODO Auto-generated constructor stub
        }
        @Override
        public void onFinish() {
            times.setText("Time is up");
            Intent intent = new Intent(QuestionActivity.this,
                    Result_Activity_TimesUp.class);
            Bundle b = new Bundle();
            b.putInt("score", score); // Your score
            intent.putExtras(b); // Put your score to your next
            startActivity(intent);
            finish();
        }
        @Override
        public void onTick(long millisUntilFinished) {
            // TODO Auto-generated method stub
            long millis = millisUntilFinished;
            String hms = String.format(
                    "%02d:%02d:%02d",
                    TimeUnit.MILLISECONDS.toHours(millis),
                    TimeUnit.MILLISECONDS.toMinutes(millis)
                            - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS
                            .toHours(millis)),
                    TimeUnit.MILLISECONDS.toSeconds(millis)
                            - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS
                            .toMinutes(millis)));
            System.out.println(hms);
            times.setText(hms);
        }
    }
    private void setQuestionView() {
        // the method which will put all things together
        txtQuestion.setText(currentQ.getQUESTION());
        button1.setText(currentQ.getOPTA());
        button2.setText(currentQ.getOPTB());
        button3.setText(currentQ.getOPTC());
        qid++;


    }


}

heres my database

package com.example.testing;

import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class QuizHelper extends SQLiteOpenHelper {
    private static final int DATABASE_VERSION = 3;
    // Database Name
    private static final String DATABASE_NAME = "mathsone";
    // tasks table name
    private static final String TABLE_QUEST = "quest";
    // tasks Table Columns names
    private static final String KEY_ID = "qid";
    private static final String KEY_QUES = "question";
    private static final String KEY_ANSWER = "answer"; // correct option
    private static final String KEY_OPTA = "opta"; // option a
    private static final String KEY_OPTB = "optb"; // option b
    private static final String KEY_OPTC = "optc"; // option c
    private SQLiteDatabase dbase;
    public QuizHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        dbase = db;
        String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_QUEST + " ( "
                + KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_QUES
                + " TEXT, " + KEY_ANSWER + " TEXT, " + KEY_OPTA + " TEXT, "
                + KEY_OPTB + " TEXT, " + KEY_OPTC + " TEXT)";
        db.execSQL(sql);
        addQuestion();

        // db.close();
    }
    private void addQuestion() {
        Question q1 = new Question("1. 5+2 = ?", "7", "8", "6", "7");
        this.addQuestion(q1);
        Question q2 = new Question("2. 2+18 = ?", "18", "19", "20", "20");
        this.addQuestion(q2);
        Question q3 = new Question("3. 10-3 = ?", "6", "7", "8", "7");
        this.addQuestion(q3);
        Question q4 = new Question("4. 5+7 = ?", "12", "13", "14", "12");
        this.addQuestion(q4);
        Question q5 = new Question("5. 3-1 = ?", "1", "3", "2", "2");
        this.addQuestion(q5);
        Question q6 = new Question("6. 0+1 = ?", "1", "0", "10", "1");
        this.addQuestion(q6);
        Question q7 = new Question("7. 9-9 = ?", "0", "9", "1", "0");
        this.addQuestion(q7);
        Question q8 = new Question("8. 3+6 = ?", "8", "7", "9", "9");
        this.addQuestion(q8);
        Question q9 = new Question("9. 1+5 = ?", "6", "7", "5", "6");
        this.addQuestion(q9);
        Question q10 = new Question("10. 7-5 = ?", "3", "2", "6", "2");
        this.addQuestion(q10);
        Question q11 = new Question("11. 7-2 = ?", "7", "6", "5", "5");
        this.addQuestion(q11);
        Question q12 = new Question("12. 3+5 = ?", "8", "7", "5", "8");
        this.addQuestion(q12);
        Question q13 = new Question("13. 0+6 = ?", "7", "6", "5", "6");
        this.addQuestion(q13);
        Question q14 = new Question("14. 12-10 = ?", "1", "2", "3", "2");
        this.addQuestion(q14);
        Question q15 = new Question("15. 12+2 = ?", "14", "15", "16", "14");
        this.addQuestion(q15);
        Question q16 = new Question("16. 2-1 = ?", "2", "1", "0", "1");
        this.addQuestion(q16);
        Question q17 = new Question("17. 6-6 = ?", "6", "12", "0", "0");
        this.addQuestion(q17);
        Question q18 = new Question("18. 5-1 = q?", "4", "3", "2", "4");
        this.addQuestion(q18);
        Question q19 = new Question("19. 4+2 = 19?", "6", "7", "5", "6");
        this.addQuestion(q19);
        Question q20 = new Question("20. 5+1 = ?", "6", "7", "5", "6");
        this.addQuestion(q20);
        Question q21 = new Question("5-4 = ?", "5", "4", "1", "1");
        this.addQuestion(q21);
        // END


    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_QUEST);
        // Create tables again
        onCreate(db);
    }
    // Adding new question
    public void addQuestion(Question quest) {

        // SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(KEY_QUES, quest.getQUESTION());
        values.put(KEY_ANSWER, quest.getANSWER());
        values.put(KEY_OPTA, quest.getOPTA());
        values.put(KEY_OPTB, quest.getOPTB());
        values.put(KEY_OPTC, quest.getOPTC());
        // Inserting Row
        dbase.insert(TABLE_QUEST, null, values);
    }
    public ArrayList<Question> getAllQuestions() {
        ArrayList<Question> quesList = new ArrayList<Question>();

        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_QUEST;
        dbase = this.getReadableDatabase();
        Cursor cursor = dbase.rawQuery(selectQuery, null);
        // looping through all rows and adding to list


        if (cursor.moveToFirst()) {
            do {
                Question quest = new Question();
                quest.setID(cursor.getInt(0));
                quest.setQUESTION(cursor.getString(1));
                quest.setANSWER(cursor.getString(2));
                quest.setOPTA(cursor.getString(3));
                quest.setOPTB(cursor.getString(4));
                quest.setOPTC(cursor.getString(5));
                quesList.add(quest);

            } while (cursor.moveToNext());
        }
        // return quest list
        return quesList;
    }
}
  • "I need my program to generate a random number without any duplication" - If you place that constraint on it, then it isn't random. You need to define your requirement more precisely. – Kevin Krumwiede Mar 14 '16 at 18:58
  • Do one thing, create a hasmap map of Question and boolean and if that question is presented put value as true else false. Now when you call random() method check if boolean is set to true or false if false show it to user else call random again. – dex Mar 14 '16 at 18:59
  • http://stackoverflow.com/questions/1519736/random-shuffling-of-an-array – CommonsWare Mar 14 '16 at 19:00
  • This could be one possible duplicate : http://stackoverflow.com/questions/4040001/creating-random-numbers-with-no-duplicates – dex Mar 14 '16 at 19:02

2 Answers2

2

Initialise an array that have the indecies of your original questions objects. e.g. init the array with the numbers from 0 and 19.

Then, when you get a random number use that value in the indecies array and remove it.

When you get the next random number get a random number between 0 and 18 and so on. This way you shouldn't care about duplicate you will always have a new question.

OnCreate:

ArrayList<Question> toSelectFrom = new ArrayList<Question>();
toSelectFrom.addAll(quesList);

Random:

Random random = new Random();
currentQ = toSelectFrom.get(random.nextInt(toSelectFrom.size()));
toSelectFrom.remove(toSelectFrom.indexOf(currentQ));

Here, I put the question objects at the array to select from instead of indecies. same approch same thing.

package com.example.testing;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.concurrent.TimeUnit;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Typeface;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class QuestionActivity extends Activity{

    ArrayList<Question> quesList;
    ArrayList<Question> toSelectFrom; // <--- HERE
    int score = 0;
    int qid = 0;
    int lives = 5;




    Question currentQ;
    TextView txtQuestion, times, scored, livess;
    Button button1, button2, button3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        QuizHelper db = new QuizHelper(this);  // my question bank class
        quesList = db.getAllQuestions();
        toSelectFrom = new ArrayList<Question>(); // <--- HERE
        toSelectFrom.addAll(quesList); // <--- HERE
        Random random = new Random();// this will fetch all quetonall questions
        currentQ = toSelectFrom.get( random.nextInt(toSelectFrom.size())); // the current question <-- edited here too.
        toSelectFrom.remove(toSelectFrom.indexOf(currentQ)); // <--- HERE
        txtQuestion = (TextView) findViewById(R.id.txtQuestion);
        // the textview in which the question will be displayed
        // the three buttons,
        // the idea is to set the text of three buttons with the options from question bank
        button1 = (Button) findViewById(R.id.button1);
        button2 = (Button) findViewById(R.id.button2);
        button3 = (Button) findViewById(R.id.button3);

        livess = (TextView) findViewById(R.id.livess);
        // the textview in which  will be displayed
        scored = (TextView) findViewById(R.id.score);
        // the timer
        times = (TextView) findViewById(R.id.timers);
        // method which will set the things up for our game
        setQuestionView();
        times.setText("00:02:00");
        // A timer of 60 seconds to play for, with an interval of 1 second (1000 milliseconds)
        CounterClass timer = new CounterClass(60000, 1000);
        timer.start();
        // button click listeners
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // passing the button text to other method
                // to check whether the anser is correct or not
                // same for all three buttons
                getAnswer(button1.getText().toString());
            }
        });
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getAnswer(button2.getText().toString());
            }
        });
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getAnswer(button3.getText().toString());
            }
        });
    }
    public void getAnswer(String AnswerString) {
        if (currentQ.getANSWER().equals(AnswerString)) {
            // if conditions matches increase the int (score) by 1
            // and set the text of the score view
            score++;
            scored.setText("Score : " + score);




        } else if(lives > 1){
            lives--;
            livess.setText("Lives: " + lives);


        }

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

        }

        {


        }
        if (qid < 20) {
            // if questions are not over then do this
            Random random = new Random();
            currentQ = toSelectFrom.get(random.nextInt(toSelectFrom.size())); // <<--- HERE
            toSelectFrom.remove(toSelectFrom.indexOf(currentQ)); // <<--- AND HERE
            setQuestionView();
        } else {
            // if over do this
            Intent intent = new Intent(QuestionActivity.this,
                    ResultActivity.class);
            Bundle b = new Bundle();
            b.putInt("score", score); // Your score
            intent.putExtras(b); // Put your score to your next
            startActivity(intent);
            finish();
        }
    }
    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    @SuppressLint("NewApi")
    public class CounterClass extends CountDownTimer {
        public CounterClass(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
            // TODO Auto-generated constructor stub
        }
        @Override
        public void onFinish() {
            times.setText("Time is up");
            Intent intent = new Intent(QuestionActivity.this,
                    Result_Activity_TimesUp.class);
            Bundle b = new Bundle();
            b.putInt("score", score); // Your score
            intent.putExtras(b); // Put your score to your next
            startActivity(intent);
            finish();
        }
        @Override
        public void onTick(long millisUntilFinished) {
            // TODO Auto-generated method stub
            long millis = millisUntilFinished;
            String hms = String.format(
                    "%02d:%02d:%02d",
                    TimeUnit.MILLISECONDS.toHours(millis),
                    TimeUnit.MILLISECONDS.toMinutes(millis)
                            - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS
                            .toHours(millis)),
                    TimeUnit.MILLISECONDS.toSeconds(millis)
                            - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS
                            .toMinutes(millis)));
            System.out.println(hms);
            times.setText(hms);
        }
    }
    private void setQuestionView() {
        // the method which will put all things together
        txtQuestion.setText(currentQ.getQUESTION());
        button1.setText(currentQ.getOPTA());
        button2.setText(currentQ.getOPTB());
        button3.setText(currentQ.getOPTC());
        qid++;
    }
}
hasan
  • 23,815
  • 10
  • 63
  • 101
  • This is the right idea, but the wrong implementation. Create a Set, if it contains your random number, generate another one. Otherwise, put your number in the Set so you know it's already used. – Francesc Mar 14 '16 at 19:02
  • I have no clue on how I will do that. Can you please help me with the coding. I've been developing this for 2 weeks now. Im new in Android. – Tyrell P. Zapanta Mar 14 '16 at 19:03
  • no its a bad approch to do what you suggest cause later when there is alot of used numbers. the later attempts will take forever. Imagine when he tries to select the last still question with index 9 for example. the probability is 1 to 19 – hasan Mar 14 '16 at 19:04
  • can you add me to facebook and discuss it to me steph.ancheta22@outlook.com – Tyrell P. Zapanta Mar 14 '16 at 19:13
  • OMG! IT WORKS I want to buy you a coffee right now send me an e-mail :) I want to thank you. steph.ancheta22@outlook.com – Tyrell P. Zapanta Mar 14 '16 at 20:10
-1

Edited:

private final Random mRandom  = new Random();

Somewhere populate your list:

List<Integer> values = new ArrayList<>(20);
for (int i = 0; i < values; ++i) {
    values.add(i);
}

Return a value:

private int getNextRandom(List<Integer> list) {
    int index = mRandom.nextInt(list.size());
    int value = list.remove(index);
    return value;
}
Francesc
  • 25,014
  • 10
  • 66
  • 84