Trouble in getting proper string input - java

I am writing a method in Java in which the user is supposed to enter a license plate for a car. The fist two signs must be capital letters, the third sign must be a digit between 1 and 9, and the last 4 digits must be digits between 0 and 9. If the user does not enter this properly, an error message should appear, and the user will be asked to input the license plate again.
After testing the problem I have discovered that if I deliberately make many different mistakes over and over, and then finally enter the license plate correctly, the program still informs me that my input is wrong. I am having a hard time knowing how to construct this, since it is supposed to take into account so many possible errors. My code presently looks like this for the method in question:
char sign;
System.out.print("License plate: ");
licensePlate = input.next();
for (int index = 0; index < 2; indeks++) {
sign = licensePlate.charAt(indeks);
while (sign < 'A' || sign > 'Z') {
System.out.println(licensePlate + " is not a valid license plate (two big letters + five digits where the first digit can not be 0)");
System.out.print("License plate: ");
licensePlate = input.next(); }
}
while (licensePlate.charAt(2) < '1' || licensePlate.charAt(2) > '9') {
System.out.println(licensePlate + " is not a valid license plate (two big letters + five digits where the first digit can not be 0)");
System.out.print("License plate: ");
licensePlate = input.next(); }
for (int counter = 3; counter < 7; counter++) {
sign = licensePlate.charAt(teller);
while (sign < '0' || sign > '9') {
System.out.println(licensePlate + " is not a valid license plate (two big letters + five digits where the first digit can not be 0)");
System.out.print("License plate: ");
licensePlate = input.next(); }
}
carObject.setLicensePlate(licensePlate);
If anyone can help me writing this properly I would be extremely grateful!

The problem is that you're taking new input every so often, but then not starting again. It would be worth having a separate method to perform the test, like this:
boolean gotPlate = false;
String plate = null;
while (!gotPlate) {
System.out.print("License plate: ");
plate = input.next();
gotPlate = checkPlate(plate);
}
carObject.setLicensePlate(plate);
Now put the rest of your logic into the checkPlate method:
static boolean checkPlate(String plate) {
// Fixed typos here, by the way...
for (int index = 0; index < 2; index++) {
char sign = plate.charAt(index);
if (sign < 'A' || sign > 'Z') {
System.out.println(plate + " is not a valid license plate " +
"(two big letters + five digits where the first digit" +
" can not be 0)");
return false;
}
}
// Now do the same for the next bits...
// At the end, if everything is valid, return true
return true;
}
I'll leave you to do the checking for '0' etc - but hopefully you can see the benefits in structuring the "testing" part separately from the "getting input" part.
EDIT: Original answer...
Sounds like you want a regular expression:
Pattern pattern = Pattern.compile("[A-Z]{2}[1-9][0-9]{4}");
Full sample:
import java.util.regex.*;
public class Test {
private static final Pattern PLATE_PATTERN =
Pattern.compile("[A-Z]{2}[1-9][0-9]{4}");
public static void main(String args[]) {
checkPlate("AB10000");
checkPlate("AB10000BBB");
checkPlate("AB1CCC0BBB");
}
static void checkPlate(String plate) {
boolean match = PLATE_PATTERN.matcher(plate).matches();
System.out.println(plate + " correct? " + match);
}
}
Of course, that doesn't tell you which bit was wrong. It also doesn't help you work out what was wrong with your original code... see earlier part.

Don't use a character based approach. Take the whole string and use the regex list above and either fail or pass it as a one time operation. You don't need that level of control here to get a pass/fail result.
HTH,
James

You should really use a regular expression for this.
However, if you want to fix the problem with your code: the problem with your approach is that you are asking for input again after you've done some validation.
For example, if the first two characters are correct, the second loop will validate the input single-handedly. If that's wrong and it asks for input again, the user could input the first two characters incorrectly and that check won't be done because the code will have passed the first stage and is now only checking the second stage.
If you were to continue with your approach, you should make one large loop which would repeat if anything is wrong in the input and do all of the checks again in order.

Related

Creating a game with loops that compares a secret number to user input

I was asked to create a mastermind game for school. The project never ran properly and I believe I went about the process in the wrong way. While the assignment is already past due I would like to know where I went wrong. Keep in mind we have still not gone over arrays.
This was the assignment description:
Your program will choose a random 4 digit number as the secret number. Your program must prompt the user to enter a 4 digit number as their guess. The program will respond with a message indicating how many of the digits in the user’s guess are the same as the digit in the same position in the secret number. For example, if the secret number is 3749, and the user’s guess is 9753, then the program would respond with the message You matched 1, because only one of the digits (the 7) in the user’s guess is the same as the digits in the same position in the secret number. The program will allow the user to continue to enter guesses until they guess the correct secret number. After the user has entered the secret number, the program will output a count of the total number of guesses the user took to find the secret number. Then the program will ask the user if they would like to play again. If the user answers “yes”, then the program will choose another random 4 digit number and play continues as described above.
Where was the best place to start for this assignment?
What was the best way to use loops?
How do I select different parts of the secret number?
Any help I can get now will help me catch up in the class.
import java.util.Scanner;
public class Assignment04 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("----- MASTERMIND -----");
System.out.println("Guess the 4 digit number!");
int secretNumber = (int)(Math.random() * 1000 + 1);
int usersGuess = 0;
int counter = 0;
int guessCount = 1;
for(int i=0; i<guessCount; guessCount++) {
System.out.print("Enter your guess: ");
usersGuess = in.nextInt();
if (String.valueOf(usersGuess).substring(0,0)==String.valueOf(secretNumber).substring(0,0));
{
guessCount ++;
counter ++;
break;
if (String.valueOf(usersGuess).substring(1,1)==String.valueOf(secretNumber).substring(1,1));
{
guessCount ++;
counter ++;
break;
}
if (String.valueOf(usersGuess).substring(2,2)==String.valueOf(secretNumber).substring(2,2));
{
guessCount ++;
counter ++;
break;
}
if (String.valueOf(usersGuess).substring(3,3)==String.valueOf(secretNumber).substring(3,3));
{
guessCount ++;
counter++;
break;
}
System.out.println("You matched " + guessCount);
if(counter==4);
{
System.out.println("Congratulations! You guessed the right number in " + counter + "guesses");
System.out.println("Would you like to play again? (Yes/No)");
}
}
}
}
}
This is all I was able to come up with.
So few points
Your for loop condition (i < guessCount) shouldn't be driven by the guess count because it should continue looping until they guess correctly.
You'd maybe want e.g. a boolean named "continueLooping" which is true and a while condition evaluating that instead of a for loop.
If the guessCount (which is summing the number of times the correct digits were aligned) is 4 then "continueLooping" would be set to false if the user said "No" when asked "Would you like to play again?"
You shouldn't be breaking after each matched digit. What if the first digit matches and the second digit matches? The break after the first match will stop the second digit ever being counted and the loop will exit
You want to check the length of their input to make sure it's 4 digits long
You'd want to use .equals() method of String rather than == as String is a reference type meaning equality is checked using equals() not the "==" operator (that is for checking primitive equality or exact reference equality)
Your "counter" should only increment once at the beginning of every loop
You GuessNumberRandomizer is wrong: it will produce 3 digit numbers only. Use this for 4 digits:
int secretNumber = (int)(Math.random() * 10000 + 1);
Also, I would suggest using String input or better yet, parse the integer input to String and use charAt() method for comparison instead. Also your usage of break may create some errors if more than 1 one digit was guessed correctly.
The first loop is is not really a good case scenario for a for loop. You should use a while loop. While will continue iterating, possibly infinitely, until the condition on which it's evaluated is no longer true.
Since your program should continue until the user guesses, or until he guesses right and doesn't want to play anymore, you should have a boolean "flag" which tells the game it should continue the loop. If the game has been won (when the correct guesses in a turn is equal to 4) then you should prompt the user if they want to continue playing, and if they say no, you just turn off the flag and the program exits.
Something like this
boolean continue = true;
int correctGuesses;
int numberOfTimesAttempted = 0;
while(continue){
numberOfTimesAttempted++;
correctGuesses = 0;
//Your game logic
if(correctGuesses == 4){
System.out.println("Do you wish to continue? Y or N");
char answer = sc.nextLine();
if(char.toUpper('N'){
continue = false;
System.out.println("It took you " + numberOfTimesAttempted + "to win!");
}
}
}
As some users pointed out, you should also have logic to verify that the user enters strictly 4 numbers.
Rather than comparing each number individually, simply convert the number to a char array and create a for loop that iterates through it. if the char at the current index is equal to the one in the secret number, increase the number of guess counts.
At the end of each loop, print the number of correct guesses. If number of guesses is 4, the user wins.

Java, How do I validate input when using scanner?

I am currently working on Java code. Basically, the int input works. However, if I type in a character, the whole system crashes. My question is as to what needs to be changed in the below code in order for the user to receive a message stating that only an int is the valid input, and to try again if they input a character.
do {
System.out.println("How many players would like to participate in this game?\t(2-4 players)");
numberOfPlayers = in.nextInt();
} while(in.hasNextInt());
numberOfPlayers = in.nextInt();
I personally prefer to use a while loop for this sort of thing rather than the do/while. Not that there is anything wrong with the do/while, I just feel it's more readable to use the while loop.
I agree with others here, accept String digits from the User instead of Integer. In my opinion it saves you other possible problems down the road and you have no need to purposely apply a try/catch mechanism should the User supply an invalid entry. It also allows you to easily apply a mechanism to quit the application which, again IMHO, should be made available to all Console app's.
You've got your answer for carrying out the task using a do/while loop but I would like to show you another way to do this sort of thing:
Scanner in = new Scanner(System.in);
String ls = System.lineSeparator();
int numberOfPlayers = 0;
String userInput = "";
while (userInput.equals("")) {
// The Prompt to User...
System.out.print("How many players would like to participate in this game?" + ls
+ "2 to 4 players only (q to quit): --> ");
userInput = in.nextLine();
// Did the User enter: q, quit (regardless of letter case)
if (userInput.toLowerCase().charAt(0) == 'q') {
// No, the User didn't...
System.out.println(ls + "Quiting Game - Bye Bye.");
System.exit(0); // Close (exit) the application.
}
/* Did the User supply a string representation of a numerical
digit consiting of either 2, 3, or 4. */
if (!userInput.matches("[234]")) {
// No, the User didn't...
System.out.println("Invalid input! You must supply a number from 2 to 4 "
+ "(inclusive)." + ls + "Try again..." + ls);
userInput = "";
continue; // Loop again.
}
// Convert numerical string digit to an Ingeger value.
numberOfPlayers = Integer.parseInt(userInput);
}
System.out.println(ls + "The Number of players you provided is: --> "
+ numberOfPlayers);
You will notice that the Scanner#nextLine() method is used to accept User input as a String. This now means that we need to validate the fact that a string representation of a Integer numerical digit (2 to 4 inclusive) was supplied by that User. To do this you will notice that I used the String#matches() method along with a small Regular Expression (RegEx) which consists of the following string: "[234]". What this does in conjunction with the String#matches() method is it checks to see if the string value in the userInput variable contains either a single "2", a single "3", or a single "4". Anything else other than any one of those three digits will display this message:
Invalid input! You must supply a number from 2 to 4 (inclusive).
Try again...
and, force the User make yet another entry.

A Program that Checks Consecutive Letters - Java

I'm looking for help with a question I have. We just started learning simple java in our course after learning a tonne of C++.
One of our bonus missions for people who know code more than what was taught in class.
The mission is as follows: Write a function by the name lettersSeries which gets letters (one letter at a time, assume all letters are lower case) inputted from the user. The function stops accepting letters from the user once the user has inputted 3 consecutive letters. (Only for loops can be used without while loops)
Example: a -> b -> a -> c -> d -> e (Here is stops)
As far I don't know much and I would be happy if someone would help me with this... I tried some options but I have no idea how to trace the alphabet, and especially how to check if letters are consecutive...
Thanks!
public static void letterSeries() {
//We create a scanner for the input
Scanner letters = new Scanner(System.in);
for(Here I need the for loop to continue the letters input) {
//Here I need to know if to use a String or a Char...
String/Char letter = next.<//Char or String>();
if(Here should be the if statement to check if letters are consecutive) {
/*
Here should be
the rest of the code
I need help with
*/
Obviously, you could change the code, and not make my pattern, I would just be happier with an easier way!
Here's how I would tackle the problem, I'm going to let you fill in the blanks with this though so I don't do all of your homework for you.
private void letterSeries() {
Scanner scanner = new Scanner(System.in);
char prevChar;
char currChar;
int amountOfConsecutives = 0;
final int AMOUNT_OF_CONSECUTIVES = 2;
for(;;) {
// Take in the users input and store it in currChar
// Check if (prev + 1) == currChar
// If true, amountOfConsecutives++
// If false, amountOfConsecutives = 0;
// If amountOfConsecutives == AMOUNT_OF_CONSECUTIVES
// Break out of the loop
}
}
You can use chars' Unicode number to check if letters are consecutive: if a and b are your letters, try to check if b - a == 1. If consequentiality is intended in a case-insensitive way ('B' consecutive to 'a') then check: (b - a == 1 || b - a == 33).
Scanner letters = new Scanner(System.in);
char previousChar = '\0';
int consecutive = 1;
for(; consecutive != 3 ;){
char userInput= letters.findWithinHorizon(".", 0).charAt(0);
if (userInput - previousChar == 1){
consecutive++;
} else {
consecutive = 1;
}
previousChar = userInput;
}
I cheated a little bit with this solution. I used a for loop with only the middle part so it acts like a while loop.
Anyway, here's how it works.
The first three lines create a scanner for user input, a consecutive variable that counts how many consecutive letters the user enters, and a previousChar to store the previous character.
"Why does consecutive start at 1?" you might ask. Well if the user enters one letter, it is going to be consecutive with itself.
In the for loop, as long as consecutive != 3, the code is going to run. The first line in the loop we read a character using findWithinHorizon(".", 0).charAt(0). And then the if statement checks whether it is a consecutive letter with the previous character. If it is, add one to consecutive and if not, reset consecutive to one. Lastly, we set previousChar to userInput to prepare for the next iteration.
private void letterSeries() {
Scanner letters = new Scanner(System.in);
String last = "";
int counter = 0;
for (;counter < 2;){
if ( last.equals (last=letters.next())) counter ++;
else counter = 0
}
}

Guessing Game Help :)

Ok, so my computer teacher has asked us to make a simple game that asks the user to guess a radomly generated number, but I want to take it one step further and make it so that it display error messages when the user tries certain things. The problem here is that I am new to booleans and well, I am having a bit of trouble using java.util.Scanner and booleans. So, if anyone could take a quick look at this I would appreciate it.
import java.util.Scanner;
import java.util.Random;
public class MoreGuessing{
//Instantiation
Scanner reader = new Scanner(System.in);
Random number = new Random();
//Variables
int randomnumber = number.nextInt(10) + 1;
int cntr = 1;
static String decimalguessed;
String error1 = "Error001: Decimal found, please enter a whole number between 1-10." + "\n" + "Program terminated......";//Decimal portion error.
String error2 = "Please enter a positive number." + "\n" + "Program terminated......"; //Negative number error.
String error3 = "Unknown character entered." + "\n" + "Program terminated......"; //Unknown character error.
//Verifier
public static boolean verifyLetters() {
if (decimalguessed.matches("[a-zA-Z]+")){
return true;
}else{
return false;
}
}
public static void main(String [] args){
//Input and display
System.out.print("Please enter a whole number between 1-10: ");
decimalguessed = reader.nextLine();
//Process and Errors
while (decimalguessed != randomnumber) {
if (verifyLetters() != false){
System.out.println(error3);
System.exit(1);}
if (decimalguessed % 1 != 0) {
System.out.println(error1);
System.exit(1);}
if (decimalguessed < 0) {
System.out.println(error2);
System.exit(1);}
if (randomnumber != decimalguessed){
System.out.println("You've lost, please make another attempt.");}
System.out.print("Please enter a whole number between 1-10: ");
decimalguessed = reader.nextDouble();
cntr++;
}
if (cntr == 1) {System.out.println("Congratulations! You've guessed the number on your first attempt!");;
}
else {System.out.println("Congratulations! You've guessed the number, it took you " + cntr + " tries");}
}
}
You need to parse your input. decimalguessed is a string, and so you can't do comparisons like decimalguessed % 1.
You can convert it to an integer like this:
int guess = 0;
try {
guess = Integer.parseInt(decimalguessed);
} catch (NumberFormatException e) {
System.out.println("Your guess was not an integer: " + e.getMessage());
System.exit(1);
}
This will handle both cases where decimalguessed contains letters, and where it contains decimal points/fractions. decimalguessed is still a string, but guess now contains the integer version of it, so you can compare it to randomnumber properly. (Your loop would have never exited before, because a string is never == an integer)
Some other notes:
You should never have:
if (condition) {
return true;
} else {
return false;
}
This can always be simply replaced with
return condition;
It feels like you're very new to this. Welcome to programming!
So first, in Java generally you're not going to have all of that instantiation and variables stuff outside of your main function, unless you're going to make everything static. I would move all of that into your main function, un-static the decimalguessed variable and setup your verifyLetters function to take an argument of String decimalguessed. It may also be wise to check if the value is a number, rather than seeing if it is not a letter. There a lot of non-number, non-letter characters.
Once you've figured out that the guess is a number, you need to tell java it is one (cast it) to a decimal, then do you further comparisons against that decimal.
Darth Android also makes some good points, especially about booleans. You should never have the only result of an if/else be to return a boolean, just return the boolean. Also avoid comparisons to true/false, just do the if on the function/variable alone, or negate it with an '!' to check for false.
Good luck!

Trying to create an Acronym out of user input

Hello I am working on an assignment and I'm running into issues I was hoping for a little direction...
The purpose is to have user input a phrase and create an acronym out of that phrase. Anything over three words will be ignored.
I'm having issues with the acronym part, I am able to get the first character and figured that I would loop through the user input and grab the character after a space, but that is not working. All I am getting is the first character, which is obvious because I grab that first, but I can't figure out how to "save" the other two characters. Any help is greatly appreciated.
*********UPDATE************************
So thanks to an answer below I have made progress with using the StringBuilder. But, now if I enter "Your Three Words" the Output is: YYYYYTYYYYYWYYYY
Which is progress but I can't understand why it's repeating those first characters so many times??
I edited the code too.
*********UPDATE*****************************
public class ThreeLetterAcronym {
public static void main(String[] args) {
String threeWords;
StringBuilder acronym = new StringBuilder();
Scanner scan = new Scanner(System.in);
System.out.println("Enter your three words: ");
threeWords = scan.nextLine();
for(int count = 0; count < threeWords.length(); count++) {
acronym.append(threeWords.charAt(0));
if(threeWords.charAt(count) == ' ') {
++count;
acronym.append(threeWords.charAt(count));
}
}
System.out.println("The acronym of the three words you entered is: " + acronym);
}
}
You can't save the other characters because char is supposed to store only one character.
You can use a StringBuilder in this case
StringBuilder acronym = new StringBuilder();
Then in your loop simply replace it with
String[] threeWordsArray = threeWords.split(" ");
for(String word : threeWordsArray) {
acronym.append( word.substring(0, 1) );
}
**updated
You store the character at the current index in space:
char space = threeWords.charAt(count);
Then you compare the value of space with the integer value 3:
if(space < 3)
This will almost certainly never be true. You are asking for the numeric value of a character. Assuming it is a letter it will be at least 65. I suspect that your intention is to store something different in the variable space.

Categories