Jony Kale
Jony Kale

Reputation: 979

Java select a random item from a multi array & not over use it again?

    private String[][] questions = 
    {
        {"Sky's color is black", "false"},
        {"The earth is round.", "true"}, 
        {"Google is written in PHP", "false"},
        {"This program is written in JAVA", "true"}, 
        {"Daniel is white", "true"}
    };

    public void selectRandomQuestion() {

    }

I want the system to select a random question from the array, and after it's selected, I want to print it + make the system remember that this question already was printed, so the system won't select that question again.

Example:

I got the question "Google is written in PHP", answered it, now I can not get this question anymore. After I run out of questions, system will turn boolean game to false, so the game will end.

How can I do this?

Upvotes: 3

Views: 431

Answers (6)

erencan
erencan

Reputation: 3763

You can insert Objects to a Set, it can be HashSet. A Set will maintain list of unique items. HashSet will maintain unique set of question objects. I also override equals method since it is called by HashSet fo uniqueness.

      public class Test { 
        public static void main(String[] args)
      { 

     HashSet<Question> setOfItems = new HashSet<String>();
        setOfItems.add(new Question("Sky's color is black",true));
        setOfItems.add(new Question("The earth is round.",false));
        setOfItems.add(new Question("Google is written in PHP",false));
        setOfItems.add(new Question("This program is written in JAVA",true));
        setOfItems.add(new Question("Daniel is white",false));
        
       while(!setOfItems.isEmpty())
       {
            Question selectedQuestion = selectRandomQuestion(setOfItems);
            //DO whatever needed.
       }
     public Question selectRandomQuestion(HashSet<Question> setOfItems) {
        String result = null;
        if(setOfItems.size() >0)
        {
            Random generator = new Random( );
            int index = generator.nextInt( setOfItems.size() );
            Iterator<Question> i = setOfItems.iterator(); 
            
            while(index<0)
            {
                 result = i.next();
                 index--;
            }
            setOfItems.remove(result); //Remove from Set
            
         }
         return current;
     }
   }
}


public class Question
        {
              private String question;
              private boolean answer;
              public Question(String question, boolean answer)
              {
                   this.question = question;
                   this.answer = answer;
              }
              @Override
              public boolean equals(Question q)
              {
                   return this.question.equals(q.getQuestion());
              }
              //Getter Setters
        }

Upvotes: 0

pjs
pjs

Reputation: 19853

Removing previously selected items from ArrayLists, as suggested by others, could work. An alternate solution is to shuffle your Array, and then just iterate through it. Once you get to the end, you'll have touched each question once and in a random order.

Upvotes: 1

Richard Tingle
Richard Tingle

Reputation: 17226

By far the simplest way to achieve this (but not what I recommend) is to use an Arraylist of Strings and then remove the used questions as you go

public class Test { 
    public static void main(String[] args) { 

        Random rnd=new Random();
        ArrayList<String> questions = new ArrayList<String>();
        ArrayList<Boolean> answers = new ArrayList<Boolean>();

        questions.add("Question 1");
        answers.add(true);

        questions.add("Question 2");
        answers.add(false);

        while (array.isEmpty()==false){
            int index=rnd.nextInt(questions.size());

            String question=questions.get(index);
            boolean answer=answers.get(index);

            questions.remove(index);
            answer.remove(index);

            //do whatever with the question
        }


    }

}


Object orientated alternative
A nicer object orientated way to do this, however, would be to create an object to hold the question and answer together

public class QAndA {
    public final String question; 
    public final boolean answer;

    public QAndA(String question, boolean answer) {
        this.question = question;
        this.answer = answer;
    }


}

And then hold those objects in an Arraylist

public class Test { 
    public static void main(String[] args) { 

        Random rnd=new Random();

        ArrayList<QAndA> array = new ArrayList<QAndA>();

        array.add(new QAndA("Question 1",true));
        array.add(new QAndA("Question 2",true));


        while (array.isEmpty()==false){
            int index=rnd.nextInt(array.size());

            QAndA question=array.get(index);
            array.remove(index);

            //do whatever with the question
        }


    }

}

Removing objects from an Arraylist is not a very quick option but given that the Arraylist is probably short this is unlikely to be an important factor. If it is consider some of the other collections. The fields in QAndA are declared public as the QAndA class is a glorified struct, again consider whether this is appropriate dependant on your usage.

Upvotes: 3

Marco Corona
Marco Corona

Reputation: 812

You could create an arrayList that indexes the question and has a boolean value, that points to if it has been asked or not. And to see when the game ends, just create a variable that is equal to questions.length and iterate that many times.

If you are against using an arrayList you could just add a 3rd row to your array:

private String[][] questions = 
{
    {"Sky's color is black", "false", "false"},
    {"The earth is round.", "true", "false"}, 
    {"Google is written in PHP", "false", "false"},
    {"This program is written in JAVA", "true", "false"}, 
    {"Daniel is white", "true", "false"}
};

The last row can point to if the question was accessed. Just to clear things up for the first question "Sky's color is black":

questionAsked = questions[0][0]
answer = questions[0][1]
ifAsked = questions[0][2]

Upvotes: 0

Wisienkas
Wisienkas

Reputation: 1751

You could make it somewhat object oriented by making a class representing each question and a class to draw random questions.

The class representing the question public class Question{

private boolean notShown = true;
private String question;

public Question(String s){

    this.question = s;
}
public boolean isNotShown(){

    return notShown;
}
public String GetQuestion(){


    notShown = false;
    return question;
}

public void setQuestionNotSeen(){

    notShown = true;
}
}

The class representing the draw

public class QuestionLister {


private ArrayList<Question> listOfQuestions;

public QuestionLister() {

    listOfQuestions = new ArrayList<>(0);

}
public QuestionLister(String s) {

    listOfQuestions = new ArrayList<>(0);
    listOfQuestions.add(new Question(s));

}


public void addQuestion(String s){

    listOfQuestions.add(new Question(s));
}

public String getRandomQuestion(){
    int r;
    boolean allSeen = true;

    for (Question question : listOfQuestions) {

        if(question.isNotShown()){

            allSeen = false;
        }
    }

    if(!allSeen){
        do{
            r = (int) Math.random() * listOfQuestions.size();

        } while(!listOfQuestions.get(r).isNotShown());

        return(listOfQuestions.get(r).GetQuestion());
    }

    return "All questions shown";
}

public void setAllQuestionsNotSeen(){

    for (Question question : listOfQuestions) {
        question.setQuestionNotSeen();
    }
}
}

Upvotes: 0

Jigar Joshi
Jigar Joshi

Reputation: 240870

See Random class javadoc and checkout Set<Integer>

Upvotes: 0

Related Questions