How to get scanner input to not trigger third method? - java

I'm working on an assignment and I mostly have it finished but I am having an issue with the last method. I'm trying to write a continueGame() method that will ask the user if they want to continue to play, and accept "y" or "n". If answered "y", the program starts again. If answered "n", the program stops and a message is shown. The problem is I need it to trigger the continueGame() method only when userChoice == answer. This is a number guessing game with an object oriented approach.
I've tried to call the continueGame() method inside my else if(userChoice == answer) statement but it doesn't seem to work. Even when my other if/else if statements are triggered, it continues to the continueGame() method.
Here is the main driver for the game
import java.util.Scanner;
public class NumberGame
{
public static void main(String[] args)
{
Scanner input = new Scanner (System.in);
GameOptions opt = new GameOptions(); // Your created class
int userChoice = -1234;
int answer = -1234;
boolean keepPlaying = true;
System.out.println("Guess the Number Game\n");
while (keepPlaying == true) {
answer = (int) (Math.random() * 10)+1;
//Create a getChoice method in your class and make sure it accepts a Scanner argument
userChoice = opt.getChoice(input);
//Create a checkAnswer method in your class. Make sure it accepts two integer arguments and a Scanner argument
opt.checkAnswer(userChoice, answer, input);
// Create a continueGame method in your class and make sure it accepts a Scanner argument
keepPlaying = opt.continueGame(input);
}
System.out.println("Thanks for playing.");
}
}
Here is the class that I am working on for the methods. Note that I can not make any modifications to the main driver file.
import java.util.InputMismatchException;
import java.util.Scanner;
import java.lang.NumberFormatException;
public class GameOptions {
int count = 0;
boolean cont = true;
//getChoice Method for NumberGame
public int getChoice(Scanner scnr) {
System.out.println("Please choose a number between 1 and 10: ");
int userGuess = 0;
String input = scnr.next();
try {
userGuess = Integer.parseInt(input);
if (userGuess < 1 || userGuess > 10) {
throw new IllegalArgumentException("Invalid value. Please enter a number between 1 and 10: ");
}
}
catch(NumberFormatException e) {
System.out.println("Error - Enter Numerical Values Only");
return userGuess;
}
catch (IllegalArgumentException ex) {
System.out.println(ex.getMessage());
}
return Integer.parseInt(input);
}
public void checkAnswer(int userChoice, int answer, Scanner scnr) {
if (userChoice > answer && userChoice < 11) {
System.out.println("Too high. Try again.");
count++;
} else if (userChoice < answer && userChoice > 0) {
System.out.println("Too low. Try again.");
count++;
} else if (userChoice == answer) {
System.out.println("You got it! Number of tries: " + count);
System.out.println("Would you like to play again? (y/n)");
}
}
public static boolean continueGame(Scanner scnr) {
String input = scnr.nextLine();
if (input.toLowerCase().equals("y")){
return true;
} else if (input.toLowerCase().equals("n")){
return false;
} else {
System.out.println("Invalid entry. Please enter either y or n: ");
return continueGame(scnr);
}
}
}
So I should be able to enter a number, and if its lower than the answer it will tell me I am too low, if its higher than the answer it will tell me that its too high, if its equal it will tell me I won and prompt me to press "y" or "n" if I want to continue. Another issue I am running into is that I am getting "Would you like to play again? (y/n)" no matter whether I guess the right number or not and my only option is to hit "y" or "n"

The driver class is calling continueGame() inside the while loop. If you're not allowed to modify that class then presumably asking at every iteration is the intended behaviour.
You should move System.out.println("Would you like to play again? (y/n)"); into the continueGame() method so that it only asks when that method is called.

The way the driver is written (I guess) is coming from your instructor/lecturer/professor, right?
With the driver (as it is), you don't need to call continueGame method from checkAnswer method. The driver is going to call it.
Just run the driver and it will work. If you have a proper IDE (eclipse or Netbeans), trace through and see what the input accepted is (I think there is line-feed in the accepted answer).
Try this (I just changed the loop structure; yours is also valid):
public static boolean continueGame(Scanner scnr) {
while (true) {
String input = scnr.nextLine().trim(); // to remove white spaces and line-feed
if (input.toLowerCase().equals("y")){
return true;
} else if (input.toLowerCase().equals("n")){
return false;
} else {
System.out.println("Invalid entry. Please enter either y or n: ");
}
}
}
Added for checkAnswer method to keep the user guess the answer until he gets correct:
public static checkAnswer(/*three arguments*/) {
boolean correct = false;
while (! correct) {
// accept input
if (answer.equals(input)) {
correct = true;
// print required correct/congrats messages here
} else {
// print required input/try again messages here
}
}
// print would you like to play again with new answer y/n message here.
}
In my opinion, printing "play again with new answer y/n message" should go into continueGame method (from last portion of checkAnswer) method to stick to encapsulation concepts.

Related

How to type correct answer in the last try without showing the game over text

I am a beginner and as you can see I made a simple Java game.
The user has 5 tries to guess a number between 1 and 20.
If the user wins a congratulations message will show.
If the user didn't succeed a game over message will pop up.
Issue
When the user enters the right answer on the 5th try both congratulations and game over messages will pop up.
Code
package org.meicode.Loops;
import java.util.Objects;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.println("Welcome");
System.out.println("Enter your name please ");
Scanner scanner = new Scanner(System.in);
String name = scanner.next();
System.out.println("Hello " + name);
System.out.println("Type 1 to start the game");
int yes = scanner.nextInt();
while (yes != 1) {
System.out.println("Type 1 to start the game");
yes = scanner.nextInt();
}
System.out.println("Guess the number in my mind,It is between 1 and 20 and you got 5 tries");
int timestried = 0;
Random random = new Random();
int x = random.nextInt(20) + 1;
while (timestried < 5) {
timestried++;
Scanner scanner1 = new Scanner(System.in);
int answer = scanner.nextInt();
if (x == answer) {
System.out.println("Well done, you did it");
} else if (x > answer) {
System.out.println("Try again,hint:the value is bigger than what you typed");
} else if (x < answer) {
System.out.println("Try again,hint:the value is smaller than what you typed");
}
}
System.out.println("Game over, the number was " + x);
}
}
How can I fix it?
Here is my attempt. I have added some comments in the code to help you.
Note that I have changed some of the file names to, so you may need to change them back for it to run, or just copy the main code section:
package com.misc;
import java.util.Objects;
import java.util.Random;
import java.util.Scanner;
public class GameTest {
public static void main(String[] args) {
System.out.println("Welcome");
System.out.println("Enter your name please ");
Scanner scanner = new Scanner(System.in);
String name = scanner.next();
System.out.println("Hello " + name);
System.out.println("Type 1 to start the game");
int yes = scanner.nextInt();
//We initialize the answer variable here to use it later on.
int answer = 0;
while (yes != 1) {
System.out.println("Type 1 to start the game");
yes = scanner.nextInt();
}
System.out.println("Guess the number in my mind,It is between 1 and 20 and you got 5 tries");
int timestried = 0;
Random random = new Random();
int x = random.nextInt(20) + 1;
//Print out the randomly generated number so we can test it. We answer wrong 4 times then put in the right answer to see if the message is fixed.
System.out.println("Testing: the answer is " + x);
while (timestried < 5) {
timestried++;
Scanner scanner1 = new Scanner(System.in);
answer = scanner.nextInt();
if (x == answer) {
System.out.println("Well done, you did it");
} else if (x > answer) {
System.out.println("Try again,hint:the value is bigger than what you typed");
} else if (x < answer) {
System.out.println("Try again,hint:the value is smaller than what you typed");
}
}
//This is the conditional that uses the answer variable we declared earlier above to avoid printing out the Game Over message in a success scenario.
if (x != answer) {
System.out.println("Game over, the number was " + x);
}
}
}
Here is proof that it works. I made the program print out the real answer, answered wrong 4 times and correctly the 5th time.
Simple fix
There are 2 things I would add to your code to achieve the desired behavior:
break or exit the loop on correct answer
set a flag signaling the question was solved to later build the message upon it
Basics: How to break loops and why
You can achieve this by two ways:
break the loop when the user typed the correct answer
add an exit-condition to the loop
return from the whole method prematurely
throw an exception that can either be caught outside or will also exit the method
I will explain (1) and (2) here in this answer (3) in a separate answer.
(1) Breaking the loop
The loop shall continue until:
the maximum number of tries has been reached
the correct answer was given
Use a break; statement to break the loop if correct answer:
if (x == answer) {
System.out.println("Well done, you did it");
break;
}
Note: contrary a continue; will skip further loop-body and jump to the next iteration.
(2) add a flag signaling premature exit (e.g. correct answer)
You can add a flag that is set to true if the user types the correct answer:
boolean userHasAnsweredCorrect = false;
while (timesTried < 5) { // here the flag can be added instead breaking
if (x == answer) {
System.out.println("Well done, you did it");
userHasAnsweredCorrect = true;
break;
}
}
// omitted some lines .. then at the end
if (userHasAnsweredCorrect) {
System.out.println("You beat the game!")
} else {
System.out.println("Game over, the number was " + x);
}
See how you define the flag before the loop, set it inside the loop (together with a break;) and then test on the flag after the loop.
Combined: set flag and add exit-condition
boolean userHasAnsweredCorrect = false;
while (timesTried < 5 && !userHasAnsweredCorrect) { // here the break happens instead
if (x == answer) {
System.out.println("Well done, you did it");
userHasAnsweredCorrect = true;
// break;
}
}
Find 2 more simpler ways of breaking the loop in my other answer, here follows the 3rd way:
Put the whole game into a method like startGame() and exit from that. Either exit after loop with max-tries has finished or inside the loop (prematurely) if answered guess was correct.
(3) Exiting the loop and method using return
That premature method-exit can be achieved by inserting a return; inside the loop.
public void startGame() {
// rest of preparation
// starting the game-loop
for (int i = 1; i <= maxTries; i++) { // for-i is indexed and safer (no infinite-loop)
// read input
// score or evaluate answer against x
if (x == answer) {
System.out.println("Well done, you did it");
return; // exit the method, not reaching "game-over" after the loop
}
// continue the iteration
}
// game-over (if not previously exited because of victory)
}
To have an exit-condition for the for loop, define int maxTries = 5 either as local variable, class field or constant.

Repeat a loop already satisfied in java

I'm looking to repeat a "game" if it is already satisfied in my case where user has to guess the random number. I can't understand where to to get back to the main game unless i have to create another "do - while" loop inside it and retype the game again in the section where it says: System.out.println("you have tried: " + count + " times. Would you like to play again? y/n"). Is there a way to just bring back to the actual guess loop rather than create another one?
Hopefully makes sense.
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
public class pass {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String pass = "password123";
String input;
int guess;
int count;
count = 0;
int num;
do {
System.out.print("Enter your password: ");
input = scanner.next();
} while (!input.equals(pass));
System.out.println("Correct! Now play the guess game! Guess a number between 1 - 10.");
do {
num = ThreadLocalRandom.current().nextInt(1,10);
guess = scanner.nextInt();
count++;
if (guess == num) {
System.out.println(" Well done!");
**System.out.println("you have tried: " + count + " times. Would you like to play again? y/n");**
}
else if (guess < num) {
System.out.println("your number is smaller than the number given");
}
else {
System.out.println("your guess is too high");
}
} while (guess != num);
}
}
The simplest solution would be to move the entire "guess loop" into a separate method. Then in the case when you want it to repeat, just call the method recursively.
If you want to reuse code you can make functions (or methods here, because we are inside a class). They can be used to encapsulate code and call it from anywhere to use it.
You can define a methods like that:
public static void methodName() {
// code go here
}
Then, you can call it from anywhere like that :
pass.methodName(); // It will execute the code inside methodName()
In reality, this is a lot more complex than that, you can give methods values and return others, change the scope of it to make it internal only or reachable by other classes. But I presume that you are a beginner so I keep it simple. I strongly recommend you to make a quick research about Object Oriented Programmation!
For your code, you can put the game's while loop in a method and call it at the beginning and each time the player wants to restart the game. Good luck with your game!
I manage to do this way. It seems working but one thing is letting me down at the very last when I key in "n" or other key than "y". Exception in thread "main" java.util.InputMismatchException. Is there a more softer way to finish it?
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
public class pass {
public static void randomnum(){
Scanner scanner = new Scanner(System.in);
int guess;
int count;
count = 0;
int num;
do {
num = ThreadLocalRandom.current().nextInt(1,10);
guess = scanner.nextInt();
count++;
if (guess == num) {
System.out.println(" Well done!");
System.out.println("you have tried: " + count + " times.");
String answer;
do{
System.out.println("Do you want to play again? y/n");
answer = scanner.next();
if (answer.equals("y")) {
System.out.println("let's play again");
randomnum();
System.out.println("Correct! Now play the guess game! Guess a number between 1 - 10.");
}
else {
System.out.println("you are logout!");
break;
}
}while (answer.equals("Y"));
randomnum();
}
else if (guess < num) {
System.out.println("your number is smaller than the number given");
}
else {
System.out.println("your guess is too high");
}
} while (guess != num);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String pass = "password123";
String input;
do {
System.out.print("Enter your password: ");
input = scanner.next();
} while (!input.equals(pass));
System.out.println("Correct! Now play the guess game! Guess a number between 1 - 10.");
randomnum();
}
}

How to end a while loop [duplicate]

This question already has answers here:
Cant figure out how to exit the loop of my program
(3 answers)
Closed 6 years ago.
My program for class asks to run the program as long as the user doesn't enter the input of -99. When I run the program and enter a usable number that isn't -99, the console will run a continuous looping answer until I have to press end.
How can I change the program so for each input there will be one answer and the program restarts until user inputs -99?
import java.util.Scanner; //import scanner
import java.io.*; //import library
public class is_odd_or_even_number {//begin class
public static void main(String []args) {//begin main
Scanner input = new Scanner(System.in);
//use try/catch method to test for invalid input
try{
//promt user to input a value
System.out.print("Enter a positive integer value: ");
int number = input.nextInt();
//PART I NEED HELP WITH **************
while (number != -99){
//Start of if statement to test which to print and call of isEven method
if (isEven(number)) {
System.out.println("Your number is Even!");
}
else
System.out.println("Your number is Odd!");
}
}
//open catch method and print invalid
catch(Exception notNumber) {
System.out.println("Input not a number, try again.");
}
}
//begin testing for odd or even in new method
public static boolean isEven(int num){
return(num & 1) == 0;
}
}
Here, you don't let the user entry other thing that the first input before the loop.
The retrieval of the input from the user :
int number = input.nextInt();
should be in the loop.
Try that :
int number = 0;
//PART I NEED HELP WITH **************
while (number != -99){
number = input.nextInt();
//Start of if statement to test which to print and call of isEven method
if (isEven(number)) {
System.out.println("Your number is Even!");
}
else
System.out.println("Your number is Odd!");
}
}
You can do like this way ;)
System.out.print("Enter a positive integer value: ");
int number = input.nextInt();
//PART I NEED HELP WITH **************
while (number != -99){
System.out.print("Not good, please enter a new one : ");
number = input.nextInt();
}
//Start of if statement to test which to print and call of isEven method
if (isEven(number)) {
System.out.println("Your number is Even!");
}
else {
System.out.println("Your number is Odd!");
}
So it will ask until you're not writing -99 as you said, but if you're asking for "a positive int" normally nobofy would write -99 :p
End a while loop
You can use a boolean value shouldContinue to control whether the programs should continue to the next input.
if (number != -99) {
shouldContinue = true;
} else {
shouldContinue = false;
}
This can be simplified as follow:
shouldContinue = number != -99 ? true : false;
// or even shorter
shouldContinue = number != -99;
Read the value correctly
But you need to ensure that you input number is reset at each loop execution so that you can read the next number:
while (shouldContinue) {
...
number = input.nextInt();
}
Other enhancements
Do not import unused packages or classes
Use camel case for Java class name
Use comment style /** ... */ for Javadoc
Always try to avoid infinite loop, e.g. use an integer count tries and count down at each loop.
Here's the final answer look like:
import java.util.Scanner;
public class IsOddOrEvenNumber {
public static void main(String []args) {
Scanner input = new Scanner(System.in);
boolean shouldContinue = true;
int tries = 0;
while (shouldContinue && tries < 10) {
try {
System.out.print("Enter a positive integer value: ");
int number = input.nextInt();
if (isEven(number)) {
System.out.println("Your number is Even!");
} else {
System.out.println("Your number is Odd!");
}
shouldContinue = number != -99 ? true : false;
} catch (Exception notNumber) {
System.out.println("Input not a number, try again.");
}
tries--;
}
System.out.println("Game over.");
}
/**
* Begin testing for odd or even in new method
*/
public static boolean isEven(int num){
return (num & 1) == 0;
}
}
Here you are the main method which will be running as long as user is not entering -99;
You should include all your code in the while loop (even try/catch).
public static void main(String []args) {//begin main
Scanner input = new Scanner(System.in);
int number = 0;
//Keep application running as long as the input is not -99
while (number != -99){
//use try/catch method to test for invalid input
try{
//promt user to input a value
System.out.print("Enter a positive integer value: ");
number = input.nextInt();
//Start of if statement to test which to print and call of isEven method
//if the entered number is -99, the following code will skipped.
if(number == -99) continue;
if (isEven(number))
System.out.println("Your number is Even!");
else
System.out.println("Your number is Odd!");
}
//open catch method and print invalid
catch(Exception notNumber) {
System.out.println("Input not a number, try again.");
}
}
}
You could accept this answer, in case it is what you are looking for :)

Guessing game adding a method

I need to add a method to my guessing game that i made a while ago. The method should return the value they enter but should use a loop to require re-entry until one of those two values has been specified.
Also if the user inputs a word and not an int, it should ask for a number. I know that I will need to use a string instead of an int. I'm just having trouble figuring this out. Here is what I have so far:
import java.util.Random;
import java.util.Scanner;
class GuessNumber {
static Random rand = new Random();
static Scanner scan = new Scanner(System.in);
static int number;
public static void main(String[] args) {
playGame();
}
public static void playGame() {
number = rand.nextInt(100) + 1;
System.out.println("Guess the number between 1 and 100");
while (true) {
int guess = scan.nextInt();
if (guess < number) {
System.out.println("Higher!");
} else if (guess > number) {
System.out.println("Lower!");
} else if (guess == number) {
System.out.println("Correct!");
Scanner scan2 = new Scanner(System.in);
System.out.println("do you wanna play again?[Y/N]");
String val = scan2.next();
if (val.equalsIgnoreCase("Y")) {
playGame();
} else {
break;
}
}
}
}
}
There might be a better way to do it but try something along the lines of:
String input = scan.next();
int guess;
try{
guess = Integer.parseInt(input);
//rest of the code inside while(true) loop
}
catch(Exception e){
System.out.println("You need to enter a valid number.");
}
and then for the Y/N validation:
String val = "No";
Scanner scan2 = new Scanner(System.in);
do{
System.out.println("do you wanna play again?[Y/N]");
val = scan2.next();
}
while(!val.equalsIgnoreCase("Y") && !val.equalsIgnoreCase("N"))
if (val.equalsIgnoreCase("Y")) {
playGame();
break;
} else {
break;
}
Reasoning: You will get an error if they do not enter a valid number so you need to catch the error and let them know what is wrong. I like to get input as string and try to convert it to integers. As for the do/while section... Unless they enter Y or N it will keep asking them. Once out of the loop, if the input was "Y" it will call the playGame() again and then break after it finishes (basically whenever the user types n in the next game). If it wasn't "Y" then it had to be "N" and needs to break.
Let me know if this helps. I have the full code that will work but this should be easy enough for you to implement.
When you declare your static variables, put:
static int number, guess;
To declare both numbers at the same time. Then, inside the main loop, do the following:
while (true) {
while (true) {
try {
guess = Integer.parseInt(scan.nextLine());
break;
} catch (Exception e) {
System.out.println("Not a valid number!");
continue;
}
}
//Rest of your if's, else if's, etc
}
I've tested it, and it works for me.
If you need me to I can paste in all the code, but you should be able to just nest that second while loop inside the first, before the if statements, easily enough.

If statement skipping right to else after being called once?

I'm making a simple coin toss game, and I wrote several methods to call and make my main class short and simple. After the game is played once, the first If/Else statement to ask users for input is jumping right to the Else statement without prompting for input.
package cointoss;
import java.util.Random;
import java.util.Scanner;
public class Game {
int money;
int result;
int bet;
Random rn = new Random();
Scanner in = new Scanner(System.in);
String playerPick;
String aResult;
public void setMoney(int a)
{
money = a;
}
public int getMoney()
{
return money;
}
public void getBet()
{
System.out.println("How much would you like to bet?");
bet = in.nextInt();
do{
if(bet > money)
{
System.out.println("You cannot bet more than you have!");
System.out.println("You have bet " + (bet - money) + " too many coins.");
continue;
}
else
System.out.println("You have bet " + bet + " coins.");
}
while(bet > money);
}
public void getInput()
{
System.out.println("Pick Heads or Tails");
playerPick = in.nextLine();
playerPick.toLowerCase();
if(playerPick.contains("heads"))
playerPick ="heads";
else if(playerPick.contains("tails"))
playerPick ="tails";
else
System.out.println("Invalid Selection");
}
public void flipCoin()
{
result = rn.nextInt(2);
if(result == 0)
{
aResult = "heads";
}
else
aResult = "tails";
}
public void checkResult()
{
if(playerPick.equals(aResult))
{
System.out.println("You have won!");
money += bet;
System.out.println("You now have " + money + " coins");
}
else{
System.out.println("You have lost!");
money -= bet;
System.out.println("You now have " + money + " coins");
}
}
}
My Tester Class:
package cointoss;
public class GameTest {
public static void main(String[] args)
{
Game coinToss = new Game();
coinToss.setMoney(100);
while(coinToss.getMoney() > 0)
{
coinToss.getInput();
coinToss.getBet();
coinToss.flipCoin();
coinToss.checkResult();
}
}
}
The method toLowerCase() does not change the contents of the string; String is an immutable class in Java. The toLowerCase() method returns the result. You need to change
playerPick.toLowerCase();
to
playerPick = playerPick.toLowerCase();
Your problem is that you are not reinitializing "in" as a new Scanner every time you run the tester loop. The single scanner reads a line of input and accepts that as the full answer, without acknowledging that there could be further input.
The problem is that when the user enters a line, the input buffer will contain characters followed by a "newline" (end-of-line) character. When you use nextInt, the Scanner will find and skip over an integer. But it won't skip over the end-of-line. So when you next call nextLine in getInput(), it will then find what's left of the previous line, i.e. an empty string, and return that. Some things you'll need to do:
(1) In getBet, add in.nextLine() at the end of the method, to skip past the end-of-line. nextLine will return a string but you can ignore it. See also Scanner issue when using nextLine after nextXXX
(2) getInput needs to have a loop so that if the user enters an invalid input, you go back and ask him to enter a valid string. Otherwise, it will display "Invalid Selection" but then ask for a bet, which isn't what you want.
(3) See the other answers with regard to toLowerCase.
When you use
playerPick.toLowerCase();
It does nothing because the value is not being assigned to anything. In order to change a value of an object you must assign a value to it, as below:
playerPick = Pick.toLowerCase();
This assigns the value, rather than calling an empty method
Hope this helps :)

Categories