I am a noob in Java and programing and I am making an app where the user is trying to guess a city based on a picture. The user sees a picture of the city and has three buttons under the picture with different answers in them. The pictures are randomized from an array and the buttons text changes so that atleast one of the buttons has the correct answer. I want a TextView with "correct" to show if user is correct and one with "incorrect" to show if user is wrong. The text is showing up when pressing any button and not when the button with the correct text is pressed. So this is what I have tried and am stuck on. And yes I know I have many mistakes in my code, such as names of methods and so. I will change these later.
I have three booleans that are set to false, they are representing which button is pressed. You will understand more later.
Boolean test1 = false;
Boolean test2 = false;
Boolean test3 = false;
In main i have three buttons and they all call on the checkanswer function. Also they all turn their own boolean to true there, which u will se why soon. Example of one of the buttons.
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
test1 = true;
checkanswer();
}
});
So here is the checkanswer function
public void checkanswer() {
DisplayRandomImage();
//Giving three strings random city names from the "cities" array.
Random rndBtnTxt = new Random();
String randomCity1 = cities[rndBtnTxt.nextInt(cities.length)];
String randomCity2 = cities[rndBtnTxt.nextInt(cities.length)];
String randomCity3 = cities[rndBtnTxt.nextInt(cities.length)];
//Setting the random city names to the three different buttons.
btn1.setText(randomCity1);
btn2.setText(randomCity2);
btn3.setText(randomCity3);
//takes the picked image from the "DisplayRandomImage" method.
String str = String.valueOf(pickedImg);
//Tells what to call the different pictures, they are known as numbers make sure they are given names instead.
if (pickedImg == 0)
str = "venice";
if (pickedImg == 1)
str = "new york";
//If-statement checking so that atleast one button has the correct answer.
if (randomCity1 != str || randomCity2 != str || randomCity3 != str) {
Random rndbtn = new Random();
Button x = btnArray.get(rndbtn.nextInt(btnArray.size()));
//Sets one of the three buttons so that it has the correct answer.
x.setText(str);
}
//See where the correct answer is
String buttonText1 = btn1.getText().toString();
String buttonText2 = btn2.getText().toString();
String buttonText3 = btn3.getText().toString();
//check if the button that the user pressed has the correct answer
if (test1.equals(true) && buttonText1.equals(str)){
CorrectAnswer();
test1 = false;
}
if (test2.equals(true) && buttonText2.equals(str)){
CorrectAnswer();
test2 = false;
}
if (test3.equals(true) && buttonText3.equals(str)){
CorrectAnswer();
test3 = false;
}
else
WrongAnswer();
}
I am not sure what I am doing wrong here. For example the "test1" is set to True when I press "btn1" and if "buttontext1" equals to the same as "str" does it should work. But for some reason it seems randomised which of the three buttons calls for the CorrectAnswer method. What am I doing wrong here?
Can we see CorrectAnswer? Also,
right off the bat, I noticed that instead of using test1, test2 and test3 to indicate which button was pressed, you can just pass some sort of argument into checkAnswer, like int button.
So onClick would look like this for the first button, and subsequent buttons by incrementing the 1:
public void onClick(View v) {
checkanswer(1);
}
and checkanswer would look like this:
public void checkanswer(int button) {
... (previous stuff) ...
//check if the button that the user pressed has the correct answer
if (button == 1 && buttonText1.equals(str)){
CorrectAnswer();
}
if (button == 2 && buttonText2.equals(str)){
CorrectAnswer();
}
if (button == 3 && buttonText3.equals(str)){
CorrectAnswer();
}
else
WrongAnswer();
}
So try this out.
Its pretty hard to tell where the bug is, if you only show us pieces of the full code.
Mistakes could be e.g. in CorrectAnswer()...
I would recommend binding onlick-listeners to your buttons instead of changing booleans.
Check this out here: https://developer.android.com/reference/android/widget/Button
Additionally I noticed another mistake:
randomCity1 != str || randomCity2 != str || randomCity3 != str
This will return true if at least one of the Strings does not contain the right answer
You probably want to enter the if-Statement, when there isnt already a button with the correct answer.This is what you would like to use:
randomCity1 != str && randomCity2 != str && randomCity3 != str
EDIT: Check out the answer of Barcode for another example of using onClicklisteners.
Thank you both for answering the question, i have found a way to complete this problem:
public void testingMethod(int button){
switch(button){
case 1:
if (buttonText1 == str)
CorrectAnswer();
else
WrongAnswer();
break;
case 2:
if (buttonText2 == str)
CorrectAnswer();
else
WrongAnswer();
break;
case 3:
if (buttonText3 == str)
CorrectAnswer();
else
WrongAnswer();
break;
}
}
And since you were wondering how the method CorrectAnswer looked like here it is, yes I know it's probably unnecessary having this method but I am noob after all.
public void CorrectAnswer() {
findViewById(R.id.txtIncorrect).setVisibility(View.GONE);
findViewById(R.id.txtCorrect).setVisibility(View.VISIBLE);
}
Related
I recently run in to same problem as this guy 4 years before. He get some answers there but non of it work either for him or me and then the question was not updated anymore.
How to get string from JTextField and save it in variable?
The point is to check what is typed in textfield and if, like in example is yet decimal dot in the TextField, then consume event and not allow to add second decimal dot.
Main problem I figured out is that I need to add this inside the key event as shown belox. But this. statement inside the event reffers to event itself and not on JTextField.So I need to find bypass or other solution how to write getText statement
String text = this.getText().toString();
if someone have ideas of how to improve code as well I'm opened to any suggestions except for rewriting it as formatted field because the user experience is a little different, from the point where I was trying formatted field.
public class TxtfNumber extends JTextField {
String text = this.getText().toString();
public TxtfNumber(){
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
#Override
public boolean dispatchKeyEvent(KeyEvent evt) {
switch (evt.getID()) {
case KeyEvent.KEY_TYPED:
String text = this.getText().toString();
if(evt.getKeyChar()=='.'&& text.contains(".")){
evt.consume();
}
}
return false;
}
});
}
}
SOLUTION
I accidentally run in solution when I used lambda expression. The formula you need to use is the name of class then .this.
So in this case,
String text = TxtfNumber.this.getText().toString();
is the solution.
But eventually, when I know how to implement JTextField, I no longer need a solution by string. So I'm giving the whole code here for later use. Feel free to use it as Choose Bean component.
It restricts the user to use only one minus sign at the start of the text, one decimal dot anywhere and then type in two decimal numbers.
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import javax.swing.JTextField;
public class TxtfNumber extends JTextField {
public TxtfNumber(){
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
#Override
public boolean dispatchKeyEvent(KeyEvent evt) {
switch (evt.getID()) {
case KeyEvent.KEY_TYPED:
//restricts input charactes
if(!Character.isDigit(evt.getKeyChar()) && (evt.getKeyChar()!='.') && (evt.getKeyChar()!='-') && (evt.getKeyChar()!=','))
evt.consume();
//change , and . for securing of different keyboard language
if (evt.getKeyChar()==',')
evt.setKeyChar('.');
//allow only one decimal dot in text
if (evt.getKeyChar()=='.' && TxtfNumber.this.getText().contains("."))
evt.consume();
//allow minus sign only at the start of text
if (evt.getKeyChar()=='-' && TxtfNumber.this.getText().length() != 0)
evt.consume();
//allow two decimal numbers after dot
for (int i = -1; (i = TxtfNumber.this.getText().indexOf(".", i + 1)) != -1; i++) {
if (i+3 == TxtfNumber.this.getText().length())
evt.consume();
}
break;
}
return false;
}
});
}
};
I'm trying to take the target (initiated as ImageView) id and put the integer id into a switch case to look at the adjacent Views and compare their drawables to determine if that player wins or if the game continues. I have the buttonPressed variable initiated as an Integer and used the parseInt() to get the int value of target.
public void compareButton(int buttonPressed){
//int count = 0;
ImageView adjacent;
ImageView adjacentB;
switch (buttonPressed){
case R.id.imageButtonA: //this is where adjacent buttons are identified and compared
adjacent = findViewById(R.id.imageButtonB);
adjacentB = findViewById(R.id.imageButtonC);
if (target.getDrawable() == adjacent.getDrawable() && target.getDrawable() == adjacentB.getDrawable()) {
Toast.makeText(MainActivity.this, "You Win!", Toast.LENGTH_SHORT).show(); //Win condition
// } else if (target.getDrawable() == R.id.imageButtonE.getDrawable() & target.getDrawable() == R.id.imageButtonI.getDrawable()) {
//Toast.makeText(MainActivity.this, "You Win!", Toast.LENGTH_SHORT).show(); //Win condition
// } else if (target.getDrawable() == R.id.imageButtonD.getDrawable() & target.getDrawable() == R.id.imageButtonG.getDrawable()) {
//Toast.makeText(MainActivity.this, "You Win!", Toast.LENGTH_SHORT).show(); //Win condition
}
break;
case R.id.imageButtonB:
break;
I am not filling every case for debugging purposes.
The issue I am having is when I run the emulator I get an error that says
Caused by: java.lang.NumberFormatException: For input string: "androidx.appcompat.widget.AppCompatImageButton{517eade VFED..C.. ...P..ID 45,381-304,628 #7f070072 app:id/imageButtonA}"
at java.lang.Integer.parseInt(Integer.java:521)
at java.lang.Integer.parseInt(Integer.java:556)
at com.example.connect3.MainActivity.switchColor(MainActivity.java:75)
Here is the code for the OnClickListener:
public void switchColor(View view) {
//Button pressed, depending on user, switch's to that users color; identify adjacent button ID's; toast player control switch
if (player == 1) {
source = findViewById(R.id.yellow);
target = findViewById(view.getId());
target.setImageDrawable(source.getDrawable());
buttonPressed = Integer.parseInt(target.toString());
compareButton(buttonPressed);
player++;
Toast.makeText(MainActivity.this, "Player 2's Turn!", Toast.LENGTH_SHORT).show();
} else {
source = findViewById(R.id.red);
target = findViewById(view.getId());
target.setImageDrawable(source.getDrawable());
buttonPressed = Integer.parseInt(String.valueOf(target));
compareButton(buttonPressed);
player--;
Toast.makeText(MainActivity.this, "Player 1's Turn!", Toast.LENGTH_SHORT).show();
}
Not entirely sure what is going on at this point because I thought I did everything correct but clearly something was missed. Any help would be appreciated.
change :
buttonPressed = Integer.parseInt(String.valueOf(target));
To :
buttonPressed = target.getId();
Explanation : your error says NumberFormatException means you are trying to get int value from String which is not possible to Parse or in simple your string doesn't contain proper int value and also you are passing (androidx.appcompat.widget...) as string while you have to pass button I'd
I am new to Java and am having trouble on getting some code working. I have a GUI with the letters A-Z. After a button click, I want to ask for a Keyevent to do a couple of things:
Only allow you to select a letter. Upper or lower case. If not wait for a response that is correct.
Then check the alphabet list to see if it has been pressed before. If it has then ask for another letter
If a new character is entered then strike it out on the alphabet and run the method that follows
Disable any further keys being pressed.
I have tried the following code:
private static void spinGame(){
switch (wheelResult)
{
case "1'
...
break;
case "2":
...
break;
default:
System.out.println("...");
newPhrase.gameB();
scene2.setOnKeyPressed((KeyEvent event) -> {
if (event.getText().isEmpty())
return;
char pressed = event.getText().toUpperCase().charAt(0);
userGuess=event.getText().charAt(0);
if ((pressed < 'A' || pressed > 'Z'))
return;
Text t = alphabet.get(pressed);
if (t.isStrikethrough())
return;
// mark the letter 'used'
else{t.setFill(Color.BLUE);
t.setStrikethrough(true);
System.out.println(userGuess);
}
int letterCount;
if ((userGuess == 'a') || (userGuess == 'e') || (userGuess == 'i') || (userGuess == 'o') || (userGuess == 'u')){
playerScores[currentPlayer] -= 250;
System.out.println("£250 docked from score for vowel use");
}
It goes wrong from here. I dont want keys to be pressed again and I don't the following method should run:
letterCount = newPhrase.makeGuess(userGuess);
...my method....;
})
I have no idea how to fix it. I tested and recorded the User guess is being selected but it does not proceed the method after and the key in input doesn't stop. I also feel that my coding for the alphanumeric stuff is wrong.
Your solution already caters for your requirements as you check for a valid letter and whether or not it is strike-through in your alphabet. So until they provide an unused letter, nothing will happen aside from the conditions being checked each time
To stop the key input I'd recommend using a ToggleButton or something similar so the user has to indicate when they want to guess. This means you can use other text based controls with a decreased probability of striking off letters in your alphabet accidentally. When they guess an unused letter you can reset the button, otherwise keep checking their input for a valid letter
Your method relating to the scoring system is only called when a vowel has been entered by the user. You can separate the score and input logic by creating a method and only providing valid unused letters to it, handling the game's scoring/phrase lookup logic there:
private void checkPhrase(char chosenLetter){
//Handle the Hangman-like logic here
boolean isVowel = vowels.indexOf(chosenLetter) >= 0;
if (isVowel) {
System.out.println("User provided a vowel");
}
}
This will make it easier to read and maintain your code as once you've determined that the letter hasn't been used you will only need to call it once. Whereas before you might have had duplication as it looks like it was only been executed for vowels
Below are the changes I made to your code when testing in case they are of use:
public class AlphabetGuess extends Application {
private String vowels = "AEIOU";
#Override
public void start(Stage primaryStage) throws Exception {
ObservableList<Text> alphabet = FXCollections.observableArrayList();
for(char letter = 'A'; letter <= 'Z'; letter++){
alphabet.add(new Text(String.valueOf(letter)));
}
HBox alphabetContainer = new HBox(5);
alphabetContainer.setAlignment(Pos.CENTER);
alphabetContainer.getChildren().addAll(alphabet);
ToggleButton button = new ToggleButton("Listen for guess");
button.setSelected(false);
VBox root = new VBox(20, alphabetContainer, button);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 500, 100);
scene.setOnKeyPressed(event -> {
//If the button isn't selected, don't process the input
if (event.getText().isEmpty() || !button.isSelected()) {
return;
}
char userGuess = event.getText().toUpperCase().charAt(0);
if ((userGuess < 'A' || userGuess > 'Z')) {
return;
}
//This will cause letters A-Z to become 0-25 allowing the list to be indexed
Text text = alphabet.get(userGuess - 'A');
if (text.isStrikethrough()) {
System.out.println(userGuess + " has already been guessed");
return;
} else {
text.setFill(Color.BLUE);
text.setStrikethrough(true);
checkPhrase(userGuess);
}
//Un-select button which will cause this event to reject incoming keys
button.setSelected(false);
});
primaryStage.setScene(scene);
primaryStage.show();
}
private void checkPhrase(char chosenLetter){
//Handle the Hangman-like logic here
boolean isVowel = vowels.indexOf(chosenLetter) >= 0;
if (isVowel) {
System.out.println("User provided a vowel");
}
//ToDo: Implement
}
}
public void processLightClick(int row, int col) {
states[row][col] = !states[row][col];
if(states[row][col] = true){
lights[row][col].setFill(ON_PAINT);
}
else if(states[row][col] = false){
lights[row][col].setFill(OFF_PAINT);
}
turns++;
System.out.println(row+":"+col);
status.setText("Turn Number " + turns);
}
This is the code I have. I'm trying to get it to toggle states and colors each time a specific square is pressed but the paint stays the same and doesn't toggle the state back and forth when I press the same square twice
You are using an assignment operator "=" instead of a comparison operator "==" in your if-statement. Try this.
public void processLightClick(int row, int col) {
states[row][col] = !states[row][col];
if(states[row][col] == true){
lights[row][col].setFill(ON_PAINT);
}
else if(states[row][col] == false){
lights[row][col].setFill(OFF_PAINT);
}
turns++;
System.out.println(row+":"+col);
status.setText("Turn Number " + turns);
}
As user2615117 pointed out, you are not using the comparison operator, but the assignment operator. Here, however, I also would use the ternary operator to make the code more concise:
lights[row][col].setFill((states[row][col] == true) ? ON_PAINT : OFF_PAINT);
Another possible improvement would be to have a single array of Light objects which contain both the state and the paint of the light.
I am making a basic calculator for Android in Java. I am stuck in one final step where it must add the input with the previous input. Have a look at the code:
public void displayValue(){
String mything = display.getText().toString();
input = Integer.parseInt(mything);
}
public void number1(View view){
if (input == 0){display.setText("");}
display.append(Integer.toString(1));
displayValue();
}
public void number2(View view){
if (input == 0){display.setText("");}
display.append(Integer.toString(2));
displayValue();
}
public void plus(View view){
displayValue(); //result= 0
result = result + input; //result= input
input = 0; //input=0
//in this step input becomes 0 to let the user enter new number input but this
//input never add the old result and the equal shows the old result.
}
public void equal(View view){
displayValue();
display.setText(Integer.toString(result));
}
I noticed that if I add a line in equal method and add the result to input I get the correct answer but that's not gonna be helpful as there will be minus button too.
Any ideas?
Thanks.
It's definitely hard to tell because you don't include full code, which would be helpful, but could it be because you call displayValue(); in some places before doing the math? Specifically in the plus method.
Ok finally I came up with a solution.
As the only option for calculation of result and new input is in equal method (because logically when user press the equal button, so wants to ends the equation), so I added two boolean values for each minus and plus calculation. Then I added both calculation for adding or minus 2 values.
Then when the user inter first part of the calculation and then hit plus sign, the boolean value of plus becomes true and after entering new input and hitting the equal sign, it does the true part of the calculation. Well it is a bit hard to explain but i guess by looking at the code you would get what I mean.
boolean whenMinus = false;
boolean whenPlus = false;
public void plus(View view){
displayValue();
result = input;
input = 0;
whenPlus = true;
}
public void minus(View view){
displayValue();
result = input;
input = 0;
whenMinus = true;
}
public void equal(View view){
if (whenPlus == true){result = result + input; whenPlus = false;}
if (whenMinus == true){result = result - input; whenMinus = false;}
display.setText(Integer.toString(result));
}
I am not sure if it is the correct way of making this calculator. But I fixed my problem anyway. It would be great to comment me and let me know if it is the standard way or its kinda hacking. I am not a pro anyway.