What i'm trying to do is quite simple. I want to generate random numbers(rand1 & rand2) and have the user give the correct answer of the sum. There are 2 buttons and the correct answer could be on either one. I am using the randDecider variable to determine whether or not the correct answer should show up on the first or second button. The randDecider is either a 1 or 2.
The issue I am having is sometimes when I click on the correct answer, The score doesn't increment. And it turns out that sometimes when I press the wrong answer, the score increments. So i'm assuming it's a 50/50 chance the score will increment regardless if the answer is correct or not.
protected void setRandom(View v) {
//Assigning random values to ints
rand1 = r.nextInt(5) + 1;
rand2 = r.nextInt(5) + 1;
randDecider = r.nextInt(2)+1 ;
//The sum of the randoms
sum = rand1 + rand2;
//Setting the texts of the random values
randTV1.setText(rand1 + "");
randTV2.setText(rand2 + "");
/*If the random deciding number is 1, set the correct answer
on the choice1 button*/
if (randDecider == 1){
choice1.setText(sum+"");
choice2.setText(sum+1+"");
//If the correct answer was chosen, increment the score and set the text
if(v.getId()==R.id.choice1){
score++;
scoreTV.setText(score+"");
}
}
/*If the random deciding number is 2, set the correct answer
to the choice2 button*/
if (randDecider == 2){
choice1.setText(sum+1+"");
choice2.setText(sum+"");
//If the correct answer was chosen, increment the score and set the text
if(v.getId()==R.id.choice2){
score++;
scoreTV.setText(score+"");
}
}
I'd suggest splitting the two distinct functions a) creating and presenting the problem to be solved and b) checking the response and then c) introducing a class variable to store the answer until another problem is presented (which would be after responding b) ).
So you could
a) add a line in the class
int correctanswer;
b) Add a method for setting the problem e.g. setProblem (called initially and then within c))
c) Add a method for checking the response e.g. setResponse which calls the setProblem method when the score has been adjusted. The setResponse method being called when either button is clicked.
d) add a call to initially invoke the setProblem.
e) set the 2 onclick listeners to call the setResponse method.
The following could be a resolution (based upon your question) :-
public class MainActivity extends AppCompatActivity {
int score, correctanswer;
TextView scoreTV, randTV1, randTV2;
Button choice1, choice2;
Random r = new Random(System.currentTimeMillis());
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get UI components
scoreTV = (TextView) this.findViewById(R.id.score);
randTV1 = (TextView) this.findViewById(R.id.rand1);
randTV2 = (TextView) this.findViewById(R.id.rand2);
choice1 = (Button) this.findViewById(R.id.choice1);
choice2 = (Button) this.findViewById(R.id.choice2);
// Initialise
score = 0;
scoreTV.setText(Integer.toString(score));
setProblem();
// Button Listeners
choice1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkResponse((Button)v);
}
});
choice2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkResponse((Button) v);
}
});
}
// Set the problem
public void setProblem() {
//Assigning random values to ints
int rand1 = r.nextInt(5) + 1;
int rand2 = r.nextInt(5) + 1;
int randDecider = r.nextInt(2)+1 ;
//The sum of the randoms
int sum = rand1 + rand2;
correctanswer = sum;
//Setting the texts of the random values
randTV1.setText(rand1 + "");
randTV2.setText(rand2 + "");
/*If the random deciding number is 1, set the correct answer
on the choice1 button*/
if (randDecider == 1){
choice1.setText(sum+"");
choice2.setText(sum+1+"");
} else {
choice2.setText(sum+"");
choice1.setText(sum+1+"");
}
}
// Check the user's response (called by onClick listeners)
public void checkResponse(Button v) {
if ((new Integer(v.getText().toString()) == correctanswer)) {
score++;
scoreTV.setText(score+"");
}
setProblem();
}
}
At the top of your method, you have several lines which generate the random numbers and the decider. These are correct.
Then, you show the random numbers and place the answers on the correct buttons, which is presumably also correct.
However, at the same time, you check whether the correct button is selected. This means you're checking against the last button the user pressed, not their answer.
One way to fix this is to save the sum and correct answer positions for at least one rotation. Change your setRandom method to generate the numbers and set them to the screen as they are now, but also to save the correct answer to an outside variable.
Then, in the button's onPressed method, check whether the pressed button is correct, increment the score, and call setRandom to put a new question on the screen.
The problem in your code stems from the fact that you check the answer right as you put the question on screen. Happy programming!
Related
So we are working on a quiz game/app and we have a problem with just one thing.
We got 4 buttons for the possible answers and only one of them is the correct one (obviusly). They are regular buttons with text on them, not the radio ones. The thing is that in order to avoid creating an activity for each question we wanna keep the buttons in one activity, and when pressed on the "correct answer" to change the buttons functions to be different. For example buttons 1,2,3 all send the player to gave over screen, while button 4 is the correct one. Then it should change the text that is displayed on the buttons and change all the buttons' functions so that 1,3,4 are now the "game over buttons" and 2 is the correct one. We tried if statements and integers, and booleans, to no avail. Any hints or solutions that could help us?
Thanks
Given your current setup I'd have each button's onClick call a method like validateCorrectAnswer(int buttonNumber) and then from there you'd do your validations. So for button1 you'd call validateCorrectAnswer(1).
From validateCorrectAnswer(...) you'd have an array of correct answers, so it could be something like int[] correctAnswers = {4, 2, 3, 4, 1, 3, 2, 1, ...}; and depending on which question they are on you'd check. So let's say you are on question 3 you'd check correctAnswers[2] == buttonNumber.
So to simplify that further within your activity store what question they are currently on in a global variable, something like private int currentQuestion = 0 and then after each question you increment that number.
So the final method would be something like:
void validateCorrectAnswer(int buttonNumber) {
if (correctAnswer[currentQuestion] == buttonNumber) {
currentQuestion++;
// correct answer, cool move on
} else {
// wrong answer, game over
}
}
In your question class, you can set the answer to a text / button id and check on a button click if the button text / id is the same as your answer.
Also, see this example from butterknife:
//Specify multiple IDs in a single binding for common event handling.
#OnClick({ R.id.door1, R.id.door2, R.id.door3 })
public void pickDoor(DoorView door) {
if (door.hasPrizeBehind()) {
Toast.makeText(this, "You win!", LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Try again", LENGTH_SHORT).show();
}
}
source: Butterknife docs
You could use the setTag(tagValue) and getTag(tagValue) methods for the 4 buttons.
1 - correct
0 - wrong
And then just switch the tagValues according to the answer given.
#Override
public void onClick(View view) {
int answer = 0;
if(view instanceof Button) {
answer = (int) ((Button)view).getTag();
}
if(answer == 1) {
//true answer
refreshButtons();
} else {
//game over
}
Log.d("TAG", "a: "+answer);
}
public void refreshButtons () {
questionNr ++;
Log.d("TAG", "q: "+questionNr);
setAnswers(questionNr);
}
public void setAnswers (int question) {
switch (question){
case 1: // Second question
v1.setTag(0);//wrong
v2.setTag(1);//correct
v3.setTag(0);//wrong
v4.setTag(0);//wrong
break;
case 2:// Third question
v1.setTag(0);//wrong
v2.setTag(0);//wrong
v3.setTag(1);//correct
v4.setTag(0);//wrong
break;
case 3:// Forth question
v1.setTag(0);//wrong
v2.setTag(0);//wrong
v3.setTag(0);//wrong
v4.setTag(1);//correct
break;
}
}
You could also setup the texts for the other views in the same setAnswer() Method
The onCreate() method could be something like this :
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//here you setup the answers for the first question
v1 = (Button) findViewById(R.id.button1);
v1.setOnClickListener(this);
v1.setTag(1);
v2 = (Button) findViewById(R.id.button2);
v2.setOnClickListener(this);
v2.setTag(0);
v3 = (Button) findViewById(R.id.button3);
v3.setOnClickListener(this);
v3.setTag(0);
v4 = (Button) findViewById(R.id.button4);
v4.setOnClickListener(this);
v4.setTag(0);
edit.
I'm trying to make a game where there is 4 buttons each button has a set value.
buttone is 1 buttontwo is 2 and so on.
and on each click of the button it takes the value from what ever button is pressed and add it to an array, the number of buttons that you have to press is set by the intent from the main activity and the buttons that have to be press is set by the randomNums array.
eg.
if the randomNums give you 1,2,1,1,2.3,3,4.
green button must be pressed 3 times
blue button must be pressed 2 times
yellow button must be pressed once.
buttonOne must be pressed 3 times.
buttonTwo must be pressed 2 times.
buttonThree must be pressed 2 times.
buttonFour must be pressed once times.
I have the randomNums which gives you the up to 12 number from 1-4.
I have the buttons set up so that if the randomNums gives you 1,1,1,2,3,3.
ButtonOne will be green buttonTwo will be yellow and buttonThree will be blue
for 3 seconds then all the buttons turn grey.
but where I'm having trouble is how do u set a button to have a set value.
eg.
if I press buttonOne 3 times it will enter into an array like so 1,1,1.
so the question is how do set a fixed value to a button so that every time it is press it send a fix value to an array.
sry if I was not clear the 1st times around if u have any more question or if you need me to explain it again or want to see the code that I have to set the color of the button play let me know . thanks
hi I'm very new to android studio,
I have 4 buttons and I want each to have a fixed value.
ButtonOne =1;
ButtonTwo =2;
ButtonThree =3;
ButtonFour =4;
and when a button is pressed I want to add that fixed button value to an array.
what I have is sending an ++ number back and not sending a fixed value.
so my question is how do you send a multiple fixed int from four buttons OnClickListener to an array?
public int counterOne = 0;
final Button buttons[] = {
(Button) findViewById(R.id.ButtonOne),
(Button) findViewById(R.id.ButtonTwo),
(Button) findViewById(R.id.ButtonThree),
(Button) findViewById(R.id.ButtonFour)
};
buttons[0].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
counterOne = counterOne+1;
CheckSET.setText(""+counterOne);
}
});
final int pressed[] =new int [12];
end.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String stringlevel = ""+CheckSET.getText();
String b = "";
final int intLevel = Integer.parseInt(stringlevel);
for (int i = 0; i < 12;i++){
//b = ""+ b +""+ pressed[i];
//pressed[i] = pressed[i]+1;
//if(intLevel==1){
// pressed[i] = pressed[i]+1;
//}else if (intLevel ==2){
// pressed[i] = pressed[i]+2;
//}
pressed[0] = counterOne;
b = ""+ b +""+ pressed[i];
diff.setText(b);
}
}
});
the end button is to add all the button clicks to the array.
but if there is a better way then doing an end button to run the button array that would be great. could you do a for() and have all the buttons inside the for and each time they are pressed it adds it to the array?
I have a random array set up all ready that picks 12 numbers from 1-4 and does not let any number repeat more then 3 times.
private int[] pickNums() {
Random rand = new Random();
int randomNums[] = new int[12];
int one = 0;
int two = 0;
int three = 0;
int four = 0;
for (int i = 0; i < 12; i++) {
randomNums[i] = rand.nextInt(4)+1;
if (randomNums[i] == 1) {
one = one + 1;
if (one>3){
i=i-1;
}
} else if (randomNums[i] == 2) {
two = two + 1;
if (two>3){
i=i-1;
}
} else if (randomNums[i] == 3) {
three = three + 1;
if (three>3){
i=i-1;
}
} else if (randomNums[i] == 4) {
four = four + 1;
if (four>3){
i=i-1;
}
}
}
return randomNums;
}
my plan is to do a bubble sort on the randomNums and on the buttonPress array to see if the buttons that are pressed all ==.
but I'm having a lot of trouble with the buttonpress array
I am not sure what you asking but may be this will help you
(Instead of Array you should use list)
private List<Integer> pressedNums = new ArrayList<>();
Button button1,button2,button3,button4;
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pressedNums.add(1)
}
});
similarly for button2,3,4 add 2,3,4
at last you can use loop
int total = 0;
for(Integer i : pressedNums){
total += i;
}
textField.setText(Integer.toString(total));
I have 3 images in my app. The images are numbers. The maximum number displayed on all the 3 images will be 9. At first the image in the unit's place will be 1 and the rest images will be 0. On Clicking on the "next" button, the next number is being displayed i.e. 2. Proceeding in this way till the last number 9,then on the next click the unit's place becomes 0 and the ten's place becomes 1 and so on will proceed till 999. There is a previous button too which will reverse the condition of next button and will decrement the numbers by one digit. I am able to achieve the next button condition by using if else conditions but unable to do the same for previous button. please help.
int image1 = 2;
int image10 = 0;
int image100 = 0;
int max = 10;
final int [] images = {
R.drawable.num00,R.drawable.num_0, R.drawable.num1, R.drawable.num2, R.drawable.num3, R.drawable.num4,
R.drawable.num5, R.drawable.num6, R.drawable.num7, R.drawable.num8, R.drawable.num9
};
ImageButton next = (ImageButton)findViewById(R.id.imageButton1);
next.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if((image1==max)&&(image10<max)) //for value with 9, 19... to increment
{
image1=1;
if (image10==0)
{
image10=2;
}
else
{
image10++;
}
img1.setImageResource(images[image1]);
img2.setImageResource(images[image10]);
}
else if((image1==max)&&(image10==max)&&(image100>=0)&&(image100<=10)) //for value with 9 in 1st block to increment
{
image1=1;
image10=1;
if (image100==0)
{
image100=2;
}
else
{
image100++;
}
img1.setImageResource(images[image1]);
img2.setImageResource(images[image10]);
img3.setImageResource(images[image100]);
}
else if (image100<=10) //for value below 9 in 1st block to increment
{
image1++;
img1.setImageResource(images[image1]);
}
}
});
Here, image1 is the position of image in the unit's place, image10 in the ten's place and image100 in the hundred's place.
The implementation can be optimized a lot.
Why cant you go for a simple number like below.
int number = 0;
for next button:
if(number <1000){
number++
updateImages()
}
for previous button:
if(number > 0){
number--
updateImages()
}
After doing the above line for those prev/next buttons, simply write a method like below.
updateImages(){
unitsPlace = number%10;
tensPlace = ((number/10)%10);
hundredsPlace = ((number/100)%10);
img1.setImageResource(images[hundredsPlace]);
img2.setImageResource(images[tensPlace]);
img3.setImageResource(images[unitsPlace]);
}
Thats it.
I am self studying Android and now I am learning how to use buttons. I created a simple up counter which works like this:
I add the strings (eg. 1 2 3) in different text fields. Then I want to compaire those in pairs(1 with 2, 1 with 3, 2 with 3). The first string element is written on the first button, second on the second and after i press any of those buttons, the tags on the buttons has to change (if there was 1 and 2 so it should change to 1 and 3 or 2 and 3 etc) and the string element gets a higher rank. Everything seems to work well, but I think I am doing huge mistake with adding buttons. Can anyone help me? :) Can I add button listeners like I did in code bellow? :) Thank You!
public void counter()
{
int i = 0;
int a = i + 1;
for ( i = 0; i < candidates.size() - 1; i++ )
{
Log.d(TAG, "Setting button one tag: " + i );
button_one.setTag(i);
button_one.setText(candidates.get(i).name);
for (a = i + 1; a < candidates.size(); a++)
{
Log.d(TAG, "Setting button two tag: " + a );
button_two.setTag(a);
button_two.setText(candidates.get(a).name);
button_one.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view) {
/* Read the clicked tag */
int tag = (Integer) view.getTag();
/* Make higher rank */
candidates.get(tag).addRank();
}
});
button_two.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view) {
/* Read the clicked tag */
int tag = (Integer) view.getTag();
/* Make higher rank */
candidates.get(tag).addRank();
}
});
}
}
everything AndyRes said plus:
you're creating (candidates.size() * candidates.size()) number of OnClickListeners
that's A LOT of unnecessary objects hogging your memory.
You should create ONE OnClickListener mListener = new View.OnClickListener etc... etc...
and OUTSIDE the loop, probably during your OnCreate() just after you defined button_one = (Button)findViewById(R.id.button_one); you do button_one.setOnClickListener(mListener);
that way you have only 1 listener that will be serving any amount of buttons you might have, and don't need to be setting again the same listener.
In general there's not need to add the click listeners in a loop, unless you create those buttons dinamically.
Setting the click listeners in a loop for the same button, every time you cycle through the loop, will do nothing but override the previous settings, so I don't see any point in doing like this.
I have just started learning Android and got some misunderstanding. I'm trying to create an application which displays a textView and a button. Every button click generates a new random number which should be displayed in the textView.
But unfortunately my code causes a list of errors. Here it is:
public class FirstAndroidProjectActivity extends Activity {
public OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView tv = (TextView) findViewById(R.id.display);
Random r = new Random();
int i = r.nextInt(101);
tv.setText(i);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(listener);
}
}
If I just don't use random and use some string except of i
(for example tv.setText("99");) everything is ok, but it doesn't work with a variable as a parameter of setText().
Where is a mistake?
Hope for your help.
You need to convert your random number to a string before setting the text on your TextView
Try
tv.setText(i +"");
Try:
tv.setText(String.valueOf(i));
Java doesn't auto convert types. The + operator is overloaded to transform the parameters passed to it into a String when one or more of those paramaters is a String. So, when you pass i + "" to setText() you are passing a String, however if you just pass i then the compiler sees you passing an int to a method that expects a String and lets you know that that can't be done.
i is an int, try tv.setText("" + i);
Convert your integer to a String before setting it to the textView. You should also move Random r = new Random(); outside of the method, or else your numbers may not really be random :
Random r = new Random();
#Override
public void onClick(View v) {
TextView tv = (TextView) findViewById(R.id.display);
int i = r.nextInt(101);
tv.setText(Integer.toString(i));
}
From the documentation :
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers
If you create two Random objects too quickly (for example the user clicks two times on the button very quickly), they will share the same seed (the system clock is used to generate it) and as a result you will get the same number two times.
By creating only one Random instance in a global variable, you avoid this issue.
use
tv.setText(new Integer(i).toString()) ;