Android Studio basic quiz issue - java

So I'm trying to make a quiz in which I will have 4 buttons for possible answers. I want to check if the right button is pressed, if so I want to change the image for about 2 seconds and load the next question (which will be an image stored in an array) this will be in a for loop the length of the question array I believe?
I'm having some trouble with this, as I'm also unsure on how to load a new question and then it know which button needs to be pressed, for example. question 1 might need button 1 pressing but question 2 might be button 3 but I don't want to change activity.
creating the array and setting image view:
private int[] ImageArr = new int[5];
private ImageView image = (ImageView) findViewById(R.id.Question_ImgView);
filling array:
public void FillImage() {
ImageArr[0] = R.drawable.img1;
ImageArr[1] = R.drawable.img2;
ImageArr[2] = R.drawable.img3;
ImageArr[3] = R.drawable.img4;
ImageArr[4] = R.drawable.img5;}
this is then called in the "onCreate method" to fill array on launch
then i will have a questions method, this is where I want the before mentioned things to happen.
tldr; I need to know how to loop through an image array if correct button is pressed (correct button changes for each question), and change the text on the buttons, till all questions are answered.
any help would be appreciated, thanks in advance. :)

I think the best thing you should do is to create a Question class.
public class Question {
#DrawableRes
private int imageId;
private String[] answers;
private int correctAnswerIndex;
public Question(int imageId, int correctAnswerIndex, String... answers) {
this.imageId = imageId;
this.correctAnswerIndex = correctAnswerIndex;
this.answers = answers;
}
#DrawableRes
public int getImageId() { return imageId; }
public String[] getAnswers() { return answers; }
public int getCorrectAnswerIndex() { return correctAnswerIndex; }
}
This class represents a question. It has
an imageId field to store the image of the question
an answers field to store all the possible answers that the user can choose
a correctAnswerIndex to store the correct answer. This actually stores the index of the correct answer in the answers array. Say you have {"blue", "red", "green", "yellow"} as the answers array and the correct answer is blue, you will set the correct answer index to 0.
Don't understand how to use it? Let's see an example.
At the moment, you have an array of image ids. You should change that to an array of Questions.
private Question[] questions = new Question[4];
And your fillQuestion method would be:
questions[0] = new Question(R.drawable.sweeper_is_handsome, 0, "True", "False", "Maybe", "I don't know");
questions[1] = new Question(R.drawable.no_one_can_beat_jon_skeet_in_reputation, 1, "True", "False", "Maybe", "I don't know");
// you get the idea.
As you can see, the answer to the first question is "True" (correctAnswerIndex = 0) and that to the second question is "False" (correctAnswerIndex = 1).
Now you have an array full of questions. How do you display it?
I think you can work out how to display the image yourself, so let's focus on how to get the buttons working.
I guess your buttons will be in an array, right? If it is isn't, then you're totally doing this wrong. Just add four buttons to an array, it's simple.
You can use the same on click handler for each button. It doesn't matter. In the on click listener, you have a view parameter like this right?
public void buttonOnClick(View view) {
// ⬆︎
// here
}
If you are doing this right, view should be an item in your buttons array. You can use the indexOf method to get the index of the button in the array. If this index matches the correctAnswerIndex of the question, the user chose the correct answer!
But how do you know which question is displaying? You create a variable in your activity class called questionIndex to keep track of it! It should start at 0 and each time you display a new question, you increment it!
EDIT:
This is how your button on click handler would look like:
int pressedButtonIndex = btns.indexOf(view);
int correctAnswerIndex = questions[questionIndex].getCorrectAnswerIndex();
if (pressedButtonIndex == correctAnswerIndex) {
// This means the user chose the correct answer
if (questionIndex == 4) {
// This is actually the last question! No need to display the next!
return;
}
// load next question
questionIndex++;
someImageView.setImage(questions[questionIndex].getImageId());
for (int i = 0 ; i < 4 ; i++) {
btns[i].setText(questions[questionIndex].getAnswers()[i]);
}
// YAY! The next question is displayed.
} else {
// User chose the wrong answer, do whatever you want here.
}

I would like to give a general approach to your question, you can or may need to modify according to your needs,
You have an Image Array of questions and would like to know the correct Button was pressed or not, for that you will need the options and a correct answer to compare with the Button clicked to check if the correct Button was pressed or not,
and you do not need to loop through all the questions at once, what you can do is when the button is pressed, compare button text with the correct answer and if its correct then show the next question image, some code example for the same,
if(btnClicked.getText().toString().equals("Correct Answer")){
questionPos++;
imgView.setImageResource(questionPos);
// Update all the buttons as per the new options
btn1.setText(options1);
// .... like wise update other buttons
}
see if this makes sense
Edit
as per you are asking how to know which button is clicked you can do something like this ...
btn1.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view) {
if(btn1.getText().toString().equals("Correct Answer")){
questionPos++;
imgView.setImageResource(questionPos);
// Update all the buttons as per the new options
btn1.setText(options1);
}
}
});
// Similarly you can do for all other buttons

Related

Getting input from multiple button groups in Java

I have an array of question, an array of possible answers and an array of properties I want to find out by answering the questions
String[] questions = new String[]{"Question1", "Question2", "Question3"};
String[] possibleAnswers = new String[]{"yes,no", "yes,no", "big,small"};
String[] properties = new String[]{"", "", ""};
I created a label for every question and JRadioButtons for every answer for that question by using split on the corresponding element in the possibleAnswers array.
for (int i = 0; i < questions.length; i++) {
//label that holds the current question
JLabel questionLabel = new JLabel(questions[i]);
questionPanel.add(questionLabel);
// string that holds answers for current question i.e. {yes, no}
String[] currentQuestionAnswers = possibleAnswers[i].split(",");
ButtonGroup buttonGroup = new ButtonGroup();
for (int j = 0; j < currentQuestionAnswers.length; j++) {
JRadioButton btnRadio = new JRadioButton(currentQuestionAnswers[j]);
// action listener that will store the selected answer and the question
btnRadio.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
answer = btnRadio.getText();
// some code that moves answer at the right index in the properties array
}
});
buttonGroup.add(btnRadio);
questionPanel.add(btnRadio);
}
}
This image shows what I want it to look like.
For each question I want to find a property. Let's say {Question1, Question2, Question3} are actually these questions {"talks?", "expensive?", "dimension?"}. When I get the text from the selected buttons, I'll have talks -> yes, expensive -> no, dimension -> big, so the properties array will become {"yes", "no", "big"}.
I know how to get the selected answer, but I can't figure out how to find the question that corresponds to that answer. I thounght I can somehow use the button groups I created, but I don't know how.
I hope this makes sense and someone can help. Thank you.
One way to do it would be to extend JRadioButton and add a simple ID field (a tag). I can't test this code right now but I think
it should work.
class MyRadioButton extends JRadioButton{
private int tag;
public getTag(){ return tag;}
public setTag(int val){ tag = val}
}
And then in the actionPerfomed method, just check this tag and take an appropriate action based on it.
int tag = 0;
btnRadio.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
answer = btnRadio.getText();
switch(btnRadio.getTag()){
case 0:
//do some action
break;
case 1:
....
}
// some code that moves answer at the right index in the properties array
}
});
btnRadio.setTag(tag++);//this will set a unique tag for each radio button
buttonGroup.add(btnRadio);
Alternatively, if you don't want to extend JRadioButton,which arguably might be overkill for your use case, you can use RadioButton.setActionCommand and ActionEvent.getActionCommand
btnRadio.setActionCommand("some_unique_string")
and then just check this command string in actionPerformed
if("some_unique_string".equals(ae.getActionCommand())
//do something

Turns issue in java game [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I've created a simple game which a player plays against computer.
I've got an issue in the timing of the turns, the computer should be the first to make a move than the real player should make his move by clicking LeftChoice or RightChoice button.
Here's my problem at code:
public class GameForm extends javax.swing.JFrame {
/**
* Creates new form GameForm
*/
final int SIZE = 10;
int CurrentSize = 10;
int PC_SUM=0;
int HUMAN_SUM=0;
boolean PC_TURN = true;
int[] RandArr = new int[SIZE];
public GameForm() {
initComponents();
}
public void init(){
for(int i = 0 ; i<SIZE;i++){
RandArr[i] = (int)(Math.random()*100)+1;
}
jTextField3.setText("");
jTextField4.setText(Integer.toString(PC_SUM));
jTextField5.setText(Integer.toString(HUMAN_SUM));
}
public void HUMAN_updateLeft(){
HUMAN_SUM+=RandArr[0];
jTextField5.setText(Integer.toString(HUMAN_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = 1 ; i<=CurrentSize;i++){
NewRand[i-1] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
PC_TURN = true;
}
public void HUMAN_updateRight(){
HUMAN_SUM+=RandArr[CurrentSize-1];
jTextField5.setText(Integer.toString(HUMAN_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = CurrentSize-1 ; i>=0;i--){
NewRand[i] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
PC_TURN = true;
}
public static boolean WhoIsBigger(int[] arr){
int even=0,odd=0;
for(int i=0;i<arr.length;i+=2){
if(i%2==0){
even+=arr[i];
odd+=arr[i+1];
}
else{
odd+=arr[i];
even+=arr[i+1];
}
}
return even>odd;
}
public void PC_updateLeft(){
PC_SUM+=RandArr[0];
jTextField4.setText(Integer.toString(PC_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = 1 ; i<=CurrentSize;i++){
NewRand[i-1] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
}
public void PC_updateRight(){
PC_SUM+=RandArr[CurrentSize-1];
jTextField4.setText(Integer.toString(PC_SUM));
jTextField1.setText(Arrays.toString(RandArr));
CurrentSize--;
int [] NewRand = new int[CurrentSize];
for(int i = CurrentSize-1 ; i>=0;i--){
NewRand[i] = RandArr[i];
}
RandArr = NewRand;
jTextField2.setText(Arrays.toString(RandArr));
}
public void PC_TURN(){
if(WhoIsBigger(RandArr))
PC_updateLeft();
PC_updateRight();
}
public void FullGame(){
while(RandArr.length>0){
if(PC_TURN){
PC_TURN();
PC_TURN = false;
}
}
}
//start button listener
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
init();
jTextField2.setText(Arrays.toString(RandArr));
jTextField1.setText("-");
jButton1.setEnabled(false);
FullGame();
}
//left button listener
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
HUMAN_updateLeft();
}
//right button listener
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
HUMAN_updateRight();
}
How can i know that the real player has made his move so it'll change PC_TURN to True and the game will move on?
Firstly, you should follow Java Naming Conventions when it comes to naming your variables. As it stands, PC_TURN looks as though it is a constant, although it is not a constant since you are changing it's value. So a more appropriate name would be pcTurn.
You also seem to have a method called PC_TURN() which I am assuming is the method which causes the computer to take it's turn and do something. So it would be better if this was named something descriptive like takePCTurn(). Notice the use of camelCase throughout. Capital letters at the start of a name should be reserved for classes and interfaces, not variables or methods.
The same goes for your method name
public void FullGame()
should be written as
public void fullGame()
Keeping to coding conventions like this make it easier for others to read and understand your code and keep everything neat and tidy. It's a good habit to get into. :)
I don't know where your left and right buttons are being declared or what you have named them, but you will need to add an event listener to each button which causes something to happen when they are clicked. I also am unsure about the purpose of RandArr.length > 0. You really don't need a loop here since this is an application with a GUI, it is never going to close unless you explicitly tell it to (e.g by clicking the close button). So I will just give you a generic solution.
You basically want the players turn to trigger the computer to take it's turn until some game over condition is met.
Example:
//Assuming this is called when the Start button is clicked
public void fullGame() {
takePCTurn();
}
public void takePCTurn() {
//Do PC's turn logic
//You might want to check if the Computer Won the game here
}
class PlayerTurnListener implements ActionListener() {
public void actionPerformed(ActionEvent e) {
//Do Player's turn logic
//You might want to check if the Player Won the game here
takePCTurn();
}
}
//We can create an instance of our listener and add it to both buttons
PlayerTurnListener playerTurnListener = new PlayerTurnListener();
leftButton.addActionListener(playerTurnListener);
rightButton.addActionListener(playerTurnListener);
So the first thing that happens is fullGame() is called by your Start button which then calls takePCTurn(); causing the computer to take it's turn. Now nothing will happen until the player clicks the left or right button. When they do this, the PlayerTurnListener's actionPerformed() method is called and you can do some logic in there and then takePCTurn(); will be called once again.
Rinse and repeat until gameover.
Hope that helps :)
You should attach a clickListener onto the left and right buttons. Then when the user clicks one that event will be fired. You should change PC_TURN to true there and re-run the loop if needed.
Example:
JButton yourButton = new JButton("Your Button");
yourButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
PC_TURN = true;
// extra code
}
});
If this is a Swing or other GUI then you will need to get rid of the while loop.
Remember that GUI programs are non-linear and are event-driven, and so rather than a restricting while loop which risks completely feezing your GUI, you would change the program's state depending on whose turn it is -- have a variable indicating whose turn it is -- and then change the behavior of the program based on the state.
If you need more specific help, then you're going to need to ask a much more complete question including one with enough code and explanation to allow us to understand your problem better (but not too much code).
Regarding the code you've posted:
Yes, definitely get rid of that while loop.
Your code is hard to understand, mainly because you're variable naming is poor. Rather than using variable names like jTextField1, use names that make logical sense, that make your code "self-debuggin", such as humanScoreField and computerScoreField, etc.
Also learn and follow standard Java naming practices including having all variables start with lower case letters, classes with upper case letters, use camelCase for all except for constants which are all upper-case.
Tell more about just what this code is supposed to be doing, what the buttons and the JTextfields represent, what behaviors you desire, etc...

How to fix ArrayIndexOutOfBoundsException when a activity is reloaded in Android?

I have created programmatically, 5 radio groups with 4 radio buttons each. I set OnClickListener on the reset button that i have created too. I want when someone clicks the button, to restart my activity. How is it even possible? When the app first time starts, it works fine but when i press the button to reload the activity, the emulator crashes. If i comment the lines where i create the radio groups and the radio buttons and i press the button, the activity is reloading fine otherwise i have this error: Unable to start activity ComponentInfo{...}: java.lang.ArrayIndexOutOfBoundsException: length=4; index=4. How can reload the activity without issues?
Here is my code:
answerGroup = new RadioGroup[5];
answer = new RadioButton[4];
int i = 0;
for (Question qn : questions) {
answerGroup[i] = new RadioGroup(this);
answerGroup[i].setOrientation(RadioGroup.VERTICAL);
int j = 0;
for (Answer an : answers) {
if (qn.getID() == an.getQuestion_id_answer()) {
answer[j] = new RadioButton(this);
answer[j].setText(an.getAnswer());
answerGroup[i].addView(answer[j]);
j++;
}
}
linearLayout.addView(answerGroup[i]);
i++;
}
restartButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);
}
});
Thanks!
The activity is probably trying to reference to old view elements (from before the Activity restart). Try to add your view components:
RadioGroup
RadioButton
As class variables. Can you try that and tell me what it is doing? I will update this answer according to the input you give me.
EDIT:
I assume that you are using a ArrayList<Question> and ArrayList<Answer> as the questions and answers variable.
for (Question qn : questions) {
RadioGroup answerGroup = new RadioGroup(this);
answerGroup.setOrientation(RadioGroup.VERTICAL);
for (Answer an : qn.getAnswers()) {
if (qn.getID() == an.getQuestion_id_answer()) {
RadioButton answer = new RadioButton(this);
answer.setText(an.getAnswer());
answerGroup.addView(answer);
}
}
linearLayout.addView(answerGroup);
}
Maybe you should add a getter method to your question called: getAnswers(); and a variable to your Question model called List<Answer> answers. Ofcourse, these answers need to be set before you try to do anything with them.
You must debug your code, probably not all your questions have 4 answers.
If one of your questions have more than 4 answers (eg: 5), and you try to loop through them you get the ArrayIndexOutOfBoundsException because j>=4.
As a solution: try to use a List for your RadioButtons:
List<RadioButton> answer = new ArrayList<RadioButton>();
And for each iteration add a new RadioButton:
answer.add(new RadioGroup(this));
PS: Also i suggest you to use recreate() method to reload/recreate your activity.

How do you iterate through dynamically created objects?

Lets say you have an object like this and you want to have the program go through each dynamically created Checkbox to see if it has not been checked.
If has not been checked, then the program should create a notification alerting the user that one or more of these objects has not been checked.
What is the best way to have the program identify whether the checkbox is checked or not?
Each time I run the program, it only applies to the last created Checkbox regardless of how many checked or unchecked checkboxes proceed it.
Thank you for your time.
View ObjectView;
CheckBox check;
//A whole bunch of code here.
public void onClick(View arg0) {
if (check==null){
}
else if (check==null || check.isChecked()){
}
else {
ObjectView.getId();
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(getActivity())
.setSmallIcon(android.R.drawable.stat_notify_more)
.setContentTitle("Items missing")
.setContentText("One or more items are missing");
int ID_Notify = 01;
getActivity();
NotificationManager managenote = (NotificationManager)getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
managenote.notify(ID_Notify, mBuilder.build());
Im gonna help you with an example of my code and try to explain it, aware that im not gonna babysit you (means you cant just copy paste) because i still have some work to do.
First, a new dynamic spinner will be created everytime you click a button (inside onClick) :
Spinner spinner = new Spinner(this);
spinner.setAdapter(spinChildAdapter);
parentSpinner.addView(spinner);
spinner.setId(totalDynamicChild); //the spinner's id will be the increment from 0
spinnderIdList.add(totalDynamicChild); //list of the dynamic spinner ID
totalDynamicChild++;
Then, we can access those dynamic Spinners with :
for(int i = 0; i < totalDynamicChild; i++)
{
Spinner s = (Spinner)findViewById(spinnderIdList.get(i));
//do something with the spinner's object here
}
Feel free to comment if you have some questions.

Android beginner onClick crash

I'm programming Android for the first time and I'm having some difficulties. The idea is to make a guessing game app in which the user takes a number in his/her head and the app tries to guess it. The user will give hints like higher and lower to the app. For some reason the app crashes after I press the start button. Because of this, I know that there is an error in the onClick method but since it shuts down immediately after I press the start button, I can't use something like a println to debug.
So actually I have 2 questions:
Where does my reasoning fail? (or show me how to figure out my mistakes)
How can I debug things like this?
The start, higher and lower are all buttons in the program.
#Override
public void onClick(View arg0) {
int min = 0;
int max = 100;
Random random = new Random(100);
int answer = 0;
if (arg0 == start) {
answer = random.nextInt(100);
buttonTextView.setText(answer);
}
else if (arg0 == higher){
min = answer;
answer = random.nextInt((max - min) + min);
buttonTextView.setText(answer);
}
else if (arg0 == lower) {
max = answer;
answer = random.nextInt((max-1) - min);
buttonTextView.setText(answer);
}
}
where does my reasoning fail?
You are using the wrong setText() method. In the TextView Docs you will see that there is one which takes an int, this is for retrieving a String resource that you have in your strings.xml so you would pass it a resource id. So your setText() is looking for a resource with the id of whatever your answer variable is. You will want to convert this to a String with something like
buttonTextView.setText(String.valueof(answer));
or one of several different ways.
How can I debug things like this?
When your app crashes there will be an exception in your logcat. This answer can help you to read your logcat. To open your logcat window in Eclipse, if it isn't already, you can do this
Window --> Show View --> Other --> Android --> LogCat
A couple side notes
You should change your params like in onClick() to something meaningful so I would change
public void onClick(View arg0)
to something like
public void onClick(View v) // v for view, could also be view, btn
// whatever makes sense to you and others who may read it
You also should compare the id of your View clicked instead of the View itself. So you would compare it with something like the following (assuming you changed arg0 to v)
if (v.getId() == R.id.start) // Assuming start is the id in your xml of your Button
// this will also allow you to use a switch statement
Your variables in onClick() (min, max, and answer) should be initialized outside of onClick() or they will be reset to the default values with each click which I'm pretty sure you don't want (thanks to 323go for pointing that out).

Categories

Resources