Java Swing application, dialog checking for number in range - java

I'm working on a card game with 1-4 players. When I start a new game it will instantiate a class DialogCreator that asks you to enter the number of players you want. Here is the code for the DialogCreator:
private class DialogCreator {
/**
* Creates a dialog for the input of how many players you want in the game.
* Takes an integer between 1 and 4.
* #param msg
* #return
*/
int createIntDialog(String msg) {
String inValue = null;
String error_msg = "";
int v = 0;
while ((inValue = JOptionPane
.showInputDialog(msg + error_msg + ":")) != null) {
error_msg = "";
int inVal = Integer.parseInt(inValue);
try {
if(inVal >= 1 && inVal <= 4)
v = inVal;
break;
} catch (NumberFormatException nfe) {
error_msg = "(Entered values can only be integers between 1 and 4)";
}
}
return v;
}
}
I thought that this code would try to set v = inVal only if 1 <= inVal >= 4 and if inVal is < 1 or > 4 it would go to catch and give me the error message. This does not work and I get an IndexOutOfBoundsException if I enter a number that is not between 1 and 4. It works fine to check if I enter a String that can not be parsed to int. Can someone tell me what I'm doing wrong here?

The problem is here:
if(inVal >= 1 && inVal <= 4)
v = inVal;
break;
Without any braces, only the v = inVal; is under the if statement. Therefore, whatever inVal is, you are going to break out of the while loop and return 0 (v was initialized to 0). Then I guess that if this method returns 0, the rest of your code fails. If you add braces around then you can assure that you will break only if the input is valid:
if(inVal >= 1 && inVal <= 4) {
v = inVal;
break;
}
As a side-note, you should be consistent with your namings: error_msg doesn't respect Java naming conventions.

A simpler solution is to just use a JOptionPane with a combo box containing the values 1-4. Then there is no need for any edit checking.
Read the section from the tutorial on Getting User Input From a Dialog for an example showing how this is done.
Or if you want to insist that the user enter a number then the tutorial also contains a section on Stopping Automatic Dialog Closing, which is a little more complicated, but a better overall solution for using the JOptionPane.

Related

How to add a variable to another variable that's already set

My homework is to create a program that takes a list of numbers and prints out the highest number divisible by four.
List would look like this:
12
16
87
58
25
73
86
36
79
40
12
89
32
Input should be:
40 because it is the highest number there divisible by four.
Here is my code:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int saved = 0;
int saved2 = 0;
for (int i = scanner.nextInt(); i % 4 == 0; i = scanner.nextInt()) {
for (boolean bull = true; bull == true; bull ^= true) {
if (i > saved) {
saved -= saved2;
saved += i;
saved2 += i;
}
}
System.out.println(saved);
}
}
}
The input of my code is
12
16
I don't really understand why this is doing it, but it seems to me that I'm adding the variables wrong. The homework page on adding variables does not specify how to add variables to each other.
Does anyone have a tip to improve the code in anyway, or find a way to make a fix my code? Thank you.
welcome to Java.
First you are saying you got input, but that is output. Input is what you enter, and output is what you get printed.
Then there is a mistake in your for loops. You have too much going on in one place. By the logic which is implemented, your program will exit first level for loop whenever your entered value is not divisable by 4.
Read on for loops if you want to learn more https://www.learnjavaonline.org/en/Loops.
I recommend to start from while loops instead. The logic whould be this:
1. create variable to hold the correct answer saved
2. create another one to hold the value read from console i
3. start the while loop with condition i = scanner.nextInt()
3.1 check if the value just entered i is divisable by 4
3.2 if it is, then compare if it's larger than the one was saved before (initially saved value will be 0)
3.3 if it is larger, then assign the read value i to the saved
4. At the end of the loop, you will have the highest number divisable by four in your saved variable. Print it.
I will provide some help, according to
How do I ask and answer homework questions?
for (int i = scanner.nextInt(); i % 4 == 0;i = scanner.nextInt())
This only reads as long as ALL inputs are divisible by 4, that is why it ends at 16, because 87 is not divisible by 4.
for (boolean bull = true; bull == true ;bull ^= true)
This needs explanation by you, but I am pretty sure that it unconditionally executes the body of the inner loop exactly once. (Not 100% sure, because the representation of true and false could be weird in your machine. Should 0 be the representation of true, i.e. really weird, then it is an endless loop, which does not match the output you describe...)
System.out.println(saved);
This executes exactly once per input, except the last one, which is not a multiple of 4.
The value of saved is identical to input, as long as it is increasing.
These hints explain the unexpected output.
If you inspect the details of what the problem is, you should be able to improve your coding attempt.
This is how I super-quickly fixed in your code.
Note that there are no statements about the possible minimum value and about how do you stop the input. Therefore the solution is pretty-straightforward, it just reads the input until integers are present there.
This article may be useful about handling the input from the Scanner.
I hope the comments in the code will help. Add comments if there are any questions. Good luck!
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int currentMax = Integer.MIN_VALUE; // you may set negative or 0 if you know that all the input is positive
// int saved2 = 0; // no need for this variable
while (scanner.hasNextInt()) { // you can make a better input handling, especially if you know when it should end the input. Now it will end on any non-integer input line
int i = scanner.nextInt();
// for (int i = scanner.nextInt(); i % 4 == 0; i = scanner.nextInt()) {
// for (boolean bull = true; bull == true; bull ^= true) {
if (((i % 4) == 0) && (i > currentMax)) {
currentMax = i;
// saved -= saved2;
// saved += i;
// saved2 += i;
// }
}
}
System.out.println(currentMax); // moved out of "for" or "while" cycles. Print the value after the input has ended.
}
}

How to compare three values from text field and if any are below/above a certain value display a message?

Hi i'm trying to write a programme similar to a BMI calculator tutorial i followed and completed successfully last fortnight.
However I'm now trying to do a health programme that compares a users temperature/blood pressure and heart beat, and if any are below or above certain values to warn the user via console message.
for example
if
temperature <35 or >39 display a warning message or
heart rate <60 or >150 display a warning message or
blood pressure <100 or >150 display a warning message.
hI am unsure how to convert and compare the value as it says "Operator '<' cannot be applied to 'java.lang.String', 'int'". I have the user input the value in a text field and understand that it is cannot compare text fields, so i tried to convert it to a float using Float.parseFloat(temperatureStr); but that didn't seem to work. Is there something that can change String temperatureStr = temperature.getText().toString(); into an interger so I am able to compare it to a number and then display a warning message?
I am not sure but if i understand you correctly you try to implement something like this:
class UserClassName {
int bodyTemp;
int bloodPressure;
int heartSkip;
public void getUsersValues() {
Scanner body, temp, blood;
body = new Scanner(System.in);
temp = new Scanner(System.in);
blood = new Scanner(System.in);
System.out.println("Your temp ..");
String intputTempAsString = body.nextLine();
try {
bodyTemp = Interger.parseInt(inputTempAsString);
catch {
throw new Exception("Your warning her");
}
// Do this for ever Number or Value you wanna have and it should work
}
// Methods to compare the input
public boolean checkHeartSkiptsFrequncy() {
return heartSkip > 60 && heartskip < 150;
}
public boolean checkBodyTemp() {
return heartSkip > 35 && heartskip < 39;
}
public boolean checkBlood() {
return heartSkip > 100 && heartskip < 150;
}
public boolean checkHealth() {
if(!chechHeartSkipFrequncy) {
System.out.println("The Frequceny of you Heartbeat ....");
else if(!checkBodyTemp) {
System.out.println("Your body Temp is bad...");
else if(!checkBlood) {
System.out.println("Your blood ....");
else {
System.out.println("Everything is fine")
}
I think this is what you are looking for. I know that is not 100% perfect but i hope this it will help you to solve your problem.
This code is also no complete solution for your problem but i tried to cover all important aspekts.
If you have any questions or improvment for me than reply to this post.
Have a nice Day and good luck man.

Android/Java using two dimensional array to create chatbot

public class ChatBot {
String[][] chatBot={
// standard greetings
{ "hi", "hello", "hey" }, { "hi user"},
// question greetings
{ "how are you" }, { "good"},
// default
{ "I did not understand. Please try something else" }, };
public ChatBot() {
}
public String checkAnswer(String message) {
byte response = 0;
int messageType = 0;
String x = null;
List temp;
int cblength = chatBot.length - 1;
while (response == 0 && messageType <= cblength) {
temp = Arrays.asList(chatBot[messageType]);
if (temp.contains(message)) {
response = 2;
x = chatBot[(messageType) + 1][0];
}
messageType = messageType + 2;
if (response == 1)
x = chatBot[chatBot.length - 1][0];
}
}
return x;
}
I created this simple chatbot to test my chat application. It uses a two dimensional String Array to save the possible inputs and outputs. The checkAnwer method receives the user input and is supposed to return the correct output. It uses a while loop to check the input fields and return the corresponding output, if the content of the field matches with the array. If the loop reaches the end of the array, it is supposed to return the default answer. The first group of inputs (hi/hello/hey) returns the right output(hi user), but every other input causes the while-loop to exceed the array length.
Edit
I removed the error in the Code, all inputs are now accepted, non valid inputs return null.
Edit2
I changed int cblength = chatBot.length - 1;
to
int cblength = chatBot.length;
and messageType = messageType + 2;
to
if ((messageType+2)>=cblength)
{
response=1;
}
else {
messageType = messageType + 2;
}
The code is now working properly.
If I'm understanding your code correctly, chatBot has a length of 5. On each full pass of the while loop, messageType is incrementing by 2. This means that on the second pass, messageType = 2. This means that on the following line :
x = chatBot[(messageType * 2) + 1][0];
We are looking for (2*2)+1 = 5 as an index. As the list is of length 5, the max index is 4, causing the IndexOutOfBoundsException.
There are two main ways I could see to fix this:
Reconsider whether you really need to repeat the same block of code twice in the while loop - this adds a bit of unneeded complexity, and reduces how often the while conditions are checked.
Update the while condition to check that any (messageType*2)+1 which will occur during the iteration will still be within the bounds of the array.

How do I make a retry pop up if the input isn't what is wanted?

So I am trying to make a JOptionPanel popup when a user doesn't put in a number from 0-60 in a JTextField, but I'm not sure how
Here is what I tried
else if(e.getSource() == Save) {
Task task = new Task();
task.hour = hin.getText();
task.min = min.getText();
if(min.getText() > 0 && min.getText() < 60) {
JOptionPane.showMessageDialog(null, "Please enter a valid time.");
}
else{
task.day = (String) dayspinner.getValue();
task.description = desc.getText();
tasks.add(task);
ObjectOutputStream os = null;
try{
os = new ObjectOutputStream(new FileOutputStream(save));
os.writeObject(tasks);
os.close();
}catch(IOException ex) {
ex.printStackTrace();
}
tframe.setVisible(false);
}
}
But I get errors that say "bad operand types for binary operator'<'".
For user input validation, use either JFormattedTextField, JSpinner, InputVerfifer or even a DocumentFilter (but if you get here, there's something you're probably doing wrong)
These will allow you to validate the field's in real time (post focus change) and ensure that the user is only allowed to enter the values you want. You can also use an InputVerifier to restrict a change of focus, so the user won't be able to leave the field until they have entered a valid value
See How to Use Formatted Text Fields, How to Use Spinners and Validating Input for more details.
getText() method returns a String, and you cannot use < or > to compare Strings. It would be better if you convert the result of min#getText to an int first, then do the proper comparison. You can do this by using Integer#parseInt():
int minVal = Integer.parseInt(min.getText());
//fixed the condition
if (!(minVal > 0 && minVal < 60)) {
//rest of the code...
}
String cant be compared using comparison-operators. Parse the int-value (Integer.parseInt(String someString)) instead and compare these.
Change
if(min.getText() > 0 && min.getText() < 60) {
JOptionPane.showMessageDialog(null, "Please enter a valid time.");
}
To
if(Integer.parseInt(min.getText()) > 0 && Integer.parseInt(min.getText()) < 60) {
JOptionPane.showMessageDialog(null, "Please enter a valid time.");
}

Java add line to specific part of text file

COMMENTS BELOW ARE ANSWERING ANOTHER QUESTION, THIS IS THE ONLY WAY FOR ME TO ASK NEW QUESTION...
Okay. My program is like writing info on a .txt file. Currently it is writing info to end of the text file like so:
t/1/15/12
o/1/12/3
o/2/15/8
... (lots of lines like this.. all with different numbers)
o/1/16/4
Then.. when I add line using:
BufferedWriter fw = new BufferedWriter(new FileWriter(new File("C://Users/Mini/Desktop/Eclipse/Japda/map/" +Numbers.map +".txt"), true));
fw.newLine();
fw.write(RightPanel.mode.charAt(0) +"/" +ID +"/" +Numbers.middlex +"/" +Numbers.middley);
fw.close();
It adds the line I want to but currently to the end of the text file.. However I would like it to write that line to a specific part of the text files.. I already do know the number of the line I want to write it.. (It is calculated depending on other lines..) :D Is there any way to do it? Or what would be the best way to edit one specific line in the middle of that text file?
To achieve what you require, you would need to use a RandomAccessFile. Steps:
First create a RandomAccessFile then:
Create a variable called lineStart which is initially set to 0
(beginning of the file)
Read in the file line by line using readline
Check whether it is the required line that you wish to insert before
If it is the correct place, then lineStart will hold the position
just before the line you wish to insert before. Use seek to
position you at the correct place by initially using seek(0) to
position you at the start of the file, then seek(lineStart) to get
the required position. You then use writeChars to write to the file.
Remember that you have to explicitly write the newline.
If it is not where you wish to insert then call getFilePointer, and
store value in lineStart
REPEAT STEPS 2-5 UNTIL YOU ARRIVE AT THE DESIRED PLACE FOR INSERTION
You want a do-while loop:
do {
//code
} while (expression);
Source:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/while.html
You probably want something like this:
int[] done = new int[100];
int randomquestion;
do{
randomquestion = (int)(Math.random() * 83 + 1);
if(done[randomquestion] != 1)
{
//ask random question
//if answer is correct, set done[randomquestion] = 1
//else just let do-while loop run
}
//check if all questions are answered
} while (!areAllQuestionsComplete(done));
Here is the method areAllQuestionsComplete(int[]):
private boolean areAllQuestionsComplete(int[] list)
{
for(int i = 0; i<list.length; i++)
{
if(list[i] != 1)
{
return false;//found one false, then all false
}
}
return true;//if it makes it here, then you know its all done
}
Looking at your latest code:
for(int i = 0; i<done.length; i++)
{
done[i] = 0;//need default values else wise itll just be NULL!!!
}
do{
ran = (int)(Math.random() * 83 + 1);
//before entering the do-while loop, you must set default values in the entire done[] array
if(done[ran] != 1)
{
//ask random question
//if answer is correct, set done[ran] = 1
//else just let do-while loop run
if (ran == 1) { //1
question = "kala";
rightanswer = "fish";}
if (ran == 2) { //2
question = "peruna";
rightanswer = "potato";}
if (ran == 3) { //3
question = "salaatti";
rightanswer = "cabbage";}
if (ran == 4) { //4
question = "kalkkuna";
rightanswer = "turkey";}
if (ran == 5) { //5
question = "kia";
rightanswer = "tikku";}
//YOU MUST HAVE EVERY CONDITION COVERED
//say your random number makes the number 10
//you dont set question to anything at all (hence getting null!)
System.out.println(question);
System.out.print("Vastaus?: ");
answer = in.readLine();
//if (answer == rightanswer){
//must use .equals with Strings...not ==
if (answer.equals(rightanswer)){
right++;
done[ran] = 1;}
else{wrong++;}
}
//check if all questions are answered
} while (!areAllQuestionsComplete(done));//use the method I wrote!
EDIT:
You must put default values in the array. When you create an array, the default value is null.
int[] done = new int[100];//create array but everything is null
for(int i = 0; i<done.length; i++)
{
done[i] = 0;//need default values else wise it'll just be NULL!!!
}
//must be done before the do-while loop starts
Finally, make sure your random number generator picks the correct range in numbers. If you have an array that is size 100, then it's indexes will be 0-99. This means there is no done[100]. It goes from done[0] to done[99].
If you have done[] be a size of 5, then it will range from done[0] to done[4]. That means you should randomly generate like this:
randomquestion = (int)(Math.random() * 5 );

Categories

Resources