Cannot quit this loop? - java

I wrote a simple guessing game which uses while loop.
If user types any word with an initial of "y", the game will run again, but if user types any other word, the game will quit and gives out the report.
public static void loopcalc(Scanner console) {
int totalRounds = 0, totalGuesses = 0, best = 1000000;
boolean want = true;
while (want = true) {
int eachguess = playOneGame(console);
totalRounds++;
totalGuesses += eachguess;
System.out.println("Do you want to play again?");
String input = console.next();
if (input.toLowerCase().charAt(0) == 'y') {
want = true;
} else {
want = false;
}
best = Math.min(eachguess, best);
}
report(console, totalGuesses, totalRounds, best);
}
Sorry I do not know how to type codes correctly.

You wrote:
while(want = true) {
You surely want to check if want is true. So write instead:
while(want == true) {
Or, better:
while(want) {
In Java, = is an operator which assigns a value to a variable. It returns also the value. So, when you type wanted = true, you:
Set want to true
Return true
Here, while returns gets true, and continue the loop infinitely.
Ps : this is a very frequent issue. In 2003, a famous attempt to insert a backdoor in the Linux kernel used this feature (C language has it too).

This is your updated answer.
public static void loopcalc(Scanner console) {
int totalRounds = 0, totalGuesses = 0, best = 1000000;
boolean want = true;
while (want) {
int eachguess = playOneGame(console);
totalRounds++;
totalGuesses += eachguess;
System.out.println("Do you want to play again?");
String input = console.next();
if (input.toLowerCase().charAt(0) == 'y') {
want = true;
} else {
want = false;
}
best = Math.min(eachguess, best);
}
report(console, totalGuesses, totalRounds, best);
}
You can also try following approach and get rid of want variable:
public static void loopcalc(Scanner console) {
int totalRounds = 0, totalGuesses = 0, best = 1000000;
boolean want = true;
while (true) {
int eachguess = playOneGame(console);
totalRounds++;
totalGuesses += eachguess;
System.out.println("Do you want to play again?");
String input = console.next();
if (input.toLowerCase().charAt(0) == 'n') {
break;
}
best = Math.min(eachguess, best);
}
report(console, totalGuesses, totalRounds, best);
}

= in want = true is an assignment operator. What you should try instead is the equality == operator.
while(want == true) or while(want)

Related

Java: stop a Constructor when System.in reads in a specific String

I have some trouble with a Constructor in Java. The Problem is that I have to read-in some input from the Systme.in in the Constructor to initialize some final variable. Now i have to quit the Program when the input is "quit". For this, it's not possible to use Systme.exit() or Runtime.exit().
I have two Ideas for this Problem, but both have some Problems.
Solution 1:
One Idea would be to set a variable to true when the input is "quit" and check the variable after each Question, but that wouldn't be a nice Code.
public Game() {
input = new Scanner(System.in);
this.gameFinished = false;
this.moveNumber = 0;
printLogo();
//Get Starting Information TODO Magic Numbers
this.playerCount = getIntegerWithCondition(1, "Question 1?");
//check if gameFinished = true
getPlayerNames();
//check if gameFinished = true
this.startGold = getIntegerWithCondition(0, "Question 2?");
//check if gameFinished = true
this.winGold = getIntegerWithCondition(1, "Question 3?");
//check if gameFinished = true
this.shuffleSeed = getIntegerWithCondition(0, "Question 4?");
//check if gameFinished = true
}
private int getIntegerWithCondition(int condition, String question) {
System.out.println(question);
boolean inputValid = false;
int playerValue = 0;
while (!inputValid) {
String playerInput = input.nextLine();
if (playerInput.equals("quit")) {
this.gameFinished = true;
break;
}
if (playerInput.matches("-*[0-9]+")) {
try {
playerValue = Integer.parseInt(playerInput);
if (playerValue > condition) {
inputValid = true;
} else {
System.out.println(String.format("Error: Your Input must be greater than %d!", condition));
}
} catch (NumberFormatException e) {
//TODO
}
} else {
System.out.println("Error: Your Input is not a Number!");
}
}
return playerValue;
}
private void getPlayerNames() {
for (int i = 1; i <= this.playerCount; i++) {
System.out.println(String.format("Enter the name of player %d:", i));
String userInput = null;
Boolean inputValid = false;
while (!inputValid) {
userInput = input.nextLine();
if (userInput.equals("quit")) {
this.gameFinished = true;
break;
}
if (userInput.matches("[A-Za-z]+")) {
inputValid = true;
} else {
System.out.println("Error: Your input can only contain characters from a to z!");
}
}
players.add(new Player(userInput));
}
}
Solution 2:
The other Idea I had would be to throw an exception in those two methods and catch them in the constructor. For this I would have to surround those Questions with a try and catch block, but then I have the Problem that the final variables might not be initialized and because they are final I can't initialize them before.
Does anybody have an Idea how to solve this problem with a clean code?

Problem with Class scope, how should I resolve this?

I started my first java project and I get stuck in class scope. I cant initiate below code:
if (guessAttemts = MaxGuesses) {
System.out.println("Sorry you used all your nine chances. Game Over.)
I will be appreciate if someone will help me to clarify what I doing wrong with that code: This NewGame class look like below.
class NewGame {
GuessAttempts GuessAttempts = new GuessAttempts();
private String WordToGuess;
private String CorrectGuesses;
private String misses;
int guessAttempts;
int MAX_Guesses = 9;
public NewGame(String WordToGuess) {
this.WordToGuess = WordToGuess;
CorrectGuesses = "";
misses = "";
guessAttempts = 0;
}
public boolean UserGuessing(char letter) {
boolean isHit = WordToGuess.indexOf(letter) != -1;
if (isHit) {
CorrectGuesses += letter;
} else {
misses += letter;
}
guessAttempts =+ 1;
return isHit;
}
if (guessAttemts = MaxGuesses) {
System.out.println("Sorry you used all your nine chances. Game Over.");
}
}
To compare to values, you should use ==.
That means that your if-statement should look so:
if (guessAttemts == MaxGuesses) {
System.out.println("Sorry you used all your nine chances. Game Over.");
}

Java parse a string using a scanner, and using the parsed string as input in an if else statement

Hello fellow programmers! I am a Java beginner and I need some help.
I have a program that I want to make the Turtle move using prefabricated instructions in a string called "rule". I want that rule to be parsed into a readable format for an if-else statement. The if-else statement will then read every character in the parsed "rule", and make the Turtle move accordingly to each condition.
I have ran into some issues with the program, it parses (I think so) and displays the rule, but there is no movement from the turtle. I believe it has something to do with the if-else statement. Please help!
import java.awt.*;
import java.util.Scanner;
class FractalEngine
{
World worldObj = new World();
Turtle m = new Turtle(200, 200, worldObj);
Scanner in = new Scanner(System.in);
FractalEngine()
{
//String rule = "F-F+F+F-FQ";
String rule = "F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-FQ";
//String rule = "F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-F-F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-F+F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-F+F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-F-F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-FQ";
m.setHeading(0);
Scanner scanner = new Scanner(rule);
System.out.println();
System.out.println("Fractal Rule: ");
System.out.println(scanner.nextLine());
System.out.println();
// it prints it to the terminal, but no Turtle movement. Am I using the right parsing method?
do
{
Scanner scanRule = new Scanner(rule);
scanRule.nextLine();
if(rule.equalsIgnoreCase("F"))
m.forward(25);
else if(rule.equals("-"))
m.turnLeft();
else if(rule.equals("+"))
m.turnRight();
else
rule = "Q";
}
while(!rule.equalsIgnoreCase("Q"));
System.out.println("Fractal construction terminated.");
}
}
public class FractalConstructor
{
public static void main(String[] args)
{
FractalEngine fe = new FractalEngine();
}
}
I tried that script, and it works for me it prints each action depends on the command , So I think the problem is in your functions I mean (m.forward(), m.turnRight()...)
public class Main {
public static void main(String[] args)
{
String rule = "F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-FQ";
int i = 0 ;
char[] cmds = rule.toCharArray();
do
{
if(cmds[i] == 'F') {
System.out.println("Foward");
}
else if(cmds[i] == '-') {
System.out.println("Left");
}
else if(cmds[i] == '+') {
System.out.println("Right");
}
else // it's surely "Q"
break ;
i++ ;
}
while(true);
System.out.println("Fractal construction terminated.");
}
}
I think you have a lot of code logic issues, you may change your do while loop with code bellow
boolean done = false;
String line ;
while((line = scanner.nextLine()) != null && !done)
{
for (int i = 0; i< rule.length(); i++) {
if(rule.charAt(i) == 'F')
m.forward(25);
else if(rule.charAt(i) == '-')
m.turnLeft();
else if(rule.charAt(i) == '+' )
m.turnRight();
else{
done = true;
break;
}
}
}

How do I check if a class' return of a method equals null?

In my program, I have a while loop that will display a list of shops and asks for an input, which corresponds with the shop ID. If the user enters an integer outside the array of shops, created with a Shop class, it will exit the loop and continue. Inside this loop is another while loop which calls the sellItem method of my Shop class below:
public Item sellItem()
{
displayItems();
int indexID = Shop.getInput();
if (indexID <= -1 || indexID >= wares.length)
{
System.out.println("Null"); // Testing purposes
return null;
}
else
{
return wares[indexID];
}
}
private void displayItems()
{
System.out.println("Name\t\t\t\tWeight\t\t\t\tPrice");
System.out.println("0. Return to Shops");
for(int i = 0; i < wares.length; i++)
{
System.out.print(i + 1 + ". ");
System.out.println(wares[i].getName() + "\t\t\t\t" + wares[i].getWeight() + "\t\t\t\t" + wares[i].getPrice());
}
}
private static int getInput()
{
Scanner scanInput = new Scanner(System.in);
int itemID = scanInput.nextInt();
int indexID = itemID - 1;
return indexID;
}
The while loop in my main class method is as follows:
boolean exitAllShops = true;
while(exitAllShops)
{
System.out.println("Where would you like to go?\nEnter the number which corresponds with the shop.\n1. Pete's Produce\n2. Moore's Meats\n3. Howards Hunting\n4. Foster's Farming\n5. Leighton's Liquor\n6. Carter's Clothing\n7. Hill's Household Products\n8. Lewis' Livery, Animals, and Wagon supplies\n9. Dr. Miller's Medicine\n10. Leave Shops (YOU WILL NOT BE ABLE TO RETURN)");
int shopInput = scan.nextInt();
if(shopInput >= 1 && shopInput <= allShops.length)
{
boolean leaveShop = true;
while(leaveShop)
{
allShops[shopInput - 1].sellItem();
if(allShops == null)
{
System.out.println("still null"); // Testing purposes
leaveShop = false;
}
}
}
else
{
System.out.println("Are you sure you want to leave?\n1. Yes\n2. No");
int confirm = scan.nextInt();
if(confirm == 1)
{
exitAllShops = false;
}
}
The problem is here:
boolean leaveShop = true;
while(leaveShop)
{
allShops[shopInput - 1].sellItem();
if(allShops == null)
{
System.out.println("still null"); // Testing purposes
leaveShop = false;
}
}
No matter what I do, I can't get "still null" to print to confirm that I'm correctly calling the return statement of the method sellItem of the class Shop. What am I doing wrong?
After calling allShops[...].sellItem(), allShops is still a valid array reference -- there's no way it could be null! You probably want to test the return value from sellItem:
if(allShops[shopInput-1].sellItem() == null)

Java: Implementing a new thread, now my code executes twice

I asked another question the other day about getting keyboard input while within a swing GUI--actually MCR input. One user found a low-level keyboard hook someone wrote. Very cool, and it mostly works. I had to learn some new things to implement it (always happy to do that), and tbh I may not be fully understanding what's going on.
Thing is, and I'll post the code below, it now runs through a while loop (while success == false, in CardRead.java) twice when I implement the thread for the keyboard hook. If I hard code sample data it only runs through once. If I delete the keyboard hook and use a normal Scanner.nextLine() (which means I have to click in the console to provide input to the application), it only runs through once. Start a new thread with an observer for keyboard input? Twice. I don't understand why, or how to fix it. I'd be happy with just understanding exactly what's going on-- if one of you all show me how to fix it, I'll be ecstatic.
Here's the code:
CardRead.java
public class CardRead {
public static String raw_card_data;
int readcount = 1;
String[] tracks = new String[2];
String[] tracks_final = new String[2];
public static void main()
{
// This doesn't happen until after card is swiped, dunno why.
//GUI.outputArea.setText(GUI.outputArea.getText() + "\n\n Scan card \n");
boolean success = false;
while (success == false)
{
//raw_card_data = "%test?;testing?"; // <-- using this, runs thru once
// using THIS, runs through twice.
// create an event source - reads from stdin
final KB_EventSource evSrc = new KB_EventSource();
// create an observer
final KB_RespHandler respHandler = new KB_RespHandler();
// subscribe the observer to the event source
evSrc.addObserver( respHandler );
// starts the event thread
Thread kb_thread = new Thread(evSrc);
kb_thread.start();
// sleep until card swiped
while (raw_card_data == null)
{
try
{
Thread.sleep(1000);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
System.out.println(raw_card_data);
// Tokenize raw_card_data
StringTokenizer tokenizer = new StringTokenizer(raw_card_data, "?");
int i = 0;
do
{
tracks[i] = tokenizer.nextToken();
System.out.println(i + ": " + tracks[i]);
i++;
}
while (tokenizer.hasMoreTokens());
//System.out.println(track1);
//System.out.println(track2);
tracks_final[0] = tracks[0].substring(1,tracks[0].length());
if (tracks[1] != null)
{
tracks_final[1] = tracks[1].substring(1,tracks[1].length());
}
if ( (readcount <= 5) && ( (tracks_final[0].equals("E") || tracks_final[0].equals(null) ) || (tracks_final[1].equals("E") || tracks_final[1].equals(null)) ) )
{
GUI.notout.setText("Card Read Unsuccessful. Scan Again.");
GUI.outputArea.setText(GUI.outputArea.getText() + "Card read unsuccessful. Scan again. \n");
success = false;
readcount++;
}
else if (readcount <= 5)
{
GUI.notout.setText("Card Successfully Read");
GUI.outputArea.setText(GUI.outputArea.getText() + "\n Success! \n");
GUI.outputArea.setText(GUI.outputArea.getText() + "Track 1 = " + tracks_final[0] + "\n");
GUI.outputArea.setText(GUI.outputArea.getText() + "Track 2 = " + tracks_final[1] + "\n");
success = true;
} // end if else chain
} // end while success == false
} // end public void main
} // end class CardRead
KB_RespHandler.java
import java.util.Observable;
import java.util.Observer;
public class KB_RespHandler implements Observer
{
private String resp;
public void update (Observable obj, Object arg)
{
if (arg instanceof String)
{
resp = (String) arg;
CardRead.raw_card_data = resp;
}
}
}
KB_EventSource.java
import de.ksquared.system.keyboard.*;
import java.util.Observable;
public class KB_EventSource extends Observable implements Runnable
{
public static String temp = "";
public static String output = "";
public void run()
{
new GlobalKeyListener().addKeyListener(new KeyAdapter()
{
#Override public void keyPressed(KeyEvent event)
{
switch(event.getVirtualKeyCode())
{
case KeyEvent.VK_0:
if (event.isShiftPressed() == true)
temp += ")";
else if (event.isShiftPressed() == false)
temp += "0";
break;
case KeyEvent.VK_1:
if (event.isShiftPressed() == true)
temp += "!";
else if (event.isShiftPressed() == false)
temp += "1";
break;
/*insert processing for other keys here*/
case KeyEvent.VK_SPACE:
if (event.isShiftPressed() == true)
temp += " ";
else if (event.isShiftPressed() == false)
temp += " ";
break;
case KeyEvent.VK_RETURN:
/*if (event.isShiftPressed() == true)
temp += "\n";
else if (event.isShiftPressed() == false)
temp += "\n";*/
setChanged();
notifyObservers(temp);
//clearChanged();
break;
} // end switch (event.getVirtualKeyCode())*/
} // end public void keyPressed
});
while(true)
try
{
Thread.sleep(100);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
So, I don't know what's going on. I was thinking maybe I need to stop the thread kb_thread after receiving input, but I can't find any way to do that. thread.stop() and thread.destroy() are deprecated and Eclipse and Google tell me not to use them. And that might not even be what I need to do anyway.
The comment in "CardRead.java" says "which upon success will change success = true".
Does this mean that it might fail, so it won't change success?
If that's true then raw_card_data would still be non-null, and it would try again.
I'm assuming that you resetting raw_card_data to null again at some point.
On another point, this:
if (event.isShiftPressed() == true)
temp += ")";
else if (event.isShiftPressed() == false)
temp += "0";
can be simplified to:
if (event.isShiftPressed())
temp += ")";
else
temp += "0";

Categories