This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
I'd like to preface this with that I've only started learning Java earlier at the beginning of this year, so I appreciate all your help! I'm currently working on a Shadowrun (3rd Edition) program that turns Decking into a Command Prompt. I'd like the user to be able to enter Blue, Green, Orange, or Red to start with a Host Color, but also give a Random option as well.
Scanner user_input = new Scanner(System.in);
String HostColor;
System.out.println("What is the color of the Host? (Blue, Green, Orange, Red, Random)"); //Get the Host's Color
HostColor = user_input.nextLine();
Random rand = new Random();
while ((!HostColor.equals("Blue")) || (!HostColor.equals("Green")) || (!HostColor.equals("Orange")) || (!HostColor.equals("Red"))) {
if (HostColor.equals("Blue")) {
...
break;
}
else if (HostColor.equals("Green")) {
...
break;
}
else if (HostColor.equals("Orange")) {
...
break;
}
else if (HostColor.equals("Red")) {
...
break;
}
else if (HostColor.equals("Random")) {
int RandomHost = (rand.nextInt(4));
if (RandomHost == 0) {
HostColor.equals("Blue");
...
break;
}
else if (RandomHost == 1) {
HostColor.equals("Green");
...
break;
}
else if (RandomHost == 2) {
HostColor.equals("Orange");
...
break;
}
else if (RandomHost == 3) {
HostColor.equals("Red");
...
break;
}
}
else {
System.out.println("Invalid Command");
System.out.println("What is the color of the Host? (Blue, Green, Orange, Red, Random)");
HostColor = user_input.nextLine();
}
}
System.out.println("Host is a " + HostColor + "...");
The code works just fine when specifying a particular color. However, when choosing the Random option and then printing the overall results, rather than printing one of the four colors, my code says the HostColor is Random. I appreciate any input to help solve this problem - thanks in advance!
HostColor.equals() is not assignment, equals() is comparision method which checks whether two strings are equals or not in this case.
else if (HostColor.equals("Random")) {
int RandomHost = (rand.nextInt(4));
if (RandomHost == 0) {
HostColor = "Blue";
}
else if (RandomHost == 1) {
HostColor = "Green";
}
else if (RandomHost == 2) {
HostColor = "Orange";
}
else if (RandomHost == 3) {
HostColor = "Red" ;
}
}
I would recommend you to use Switch statements for comparing string instead of if-elseif. Switch appears to be more clean way of writing such conditional codes.
Related
I am trying to make a small game:
There are 2 heroes you can choose: 1 Warrior and 2 Mage.
Next, you should choose how to travel: 1 by Horse 2 Teleportation (available to Mage only).
Finally, choose a weapon: 1 Sword 2 Staff (*Mage can only use Staff; Warrior can use both).
I created a loop for my first question (choosing a hero) so that if the user enters something else aside from 1 or 2, the program will repeat the question ("Choose your hero: ...). I need the same done for my second and third question (especially since there are some restrictions, e. g. if the user chose Warrior, he can't choose Teleportation as his travel option).
public static void main(String[] args) {
int hero, travel, weapon;
Scanner scan = new Scanner(System.in);
loop:
while (true) {
System.out.println("Choose your hero: 1 for Warrior, 2 for Mage");
hero = scan.nextInt();
switch (hero) {
case 1:
System.out.println("Choose your travel option: 1 for Horse; 2 for Teleportation");
travel = scan.nextInt();
break loop;
case 2:
System.out.println("Choose your travel option: 1 for Horse; 2 for Teleportation");
travel = scan.nextInt();
break loop;
default:
break;
}
}
}
I don't know how to use a loop inside another loop properly. I've tried several options but it always returns an error.
It is always a good idea to split things up, instead of making nested loops. Here is a simple way to split the program in 3 methods, each one dealing with a choice.
Hero choice: Offer both choices and loop until given a valid answer. Then return the answer
private static int queryHero() {
Scanner scan = new Scanner(System.in);
int hero;
while (true) {
System.out.println("Choose your hero: 1 for Warrior, 2 for Mage");
hero = scan.nextInt();
if(hero == 1 || hero == 2) {
break;
} else {
System.out.println(hero + " is not a valid choice");
}
}
return hero;
}
Travel option choice: Offer choices depending on the chosen hero and loop until given a valid answer. Then return the answer
private static int queryTravelOptionForHero(int hero) {
Scanner scan = new Scanner(System.in);
int travelOption;
while (true) {
if (hero == 1) {
System.out.println("Choose your travel option: 1 for Horse");
travelOption = scan.nextInt();
if (travelOption == 1) {
break;
} else {
System.out.println(travelOption + " is not a valid choice");
}
} else if (hero == 2) {
System.out.println("Choose your travel option: 1 for Horse; 2 for Teleportation");
travelOption = scan.nextInt();
if (travelOption == 1 || travelOption == 2) {
break;
} else {
System.out.println(travelOption + " is not a valid choice");
}
}
}
return travelOption;
}
Weapon choice: Offer choices depending on the chosen hero and loop until given a valid answer. Then return the answer
private static int queryWeaponForHero(int hero) {
Scanner scan = new Scanner(System.in);
int weapon;
while (true) {
if(hero == 1) {
System.out.println("Choose your weapon: 1 for Sword; 2 for Staff");
weapon = scan.nextInt();
if (weapon == 1 || weapon == 2) {
break;
} else {
System.out.println(weapon + " is not a valid choice");
}
} else if(hero == 2) {
System.out.println("Choose your weapon: 2 for Staff");
weapon = scan.nextInt();
if(weapon == 2) {
break;
}else {
System.out.println(weapon + " is not a valid choice");
}
}
}
return weapon;
}
Then in your main:
int hero = queryHero();
int travelOption = queryTravelOptionForHero(hero);
int weapon = queryWeaponForHero(hero);
System.out.println("hero: " + hero);
System.out.println("travelOption: " + travelOption);
System.out.println("weapon: " + weapon);
Note: I am not sure if you know about them, but there are ways to make this code nicer using enums and Lists
Your flow can be written as a simple procedural code. As so, I would write it in the most simple form I can - at least as a start.
There is no real justification for using switch labels and loops inside loops
Just write 3 simple loops, one after another - It will be simple to read, understand and debug.
I dont want to write the code for you, it is not the purpose of this site, but here's a Pseudo code:
Loop 1 (selecting heroes)
If(heroes != Warrior)
Loop 2 (selecting travel)
else travel=Horse
Loop 3 (selecing weapon)
Like the comments suggest i would not go with loops inside loops. Instead you should assign the variables one at the time. I have written a helper method selectVariable(String description, String varOne, String varTwo) that you can use to assign variables and give you a start for your story game. You could expand it if you want to give the user more choices. Also don't give the use the illusion a choice can be made, if there is no choice in that situation.
Here is the code that should do what you want:
import java.util.Scanner;
public class Story {
static Scanner scan = new Scanner(System.in);
public static void main(String[] args) {
int hero = chooseHero();
int travel = chooseTravel(hero);
int weapon = chooseWeapon(hero);
//For printing purposes give your choice their respective string name again.
String heroDesc = hero == 1 ? "Warrior" : "Mage";
String travelDesc = travel == 1 ? "Horse" : "Teleportation";
String weaponDesc = weapon == 1 ? "Sword" : "Staff";
System.out.printf("you are a %s, traveling by %s, wielding a %s" + System.lineSeparator(), heroDesc, travelDesc, weaponDesc);
}
private static int chooseHero() {
return selectVariable("choose your hero class", "warrior", "mage");
}
private static int chooseTravel(int hero) {
if (hero == 1) { // if the user has no choice don't give the illusion a choice can be made
System.out.println("you are a Warrior you will travel by horse");
return 1;
} else {
return selectVariable("choose your way of travel", "by horse", "teleportation");
}
}
private static int chooseWeapon(int hero) {
if (hero == 2) {
System.out.println("you are a mage you will wield a staff");
return 2;
} else {
return selectVariable("choose your weapon", "sword", "staff");
}
}
//you can reuse this method to also assign other traits to your story
private static int selectVariable(String description, String varOne, String varTwo) {
int var;
do {
System.out.printf("%s: 1 %s, 2 for %s" + System.lineSeparator(), description, varOne, varTwo);
var = scan.nextInt();
switch (var) {
case 1:
System.out.printf("you have chosen %s" + System.lineSeparator(), varOne);
return var;
case 2:
System.out.printf("you have chosen %s" + System.lineSeparator(), varTwo);
return var;
default:
System.out.println(var + " is an invalid choice");
}
}
while (true);
}
}
So I have an arrayList with rooms and im getting the user to put in the room they are looking for, im capturing this as a string and then trying to use instanceOf to match it up with the names of the java classes but cant do this due to comparing a string to a java class.
Also I am capturing there answer in a switch statement to make sure the classes are perfectly spelt and what not. just not sure how to reach in the arrayList and pull out the class they are looking for.
public static void serachRooms(ArrayList<Room> rooms) {
int option = 0;
String temp = "";
boolean flag = false;
do {
System.out.println("please Enter What room Type you would like:"
+ "\nNormal Room = 1"
+ "\nComputer Room = 2"
+ "\nBiology Lab = 3"
+ "\nBoard Room = 4"
+ "\nYou must choose one!");
option = input.nextInt();
if (option == 1 || option == 2 || option == 3 || option == 4) {
flag = true;
}
} while (!flag);
switch (option) {
case 1:
temp = "BiologyLab";
break;
case 2:
temp = "BoardRoom";
break;
case 3:
temp = "ComputerRoom";
break;
case 4:
temp = "Room";
break;
}
for (Room room : rooms) {
if (temp instanceof BiologyLab) {
}
}
}
instanceof is something pretty special that has to do with types and inheritance. Check out the Java documentation.
For your case, you want to compare the String temp to the String "BiologyLab". Just use
if ("BiologyLab".equals(temp)) {
...
}
and check out How To Compare Strings In Java for more information.
I have designed a flowchart that is based on this code in Java.
public static void main(String args[]) throws IOException {
BufferedReader bw = new BufferedReader(new InputStreamReader(System.in));
attendance_and_student_management object = new attendance_and_student_management();
int flag = 1;
do {
{
int var = object.menu();
if (var == 1) {
System.out.println("\f");
object.add_student();
System.out.println();
} else if (var == 2) {
System.out.println("\f");
object.search_student();
System.out.println();
} else if (var == 3) {
System.out.println("\f");
object.change_student_information();
System.out.println();
} else if (var == 4) {
System.out.println("\f");
object.take_attendance();
System.out.println();
} else if (var == 5) {
System.out.println("\f");
object.attendance_summary();
System.out.println();
} else if (var == 6) {
System.out.println("\f");
object.monthly_defaulter_list();
System.out.println();
} else if (var == 7) {
System.out.println("\f");
System.out.println("THANK YOU FOR USING THE PROGRAM!!");
System.exit(0);
} else {
System.out.println("\f");
System.out.println();
System.out.println("Invalid Input. Would you like to try again? Press 1 for Yes");
int choice1 = Integer.parseInt(bw.readLine());
if (choice1 == 1) {
continue;
} else {
break;
}
}
System.out.println("Would you like to return to the Main Menu to perform more tasks? Press 1 for Yes and 0 for No");
flag = Integer.parseInt(bw.readLine());
if (flag != 1) {
System.out.println("Are you sure you want to exit? Press 1 for Yes");
int flag2 = Integer.parseInt(bw.readLine());
if (flag2 == 1)
flag = 0;
else
flag = 1;
}
}
}
while (flag == 1);
}
The flowchart is given below:
I am still learning how to construct flowcharts, therefore, I am not sure whether this diagram is correct. Any inputs or suggestions will be much appreciated.
PS: I tried to make the flow chart a bit simpler, please do tell if this is more appropriate than the previous one...
Your condition on the chart
Is var equal to 1,2,3,4,5,6 or 7?
ist not 100% right.
Your program works with if and else if conditions, which check each condition serial. You first check the 1, then the 2, then the 3 and so one...
Your chart shows this conditions as an All-In-One condition, what in java mean a switch).
So your chart should show these if's more like this:
Next, you dont need to draw the chart-boxes
Execute Method
In your code, you can draw just one box for the action in a true if-condition (like my added image).
And finally, you should have only one "Exit / End" point on the chart. Each flow that stopps the program, should link to this End-Point.
I need the syntax for adding in the variable parameter to a switch case that already has lots of parameters. The context is provided below.
I'm using a switch case to change a string answer to an integer return. Instead of having the user answer
1. This.
2. Something else.
I want the answer to look like
(y/n)
I've done it before with a code like this:
static public int getYN() {
String answer = "";
switch(keyboard.nextLine().substring(0, 1).toLowerCase()) {
case "y":
return 1;
case "n":
return 0;
default:
return 2;
}
}
And then using the statement:
int getAnswer = getYN();
System.out.println();
if (getAnswer == 1) {
System.out.println("Stuff.");
test = 1;
}
else {
System.out.println("Other stuff.");
System.out.println();
}
But, I don't know where to put the String answer variable into the switch case. Usually, if you aren't using many other parameters, it would just be
switch(answer) {
}
Check it inline, forget having a dedicated method to doing this check.
char getAnswer = keyboard.next().charAt(0);
System.out.println();
if (getAnswer == 'y' || getAnswer == 'Y')
{
System.out.println("Stuff.");
test = 1;
}
else if( getAnswer == 'n' || getAnswer == 'N')
{
System.out.println("Other stuff.");
System.out.println();
}
If you absolutely have to use a switch:
char getAnswer = keyboard.next().charAt(0);
switch(getAnswer)
{
case 'y':
System.out.println("Stuff.");
test = 1;
break;
case 'n':
System.out.println("Other stuff.");
System.out.println();
break;
}
You can achieve the same thing in one line:
public static int getYN(String s) {
return ("yn YN".indrxOf(s) + 3) % 3;
}
Both upper and lower cases are handled, and the "not found" default value of 2 is handled by adding 3 (indexOf() returns -1 when the target is not found) and modulus divusion takes care of the capital letter indexes.
Fairly neat even if I do say so myself.
I am doing a TicTacToe Program, the only missing part is to have the user to choose whether to quit the game or to replay. I can't find a way to "return" to the gaming.
import java.io.*;
public class Expierment
{
static char c1 [] = new char[10];
static char c2 [] = new char[10];
static char c3 [] = new char[10];
static char p1;
static char p2;
static boolean gameOver = false;
public static void main(String args[])
{
int counter = 0;
int p1Wins = 0;
int p2Wins = 0;
int r1 = 0;
int r2 = 0;
int r3 = 0;
int r4 = 0;
int r5 = 0;
int r6 = 0;
int r7 = 0;
int r8 = 0;
int r9 = 0;
int pick1 = 0;
int pick2 = 0;
int pick3 = 0;
int pick4 = 0;
int pick5 = 0;
int pick6 = 0;
int pick7 = 0;
int pick8 = 0;
int pick9 = 0;
char turn = 'X';
int choice = menu();
switch(choice)
{
case 1:
System.out.println("The game is called 'Tic-Tac-Toe', you should have known it. If you don't, search it.") ;
case 2:
gameOver = false;
break;
case 3:
System.out.println("\nSee you next time !!");
return;
default:
System.out.println("\nYou hit the wrong key......\n");
return;
}//end of switch
System.out.println("\nPlayer 1 initials ?");
String n1 = GCS();
p1 = n1.charAt(0);
System.out.println("\nPlayer 2 initials ?");
String n2 = GCS();
p2 = n2.charAt(0);
c1[2]='1';
c2[2]='2';
c3[2]='3';
c1[1]='4';
c2[1]='5';
c3[1]='6';
c1[0]='7';
c2[0]='8';
c3[0]='9';
printBoard ();
while(gameOver!=true)
{
System.out.println("Which spot ?");
int pick = Integer. parseInt(GCS());
switch (pick)
{
case 1:
if (r1<1)
{
c1[2] = turn;
r1++;
}
else
{
System.out.println("That column is full, pick another.\n");
continue;
}
break;
case 2:
if (r2<1)
{
c2[2] = turn;
r2++;
}
else
{
System.out.println("That column is full, pick another.\n");
continue;
}
break;
case 3:
if (r3<1)
{
c3[2] = turn;
r3++;
}
else
{
System.out.println("That column is full, pick another.\n");
continue;
}
break;
case 4:
if (r4<1)
{
c1[1] = turn;
r4++;
}
else
{
System.out.println("That column is full, pick another.\n");
continue;
}
break;
case 5:
if (r5<1)
{
c2[1] = turn;
r5++;
}
else
{
System.out.println("That column is full, pick another.\n");
continue;
}
break;
case 6:
if (r6<1)
{
c3[1] = turn;
r6++;
}
else
{
System.out.println("That column is full, pick another.\n");
continue;
}
break;
case 7:
if (r7<1)
{
c1[0] = turn;
r7++;
}
else
{
System.out.println("That column is full, pick another.\n");
continue;
}
break;
case 8:
if (r8<1)
{
c2[0] = turn;
r8++;
}
else
{
System.out.println("That column is full, pick another.\n");
continue;
}
break;
case 9:
if (r9<1)
{
c3[0] = turn;
r9++;
}
else
{
System.out.println("That column is full, pick another.\n");
continue;
}
break;
default:
System.out.println("Seriously?! Pick a possible spot.\n");
continue;
}//end of switch
if (turn=='X') turn = 'O';
else turn = 'X';
printBoard();
if (checkWinner())
{
while(gameOver==true)
{
int Echoice = EGM();
switch(Echoice)
{
case 1:
System.out.println("The game is called 'Tic-Tac-Toe', you should have known it. If you don't, search it.") ;
case 2:
gameOver = false;
menu();
break;
case 3:
System.out.println("\nSee you next time !!");
return;
default:
System.out.println("\nYou hit the wrong key......\n");
return;
}//end of switch
}//end of while true
return;
}
counter ++;
if (counter==9)
{
System.out.println("\n\nYou tied.\n");
return;
}
}//end of while not true
}//end of main
public static boolean checkWinner()
{
for (int k=0; k<2; k++)
{
if ((c1[k]!=' ')&&(c1[k]==c2[k])&&(c1[k]==c3[k]))
{
System.out.println("\nYo " + c1[k] + " is the winner!\n");
gameOver=true;
return true;
}//checks column 1-3 horizontally
}//end of horizontal check
for (int m=0; m<2; m++)
{
if((c1[m]!=' ')&&(c1[m]==c1[m+1])&&(c1[m+1]==c1[m+2])&&(c1[m]==c1[m+2]))
{
System.out.println("\nYo " + c1[m] + " is the winner!\n");
gameOver=true;
return true;
}//checks column 1 vertically
if((c2[m]!=' ')&&(c2[m]==c2[m+1])&&(c2[m+1]==c2[m+2])&&(c2[m]==c2[m+2]))
{
System.out.println("\nYo " + c2[m] + " is the winner!\n");
gameOver=true;
return true;
}//checks column 2 vertically
if((c3[m]!=' ')&&(c3[m]==c3[m+1])&&(c3[m+1]==c3[m+2])&&(c3[m]==c1[m+2]))
{
System.out.println("\nYo " + c3[m] + " is the winner!\n");
gameOver=true;
return true;
}//checks column 3 vertically
if ((c1[m]!=' ')&&(c1[m]==c2[m+1])&&(c1[m]==c3[m+2]))
{
System.out.println("\nYo " + c1[m] + " is the winner!\n");
gameOver=true;
return true;
}//checks upward diagonal
if ((c3[m]!=' ')&&(c3[m]==c2[m+1])&&(c3[m]==c1[m+2]))
{
System.out.println("\nYo " + c1[m] + " is the winner!\n");
gameOver=true;
return true;
}
}//end of vertical check
return false;
}//end of checkWinner
public static void printBoard()
{
System.out.println("_______");
for (int j = 2; j > -1; j--)
{
System.out.println("|" + c1[j] + "|" + c2[j] + "|" + c3[j] + "|");
System.out.println("-------");
}
}//end of printBoard
public static int menu()
{
System.out.println("Tic-Tac-Toe ~ Main Menu\n\n1. Instructions\n2. Play a 1 player game"+"\n3. Exit\n");
int selection = Integer.parseInt(GCS());
return selection;
}//end of menu
public static int EGM()
{
System.out.println("Tic-Tac-Toe ~ End of Game Menu\n\n1. Instructions\n2. Play again"+"\n3. Exit\n");
int Eselection = Integer.parseInt(GCS());
return Eselection;
}
public static String GCS()
{
int noMoreInput=-1;
char enterKeyHit='\n';
int InputChar;
StringBuffer InputBuffer = new StringBuffer(100);
try
{
InputChar=System.in.read();
while(InputChar != noMoreInput)
{
if((char)InputChar !=enterKeyHit)
{
InputBuffer.append((char)InputChar);
}
else
{
InputBuffer.setLength(InputBuffer.length()-1);
break;
}
InputChar=System.in.read();
}
}
catch (IOException IOX)
{
System.err.println(IOX);
}
return InputBuffer.toString();
}//end of GCS
}//end of public class
You really should get some of that code out of the main function.
Specifically, I'd put the whole game loop in a separate function, maybe called playGame(), which contains the logic for playing the game, checking winner, etc., and either returns the winner or just prints the winner and returns void.
Then the main function could put a call to playGame() in a loop, and at the end of the loop, ask the user if s/he wants to play again.
In general, you want each function to do one logical task. You've done well with moving checkWinner out, now do the same with some of the other code.
If you need help on the "asking the user about playing again", leave a comment and I'll make an edit to address that.
quick and dirty pseudo-code - not modular
do {
//everything in your main goes here
.
.
.
playAgain = prompt the user
} while(playAgain);
With the current program layout, there is no "clean" way to accomplish that. Here are some constructive criticism :
Your main method should only be a bootstrapper
You should only initialize your program in your main method. Consequently, try to have 1 method doing only 1 thing. You're design now has the game menu and game main loop inside the same method.
Your game loop could look like this:
while still playing
read input from user
if game is active
process game input
update game
else
process menu input
update menu
This way, you only need to swith the game is active state for the menu or the game. Etc.
Do not reinvent the wheel
Your GCS method is way too complicated, just replace it with :
Scanner scanner = new Scanner(); // put this somewhere at the class level (so it is reusable)
...
String input = scanner.nextLine(); // put this somewhere in a method reading an input
Variable abuse
Instead of initializing many variables, perhaps (like other have suggested) you could use arrays, or more specifically a 2-dimensional array.
int grid[][] = new int[3][3];
// grid[0][0] points to the top-left cell, grid[2][2] points to the bottom right one
Or you could use a single int to store everything; represent your grid as a bit array
int grid = 0; // empty grid
...
// set player move
grid |= (1 << (y*3)+x) << PLAYER_OFFSET; // PLAYER_OFFSET: 0=player 1, 16=player 2
// reset (clear) player move
grid &= ~((1 << (y*3)+x) << PLAYER_OFFSET); // ...
// check if player move is set
boolean isSet = (grid >> ((1 << (y*3)+x) << PLAYER_OFFSET)) && 1; // ...
Why are bit arrays cool? Because to check if a player wins, you don't need fancy for..loop and other complicated algorithms, just validate against a winning pattern... :
int pattern = 273; // test for diagonal from [0,0] to [2,2], or bits "100 010 001"
boolean isWinning = (grid && (pattern << PLAYER_OFFSET)) != 0;
That's it!
Also, using 0 to 9 may be good to identify the grid cell, however as input value is not that intuitive for a player. Many games (chess, checkers, LOA, etc.) and applications (Excel, Calc, etc.), for example, are using the Algebraic chess notation system. Converting the notation in x and y is very simple. For example :
boolean cellPlayed = false;
while (!cellPlayed) {
String cellStr = scanner.readLine().toLower(); // ex: "b2" for the center cell
try {
int gridx = cellStr.charAt(0) - 'a'; // ex: for "b2" should return 1
int gridy = cellStr.charAt(1) - '1'; // ex: for "b2" should return 1
grid(gridx][gridy] = playerValue; // 1 for "player 1" and 2 for "player 2"
cellPlayed = true;
} catch (Exception e) {
System.out.println("Error! Invalid input");
}
}
Don't feel discouraged! We all start somewhere! :)
Even dirtier than the do-while method. Will eventually cause stack-overflow.
//your current main method
boolean playAgain = prompt the user
if(playAgain){
main(args);
}
Things would be a lot more clear with a more concise main method. The really quick and dirty way would be to copy everything in your main method into a new method and just call that method from the main and when the user chooses to start a new game.