Android Studio (Java) not receiving sequentially correct Button values - java

I am currently working on a game where players are supposed to solve for X + Y with selection of 3 buttons (1 of which is answer) and a "Next" button to go to the next question (by replacing values of components into the next question's). However, I am not able to tally the answers because my tested selection (Button) is always testing the values of the next question
To give a little context,
questionCategories is an ArrayList of ArrayList with different levels
e.g. questionCategories.get(selectedLevel) returns ArrayList of different arithmetics
jumbleOptions populates 3 buttons with correct and incorrect answers which are housed in options
I'm having a situation where when answering Question 1, the shown option values belongs to Question 1, but the tested values (in test) are from Question 2.
e.g.
Qn1: 3 + 5 - A: 2, B: 8, C: 4
Qn2: 8 + 2 - A: 10, B: 11, C:12
When I attempt Qn1 on B and click "Next" to go to the next question (and test for correctness), Instead of testing B:8 my program ends up testing B: 11 instead. I have tried to Log the captured values of each Button and Question's answer but they are all correct and I am not sure where did I go wrong.
The code snippet is within onViewCreated, the first question is initialized to display because of placeholder text in the original element. I'm sorry if the code snippet does not make much sense, trying to keep it short so it's (hopefully) more readable.
// Initialize first question to display
questionNumber.setText("Question " + String.valueOf(qnNumDisplay));
questionTitle.setText(((questionCategories.get(selectedLevel)).get(0)).toString());
jumbleOptions(((questionCategories.get(selectedLevel)).get(0)));
do {
nextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Question q = (questionCategories.get(selectedLevel)).get(numQnAnswered);
// Increment question number related variable
numQnAnswered++;
// Replace displayable elements with next question
//Question Number
questionNumber.setText("Question " + String.valueOf(numQnAnswered));
questionTitle.setText(q.toString());
jumbleOptions(((questionCategories.get(selectedLevel)).get(numQnAnswered)));
boolean test = checkAnswer(String.valueOf(q.getAnswer()),
options.get(SELECTED_OPTION).getText().toString());
Log.d("Answer Correctness", String.valueOf(test));
}
});
counter++;
} while (counter < NUMBER_OF_QNS);

Let's simulate the scenario:
First question is set up manually, and next question is loaded based on button click. I assume numQnAnswered is 0 and you're getting the answer from your Question object of numQnAnswered th position, right?
final Question q = (questionCategories.get(selectedLevel)).get(numQnAnswered);
As your codes say so.
Notice here, carefully:
// Increment question number related variable
numQnAnswered++;
Now the problem however is, the answer is validated inside button click, I think you've forgot the fact that the first question was set up manually... & before checking the answer for that one you've incremented the numQnAnswered variable, thus your question is one step behind your answer. Hope it make sense.
Just decrement the numQnAnswered variable after the validation of current question.
// Initialize first question to display
questionNumber.setText("Question " + String.valueOf(qnNumDisplay));
questionTitle.setText(((questionCategories.get(selectedLevel)).get(0)).toString());
jumbleOptions(((questionCategories.get(selectedLevel)).get(0)));
do {
nextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Question q = (questionCategories.get(selectedLevel)).get(numQnAnswered);
// first we need to check answer of previous question
boolean test = checkAnswer(String.valueOf(q.getAnswer()),
options.get(SELECTED_OPTION).getText().toString());
Log.d("Answer Correctness", String.valueOf(test));
// Increment question number related variable
numQnAnswered++;
// Replace displayable elements with next question
//Question Number
questionNumber.setText("Question " + String.valueOf(numQnAnswered));
questionTitle.setText(q.toString());
jumbleOptions(((questionCategories.get(selectedLevel)).get(numQnAnswered)));
}
});
counter++;
} while (counter < NUMBER_OF_QNS);

Related

Java ArrayList indexes lagging behind in for-loop? [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 4 years ago.
So I'm a scrub at java, just started learning the language at a university course.
While trying to compare values of variables linked to objects to inserted values to make sure that there are no duplicates, I ran into an issue. It appears as if the objects are "lagging behind" in the lack of a better expression. See the commenting of the code for a better explanation.
The problem only appears if you add like 2 or more separate weapons and then try to re-add a weapon with the same name, it allows you to do so. If you add just one one weapon and then try to re-add it it says nope and the code works as intended.
So yeah, when I call the method printHeroInfo I still see that I can end up with several weapons with the same name. There is also another class called superWeapon, and if you think the code in there is relevant to this issue then let me know and I'll post that in a commment or something.
Thanks in advance for helping me with the head scratching.
import java.util.ArrayList;
public class superHero{
private ArrayList<superWeapon> superWeaponList;
private String superHeroName;
private String superHeroInfo;
public superHero(String superHeroName, String superHeroInfo){
this.superHeroName=superHeroName;
this.superHeroInfo=superHeroInfo;
superWeaponList=new ArrayList<superWeapon>();
}
public void addSuperWeapon(String superWeaponName, int superWeaponCharges){
superWeapon Obj = new superWeapon(superWeaponName, superWeaponCharges); // Making an object of the superWeapon class.
int size=superWeaponList.size(); // Gets the size of the array superWeaponList.
if(size==0){ /* If the size of the arary is zero, that means there are no weapons in it currently.
For that reason we don't need the for-loop we otherwise would need to compare the name of the weapon
we are trying to add against the pre-existing names of weapons in the array. */
superWeaponList.add(Obj);
System.out.println("The Superweapon"+superWeaponName+" has been added for the superhero "+superHeroName+".");
System.out.println(superWeaponName+" has "+superWeaponCharges+" charges.");
}
else{ /* If the size of the array is NOT zero, we need to compare the name of the weapon we are trying to add
against the weapons already existing in the array. This we do with the following for loop. */
for(int i=0;i<size;i++){
superWeapon temp_obj=superWeaponList.get(i);
String temp_name = temp_obj.getName();
System.out.println(temp_name); /* Why does the name lag behind one entry?
On the second entry it also shows the first entry. On the third entry it shows the second
entry and so on... The first place in an arraylist should be index=0,
so the for-loop starting at 0 should also be correct, right?
I just added this print to see what the current value for getName()
would end up returning. This is how I found the bug/error. */
if(temp_name!=superWeaponName){ // If the name doens't match then we add a new superweapon.
superWeaponList.add(Obj);
System.out.println("The superweapon "+superWeaponName+" has been added for the superhero "+superHeroName+".");
System.out.println(superWeaponName+" has "+superWeaponCharges+" charges.");
}else{ // If the names match however, we don't add the new weapon we were trying to add.
System.out.println("There already is a superweapon with the name "+superWeaponName+
" registered for the superhero "+superHeroName);
}
}
}
}
public void printHeroInfo(){
System.out.println(superHeroName);
System.out.println(superHeroInfo);
int size=superWeaponList.size();
for(int i=0;i<size;i++){
superWeapon temp_obj=superWeaponList.get(i);
System.out.println(superHeroName+" has the superweapon "+temp_obj.getName()+" with "+temp_obj.getCharges()+" charges.");
}
}
}
Although it can be improved a lot with using Set instead of list, but I will just point out the error in assumption you are making in comparing Strings...
if(temp_name!=superWeaponName) //incorret
if(!temp_name.equals(superWeaponName)) //correct

for loop jumps to last number in java android development

Hi I am making an android App, I want to add some values to a database and I want to do N times so I used a for loop as seen below:
private void addCodeToDataBase() {
for (int i = 1; i <= 100; i++) {
//indexnumber is a TextView
indexNumber.setText("Please enter the TAN code for Index number " + i);
//tanCode is an EditText
if (tanCode.getText().toString() != null) {
//index here is just an int so i can use the i inside the onClick
index = i;
//add is a button
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String codeText = tanCode.getText().toString();
dbHandler.addcode(index, codeText);
}
});
} else {
Toast.makeText(addcode.this, "Please enter your code !!!", Toast.LENGTH_LONG).show();
}
}
}
but what I am facing here is the for loop jumps to 100 at the first run, What I mean is the text will show :
Please enter the TAN code for Index number 100
it skips 99 numbers!! how would I fix it ?
It's Because your for loop executes so fast that you can't notice that the change of the text.First i is 0,and then it becomes 1,then the text will be "Please enter the TAN code for Index number 1" ......
your loop is working correctly but it is replacing text on each iteration that's why you think that it is jumping on last value please use break point and debug you will see each value on each iteration or use log in which you will see each value
It's not easy to imagine what your code does without seeing your declarations of indexNumber, tanCode, index, and, in particular, add. So, e.g., we don't know how often your if condition yields true.
However, most probably, the problem is that your assignment add.setOnClickListener(...) is just iterated with no user interaction in between. Now if you repeatedly assign something to your add (whatever that is), the last assignment will win.
If you want 100 buttons, you'll need to have an array or List of buttons to press, where each has a different tan code. If you want one button that repeatedly asks for the different tans, then you have to assign the data for click i + 1 only after click i has been handled, i.e. in the on click listener.
To give more specific help, we would need to know how your user interface should look (how many widgets of what kind) and how each widget should behave.

Beginner Java Scope Issue [duplicate]

This question already has an answer here:
Beginner Java: Variable Scope Issue
(1 answer)
Closed 7 years ago.
I'm new to programming and seem to be running into issues with when a variable, class, etc can and can't be referenced. Below is an example, hoping one of you can fix the specific issue but also help me understand it more broadly so I don't run into it again and again.
to try and avoid posting a bunch of code please note that a Question class is defined as well as a setText, setAnswer, checkAnswer, and display method are all defined elsewhere (all public).
The relevant code is below and I have two questions:
Why is the variable first not recognized in the method presentQuestion()?
At the very end there, why can't I just call the method checkAnswer() on first, i.e. why can't I just do first.checkAnswer(response);? Why do I have to define it in a new variable: boolean outcome = first.checkAnswer(response);?
Code:
/**
* This program shows a simple quiz with two questions.
*/
public class QuestionDemo {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Question first = new Question();
first.setText("Who was the inventor of Java?");
first.setAnswer("James Gosling");
Question second = new Question();
second.setText("Who was the founder of Udacity?");
second.setAnswer("Sebastian Thrun");
int score = 0;
score = score + presentQuestion(first, in);
// Present the second question
score = score + presentQuestion(second, in);
System.out.println("Your score: " + score);
}
/**
* Presents a question to the user and obtains a response.
* #param q the question to present
* #param in the scanner from which to read the user input
* #return the score (1 if correct, 0 if incorrect);
*/
public static int presentQuestion(Question q, Scanner in) {
// Display the first question
first.display();
System.out.println("Your answer:");
String response = in.nextLine();
// Check whether the response was correct
// If so, print "true" and return 1
// Otherwise, print "false" and return 0
boolean outcome = first.checkAnswer(response);
System.out.println(outcome);
if (outcome) {
return 1;
}
else {
return 0;
}
}
}
The reason you can't use the variable first inside presentQuestion is because it's defined in main, and therefore not visible outside of main. Isn't this precisely why you gave presentQuestion its Question q parameter, however?
It seems to me that this is what you want to do:
public static int presentQuestion(Question q, Scanner in)
{
// Display the first question
q.display();
System.out.println("Your answer:");
String response = in.nextLine();
// Check whether the response was correct
// If so, print "true" and return 1
// Otherwise, print "false" and return 0
boolean outcome = q.checkAnswer(response);
System.out.println(outcome);
if (outcome) {
return 1;
} else {
return 0;
}
}
Note that references to first have been replaced by references to q.
To try and clear up what I imagine your confusion may consist in, imagine if presentQuestion were called from another method than main, in which case no first variable would be declared at all. What would then happen to the references to first inside of presentQuestion, now not referring to anything at all? This is why you need to explicitly pass the data you want as parameters. Different methods are independent blocks of code, and you can't intermingle variable references between them even if they happen to call each other.
As for question 2, there should indeed be no problem with checking if(q.checkAnswer(response)) directly, without using the outcome variable. I'm guessing you were simply confused by the error emitted by the compiler when first wasn't recognized again.
first is a local variable, that means it can only be accessed inside the method in which it is defined.
You don't have to put the result of checkAnswer() into a boolean before using it. Actually, if (checkAnswer(response)) { ... } is valid.
presentQuestion takes a question as a parameter. In main, you're calling it on the first question, and then on the second question; it looks like the intent is that you use presentQuestion on the first question, and then on the second question. So far, so good.
The problem is that in presentQuestion, you're referring to the question (which could be the first or the second question) as q in the parameter list. All you need to do is use q instead of first in the rest of the method.
When I was new to programming, I had this problem as well! Then I found out it is very simple.
For your first question, first is declared in the main method and you want to use it in presentQuestion method. But presentQuestion and main are different methods! So you can't get to first in presentQuestion. As you can see, there is a Question-typed parameter in the presentQuestion method. This is like you telling first, "Come here, man! And then change your name to q." When you do pass the argument first to presentQuestion,
presentQuestion (first, in);
first comes to the pressentQuestion method with its name being as q. So you should use q instead of first in the presentQuestion method.
Now the second question, using a variable in this context is not needed. But to increase efficiency, use a boolean variable to store the result of checkAnswer. Let's imagine what happens if you don't use a boolean variable.
System.out.println(q.checkAnswer(response));
if (q.checkAnswer(response)) {
return 1;
} else {
return 0;
}
See? you called q.checkAnswer twice! This would slow down your program so you should use a boolean variable.

Messed up checks?

Just a brief description of what I am doing - I have random equation generator and buttons with all the digits. In order to answer the question the user has to click the corresponding buttons to form the question(digits are written from left to right) e.g. 9 + 6 = user clicks 1 and 5. If the answer is correct another equation should come up. The issue I am encountering for now is that SOMETIMES when the answer is a single digit there is no new equation showing up, nor any errors or something. Just nothing happens. Most of the time this occurs is when the answer is "0". Any idea what might be causing this ? Here is part of the code :
public void checkAnswer(){
int answer = question.getAnswer();
if(ansID2==-1){
if(String.valueOf(answer).equals(String.valueOf(ansID1))){
makeEquation();
}
}else{
if(String.valueOf(answer).equals(String.valueOf(ansID1) + String.valueOf(ansID2))){
makeEquation();
}
}
}
ansID2 is set to be -1 so if the answer is only a single digit the second digit place is skipped. ansID's are assigned when the button with the digit is clicked.
checkAnswer is called from a button "Check Answer" with the following code
EventHandler checkHandler = new EventHandler(){
#Override
public void handle(Event arg0) {
checkAnswer();
}
};
ansID2 is set to -1 in the field declaration
I would do this numerically:
public void checkAnswer(){
int answer = question.getAnswer();
int response = ansID1;
if(ansID2 >= 0) {
response = 10 * response + ansID2;
} // else a one-digit response
if (answer == response) {
makeEquation();
}
}
At minimum, that's more efficient than performing all the string manipulation you do in the original code. With that said, I don't see why this version would produce different results from yours. I'm inclined to suppose that your real problem is elsewhere, such as either the answer or the response digits being incorrect.
In particular, you say
ansID2 is set to -1 in the field declaration
but that's sufficient only until the first question with a two-digit answer, which will cause ansID2 to be set to something else. It (and also ans1ID) should be reset when a new equation is created.

What wrong with my Push function ? Stacking

Doing this for my project, using jFrame.
My problem is, when I input first:1 , Second: 2 , third: 3
and I clicked view stack, and the problem shows [ 1 , 2 , 3 , 0 , 0 , 0 . . . ]
I think the view should be [ 3 , 2 , 1 , 0 , 0 . . . .]
what what I understood about push.
code used :
// Global Variable
int[] myStack = new int [10];
int top = -1;
// Push Button
if ( top == 9){
JOptionPane.showMessageDialog(null, "Stack Full!");
}else{
int val = Integer.parseInt(pushtxt.getText());
top++;
myStack[top] = val;
pushtxt.setText("");
}
}
// View Stack Button
if (top == -1){
JOptionPane.showMessageDialog(null, "Stack Empty!");
}else{
viewtxt.setText("");
for (int x=0; x<=9; x++){
viewtxt.setText(viewtxt.getText()+" "+ myStack[x]);
}
}
I think you're misunderstanding the way a stack works. More specifically, the algorithm you use to display the stack is incorrect. In your case, you start at the bottom of the stack (where x=0) and work your way towards the top (actually, beyond the top, where x=9). This is why your output seems reversed to you (it's also full of zeros that you shouldn't be printing).
When displaying the stack, you should start at the top (x=2) and work your way towards the bottom (x=0). If you do things this way, then the output will be correct.
Stacks are FiLo, First in, last out. Generally stacks are used in a manner where you push items (the first being the bottom of the stack) and they keep on stacking. When you need to get values off of the stack you pop, going back in reverse order.
So the order you entered for data would store as:
1,2,3
bottom -> top
Your data is correct, it is as it should be.
So next you'll want to write a pop function, where you grab the value at the top of the stack and then decrement the top variable.
Popping your stack one at a time would return in the following order:
3
2
1
From what you were describing, I think perhaps you were going to pop from the front of the stack? If that is what you want to do, you would have to shift all of your values every-time you pushed a new value. What you currently have now is better code than shifting all your values on every push =]
You are on the right track.
EDIT I have not used swing in a while, but hopefully this will lead you in the right direction (I looked at some old code to make sure my syntax was correct, have not tested though). To answer the question you asked in my comment, your code would look something similar to the following for the pop function and setting the text for the popTextField
your pop function should look something like the following:
/**
* The code for the button press could be as simple as follows
*/
popBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
try{
popTextField.setText(popStack);
}catch(IndexOutOfBoundsException e){
popTextField.setText("The stack is empty");
}
}
});
the pop function can be really simple. You do not need to use exceptions - but it is good practice.
/**
* Simple Pop function
*/
private int popStack(){
if(top >= 0){
return myStack[top--];
}else{
throw new IndexOutOfBoundsException("The stack is empty");
}
}

Categories

Resources