I'm trying to write a program that can decide what mechanism a organic reaction will go through using a series of if else and switch statements.
Could you guys help me figure out what I'm doing wrong here? I'm having a problem getting the first if else statement to work. The program runs on my computer(I'm using the BlueJ editor), but when I respond to the first question "Is it soluble in solution?" it defaults to the else statement. The switch statements on the inside of the if else statement works fine by itself.
Can I use switch statements inside if else statements? Is there an easier way to program this?
Could you also explain why it doesn't work, or why another method would be more efficient?
Thanks a ton :)
import java.util.Scanner;
/**
* This program will decide what mechanism a reaction will undergo given information about the reactants.
* I will also include a mechanism to give a rudimentary explanation of the decision making process to
* get the reaction mechanism.
*/
public class mechanism
{
public static void main(String[] args)
{
System.out.println("Hello, this program is designed to figure out what mechanism a reaction will under go.");
//The decision tree will be a series of if-else statements. If I find a better method, I will use that
System.out.println("Is the reactant soluble in the solvent? Answer in yes or no.");
Scanner keyboard = new Scanner(System.in);
String Solubility = keyboard.next(); //Defines if the reactant is soluble in the solvent
String functional = "unassigned";//Defines if the functional roup is primary secondary or tertiary
String Base = "unassigned";//Defines the strength of the base if needed
String Polar = "unassigned";//Defines if the reactant is polarizable
String Solvent = "unassigned"; //Defines if the solvent is protic or aprotic
if ( Solubility == "yes" )
{
System.out.println("Is the functional group attached to a primary, secondary, or tertiary carbon?");
System.out.println(" Answer in p for primary, s for secondary, and t for tertiary.");
keyboard = new Scanner(System.in);
functional = keyboard.next();
switch (functional){
case "p": System.out.println("All unimolecular reactions are ruled out, leaving E2 and Sn2.");
System.out.println("Is the reactant a strong base? Answer in y for yes or n for no");
keyboard = new Scanner(System.in);
Base = keyboard.next();
if (Base == "y" ){
System.out.println("The reaction undergoes E2");
} else{
System.out.println("The reaction undergoes Sn2");
}
break;
case "s": System.out.println("No reactions have been ruled out.");
System.out.println("Is the reactant a strong base? Answer in y or n");
keyboard = new Scanner(System.in);
Base = keyboard.next();
if( Base == "y" ){
System.out.println("yay");
} else {
System.out.println("whatever");
}
break;
case "t": System.out.println("tertiary");
break;
}
}
else{
System.out.println("No reaction will occur");
}
}
}
It's another one of those mistakes that you and I will make once in a while.
Short answer: You can't use == to compare strings!
Long answer:
In your if statements, you are comparing strings with ==. You should never EVER do that. The == compares the memory addresses of the two operands if they are not a primitive. I know you want to check if the characters of the two strings are the same. But two strings with the same characters may not have the same memory address!
What you should do is use the equals method to compare strings, like this:
if (Solubility.equals("yes"))
You can also use the equalsIgnoreCase method. It does what it says on the lid. Remember to change all the other if statements as well!
Moreover, you cannot use switch statements to switch a string. But seeing you didn't recieve any compiler error, I think you are using Java 8.
But if you are not using Java 8, the best way IMO to resolve this is to switch a Character.
char functionalChar = functional.charAt(0);
switch (functionalChar) {
case 'p': // remember to use single quotes!
...
}
Although this is not the biggest problem, it is still worth correcting:
You only need to instantiate Scanner once.
It is perfectly fine to use a switch statement for multiple input types - even within an if statement.
Your problem is that you keep re-initializing the Scanner object.
Once you have initialized the Scanner:
Scanner keyboard = new Scanner(System.in);
Then elsewhere where you would like to receive input, just re-use it:
//keyboard = new Scanner(System.in); // You don't need this line
Base = keyboard.next();
Also, the reason that you are never entering your if statement is the way you are comparing Solubility with'Yes'. For Strings, you should use either equals() or equalsIgnoreCase if case does not matter.
Change the if statement to the following line and your code will work as expected:
if ( Solubility.equalsIgnoreCase("yes"))
Related
So recently I've switched over from python to java and was trying to recreate some of the projects that I made on python in java. The first thing that came to mind was a quiz.
Basically, to create a quiz, I define an answer variable to the answer then use the scanner method in java to detect the user's input. After that, I use an if statement to see if the input equals the answer.
ex.
class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String answer = "dog";
System.out.println("What is a common furry animal");
String input = scan.nextLine( );
if (input.equals(answer))
{
System.out.println("Correct");
}
else
{
System.out.println("Inncorect");
}
}
}
Now that all works but the user doesn't know the exact casing of the answer variable which means if the variable was "dog" and he input "Dog" it would be incorrect. So if it was possible to create an "or" condition to an if statement it would be awesome if someone let me know.
-Thanks
To or any condition in Java, use the conventional || to separate conditions. In your case it would be something like:
if (input.equals(answer) || input.equalsIgnoreCase(answer))
Although you probably just need the Java method equalsIgnoreCase as the lone condition in the first place.
So I only VERY recently got into what people call "coding", especially Java.
Here's what I've made with my teeny tiny hands. Basically, you input a year, and it converts it into centuries:
import java.util.Scanner;
public class somemaths {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
System.out.println("Please insert a year:");
int str = sc.nextInt();
int calc1 = (str+99)/100;
if (str>0) {
System.out.print("This is the " + calc1);
int unity = calc1%10;
if (unity>=4)
System.out.print("th century. I'm sure of it!");
if (unity==3)
System.out.print("rd century. I'm sure of it!");
if (unity==2)
System.out.print("nd century. I'm sure of it!");
if (unity==1)
System.out.print("st century. I'm sure of it!");
}
else
System.out.print("Please don't input negative numbers :c");
}
}
Questions are:
1) Eclipse tells me that 'sc' is never closed. What is this about?
2) Is the code itself okay-ish?
3) This is probably the noobiest question I'll ever ask, but how can I create a window with a dialog and a text box (as in, a box where you can input some numbers), and then show the result in another dialog window? I've vaguely heard of JOptionPane.showMessageDialog before, but I just don't know how to apply it here.
Thanks a bunch!
You should try and focus your questions a bit more on Stack Overflow to get better answers. Asking three questions in one is expecting a lot. Also your second question is better suited to code review stack exchange. Your third question is also quite broad.
Question 1:
A Scanner object needs to be closed once you're finished with it. Call sc.close()
at the end of your program to do this.
Question 2:
Your variable names aren't as good as they could be. If you want to ensure your code is 'complete', you should look into unit testing and write a comprehensive suite of tests to ensure your code covers all cases. E.g. you will have a test case which takes the date 1980, and ensures the correct output of the 20th century is given.
Question 3:
You should look into Java Swing for creating a simple GUI. There are lots of tutorials out there.
sc is never closed
Since Scanners use input streams, they will open the stream to use them. They don't automatically close so to ensure safe and clean termination, after the last input from sc, call sc.close(). Technically since it's System.in nothing bad happens if you don't but you should close it anyway.
Is the code itself simple/complete enough?
Go to Code Review if your code works and you want to make it better in terms of efficiency, et cetera. However, I will tell you that you should probably be doing something like this:
if (str > 0) {
System.out.print("This is the " + calc1);
int unity = calc1%10;
String century;
if (unity == 1) century = "st";
else if (unity == 2) century = "nd";
else if (unity == 3) century = "rd";
else century = "th";
System.out.print(century + " century. I'm sure of it!");
else
System.out.print("Please don't input negative numbers :c");
}
JOptionPane#showMessageDialog
Official Documentation of javax.swing.JOptionPane
For your purpose, you probably want:
JOptionPane.showMessageDialog(
null, // This is the parent frame; if unspecified, it will make a new window
"the output goes here", // This is the output you want to show to the user
"some title" // You can specify the title
// This will use the defaults to display a notification (not an error or a confirm) with the default icon. Check the docs for more information
)
I've modified your java code to clean it up a bit. I'll provide some explanations as to what I changed an why I did so.
sc.close();
Your first problem is caused by not properly calling the close() method of the scanner object named sc. You can find some other helpful posts on stack overflow (such as this one) on why this is essential, but you will need to understand how your programs utilize memory and how the Scanner object in particular utilizes it. For now, I would just always make sure that you close all scanner objects once they are done being utilized.
if (unity>=4)
....
if (unity==3)
....
if (unity ==2)
....
Instead of using an if statement for each case of what the unity variable equals, you should be using either if else statements or a switch statement. In your program, you do not want any possibility of the other if statements executing. It might not seem obvious in your example, but if this type of code was within a much larger project, you or someone else could vary easily modify the unity variable in between one of your if statements and change the behavior of your output. This is a good practice to get into as you are learning to program, and is important once you start working on larger projects. Always ask the question, "What if 5 years from now someone looked at my code?" :) I would also try to follow a consistent "coding standard". Be consistent in your spacing and when to use curly braces. This makes your code much more readable.
import java.util.Scanner;
public class somemaths {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please insert a year:");
int str = sc.nextInt();
sc.close();
int calc1 = (str+99)/100;
if (str>0) {
System.out.print("This is the " + calc1);
int unity = calc1%10;
if (unity>=4){
System.out.print("th century. I'm sure of it!");
} else if (unity==3){
System.out.print("rd century. I'm sure of it!");
} else if (unity==2){
System.out.print("nd century. I'm sure of it!");
} else if (unity==1) {
System.out.print("st century. I'm sure of it!");
} else {
System.out.print("Please don't input negative numbers :c");
}
}
}
}
Ok, so the code below loops wonderfully. It can loop as long as it wants to. The thing is though, I can never get out of the loop. I'm trying to build a text-adventure, by the way for those wondering, but I really need to get out of this loop.
System.out.println("\n\nWelcome, " + name + "! To proceed, enter your class of fighter.");
System.out.println();
boolean x = true;
while (x){
//information print statements
System.out.println("What will your class be? ");
String heroclass = scan.nextLine();
heroclass.toLowerCase();
String A;
switch (heroclass)
{
case "slayer": A = "You have selected the Slayer class.";
break;
case "blader": A = "You have selected the Blader class.";
break;
case "bandit": A = "You have selected the Bandit class.";
break;
case "wizard": A = "You have selected the Wizard class.";
break;
default: A = "Invalid entry.";
break;
}
String killloop = A;
if (killloop.charAt(0) == 'Y'){
x = false;
}
}
You need to assign heroclass.toLowerCase(); to the original value of heroclass:
heroclass = heroclass.toLowerCase();
If you do not do this, the lowercase version of heroclass is not saved.
heroclass is of String type. String is immutable type of object, so you can't update this string. heroclass.toLowerCase() just return another String object with lower cased characters, so you need to reassign this string result to this variable:
heroclass = heroclass.toLowerCase();
Put your loop in a labeled block:
myblock: {
while (true) {
//code
heroclass = heroclass.toLowerCase();
switch(heroclass)
{
case "slayer": A = "text";
break myblock;
//repeat with other cases
}
}
}
//goes to here when you say "break myblock;"
What you're doing is basically assigning the label myblock to the entire loop. When you say break myblock it breaks out of the entire section inside of the brackets.
NOTE: I would recommend this solution over the others because it doesn't depend on the magic value assigned by the switch; it works no matter what it is.
Also, I've added the part to make it case insensitive. Sorry about the confusion!
Although coding wombat is right, i'm not a big fan of the way you did things here. A loop around your whole program like this isn't good practice. It's super clunky and will lead to many problems, not to mention you're making things more complicated for yourself. Ideally you'd want to put this class selection part of the program inside a method. Then if the user's input is invalid, simply call back the method recursively until you get correct input.
Ex.
case A: do this...
case B: do this...
case C: System.out.println("Not a valid input);, classSelector();
Also, when you use OOP you have the benefit of storing all the player's attributes inside an object, as well as making methods that manipulates those attributes. It will make your code a lot cleaner and easier to work with.
Ex.
Player1.heal(10);
I have no code to paste since all I have is a template of my methods to be used. Hopefully this isn't too broad because I've looked all over and haven't received the answer I'm needing.
Many have seen or heard of a "Magic 8 Ball" program. A user asks a question, and they receive a random answer in return. I could have written the code easily with one method, but now we've delved into using multiple methods and I'm missing a piece of the puzzle.
The rules of this program:
1) I have to create at least three methods: the main, an input method, and an output method.
2) I have to use a switch statement for the random answers.
3) I have to use a while loop (or a do-while) to prompt the user to either ask another question, or quit.
I think my only problem lies in where to place each piece of the code. I'm going to need to call a Scanner. That's no big deal. I know how to do the switch statement. I know how to randomize the output. I'm most likely going to use a boolean for the keep going/quit part. But where do I actually PLACE the scanner? The boolean? In the main? In an input method? What about the processing section for the randomization? Are all my variables declared in the main so they spread throughout?
I hope my question makes sense.
Creating Scanner once either in main, or in the constructor as a class level object will be much cheaper than creating every time you call the input method. If created at class level it can be used directly in input method, otherwise if it is created in main method it can be passed as an argument to the input method.
Boolean can be in the input method because you are directly comparing the input and you have no more use for it.
When you have an object, especially an expensive one, it is better to create it only once wherever applicable, or create it as few times as possible.
Excuse my sloppy code, and ignore the case names. They are temporary since I will be renaming them. I tried every scenario after compiling. I asked a question, it answered, and it asked if I wanted to ask another. I asked another, it repeated the prompt. I answered "n", and it said "Thanks for playing. Goodbye", and stopped running. Here is my code. Problem solved.
import java.util.Scanner;
public class MagicBall {
public static void main(String[] args) {
int random = 0;
boolean playAgain = true;
while (playAgain) {
askAnother(random);
}//end while
}//end main
public static void askAnother(int r) {
System.out.print("Hello! What is your question? ");
Scanner input = new Scanner(System.in);
String question = input.nextLine();
String yes_or_no;
String next_question;
randomAnswer(r);
boolean playAgain = true;
while(playAgain) {
System.out.println("Would you like to ask another question? Y to ask, N to quit.");
yes_or_no = input.nextLine();
if (yes_or_no.equalsIgnoreCase("Y")) {
System.out.println("What is your next question?");
next_question = input.nextLine();
randomAnswer(r);
}//end if
else if (yes_or_no.equalsIgnoreCase("N")) {
playAgain = false;
System.out.println("Thanks for playing. Goodbye.");
System.exit(0);
}
else {
System.out.println("Invalid Input. Please enter Y or N.");
continue;
}//end else
}//end while
}//end input method
public static int randomAnswer(int r1) {
r1 = (int)(Math.random() * 9);
switch(r1) {
case 0: System.out.println("Yes"); break;
case 1: System.out.println("Yes1"); break;
case 2: System.out.println("Yes2"); break;
case 3: System.out.println("Neutral"); break;
case 4: System.out.println("Neutral1"); break;
case 5: System.out.println("Neutral2"); break;
case 6: System.out.println("No"); break;
case 7: System.out.println("No1"); break;
case 8: System.out.println("No2"); break;
}//end switch
return r1;
}//end output method
}//end MagicBall class
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 8 years ago.
So, normally for detecting user input, I use int and double variable types.
Example:
Scanner in = new Scanner(System.in);
int selection;
System.out.println("Welcome to RPG! (prototype name)\nIn this game, you do stuff.\nChoose a class:\n1. Soldier\n2. Knight\n3. Paladin\n4. Heavy");
selection = in.nextInt();
if(selection == 1){
System.out.print("you are a soldier");
}
else{
System.out.print(selection);
}
}
This technique usually works fine for me, but I noticed that if the user inputs a letter into the int variable, the game will crash because integers can't store letters. (right?) So I tried using a String variable in its place, like this:
Scanner in = new Scanner(System.in);
String selection;
System.out.println("Welcome to RPG! (prototype name)\nIn this game, you do stuff.\nChoose a class:\n1. Soldier\n2. Knight\n3. Paladin\n4. Heavy");
selection = in.next();
if(selection == "1"){
System.out.print("you are a soldier");
}
else{
System.out.print(selection);
}
}
This seemed to work at first, but as you can see, I have it set so that if the variable "selection" is equal to 1, that it will print "you are a soldier", yet this did not work, instead it printed out the "selection" variables value (1). Did I do something wrong or should I use a different type of variable?
you can use something la this :
try{
int type = Integer.parseInt(selection);
switch(type){
case 1:{
//do soldier stuff
}
case 2:{
// do knight stuff
}
default:{
//do other stuff
}
}
}catch(NumberFormatException exc ){
System.out.println(selection + "is not a number, try again!!!");
}
selection == "1"
Compare strings with String#equals.
"1".equals(selection)
There are lots of ways to do this. A quick point I'd like to make is if you're comparing strings you should use:
var.equals("string");
Since you're only taking one character you could use a character in which case the correct syntax would be:
var == '1'
If you want to be fancy you can do a try catch around your read statement and just read in an string and parse it to an integer, but that is a bit more advanced.
change selection == "1" to "1".equals(selection)
use .equals() for comparing the string "1" and selection and read this A simple explanation would be
x == y returns true only when both x and y refer to same object which is not in your case. equals check if contents are equal meaning if contents of memory location that x and y are referring to are equal or not.