I am new to Java, would appreciate some help.
what I am trying to do here is switch between the cases. However what I also need is to not skip the remaining cases in this procedure.
I mean the code below should output:
two
four
three
four
public class X {
public static void main(String[] args) {
String n = "two";
while(true)
{
switch (n)
{
case "zero":
{
System.out.println("zero");
n="one";
}
case "one":
{
System.out.println("one");
n="three";
}
case "two":
{
System.out.println("two");
if (12>3)
{
n="four";
break;
}
}
case "three":
{
System.out.println("three");
}
case "four":
{
System.out.println("four");
return;
}
}
}
}
}
I have used return to end the while loop. Now I do understand that I have used break in case two which will break the current switch and thereby not complete it. But if i don't, I just can't switch between cases in the first place. So, I need a different solution. And working implementation in java should be helpful. Thanks
You can use Queue for this.
Each case is responsible to add the next one to the queue by the order of expected execution.
Queue q = new LinkedList();
q.add("two");
String n = (String)q.poll();
while(n!=null)
{
switch (n)
{
case "zero":
{
System.out.println("zero");
q.add("one");
break;
}
case "one":
{
System.out.println("one");
q.add("three");
q.add("two");
break;
}
case "two":
{
System.out.println("two");
if (12>3)
{
q.add("four");
}
q.add("three");
break;
}
case "three":
{
System.out.println("three");
q.add("four");
break;
}
case "four":
{
System.out.println("four");
break;
}
}
n=(String) q.poll();
}
The problem does not lie within the switch statement. You simply need to distinguish from where you 'came from'.
To do that you need to remember it, e.g. in a local variable:
String lastN;
and in the loop before the switch:
lastN = n;
Now you can do something like:
case "four":
{
System.out.println("four");
if("three".equals(lastN))
{
return;
}
else
{
n = "three";
break;
}
}
Your code is working as it should, if what you need is a fall through
then consider the fact that case zero and one must be executed first...
on the other hand, you don't need to add { } to the case group
case "zero": {
System.out.println("zero");
n = "one";
}
public static void main(String[] args) {
String n = "two";
while(true)
{
switch (n)
{
case "zero":
{
System.out.println("zero");
}
case "one":
{
System.out.println("one");
}
case "two":
{
System.out.println("two");
}
case "four":
{
System.out.println("four");
if(n=="four"){
return;
}
}
case "three":
{
System.out.println("three");
n="four";
}
}
}
}
Related
I have the function below and I want to add synonyms to each case for example case "north" could also be "up", case "east" could be right etc. Since all the cases fall into the same try/catch statement I wasn't sure how I could do that for each specific case. Appreciate any help! Thanks
public void changeRoom(boolean isValidInput, String[] input, int attemptCount) {
while (isValidInput) {
switch (input[1]) {
case "north":
case "east":
case "south":
case "west":
try {
if (world.getCurrentRoom().roomExits.containsKey(input[1])) {
player.setMostRecentExit(input[1]);
world.setCurrentRoom(world.getCurrentRoom().roomExits.get(input[1]));
isValidInput = false;
if (isSound) {
walkEffect.playSoundEffect();
}
Thread.sleep(1800);
narrateRooms(world.getCurrentRoom().getDescription());
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
default:
System.out.println("You hit a wall. Try again: ");
System.out.print(">>>");
attemptCount++;
if (attemptCount >= 2) {
System.out.println();
openMap();
System.out.println("Where would you like to go? ");
System.out.print(">>>");
}
input = scanner.nextLine().strip().toLowerCase().split(" ");
break;
}
}
I was able to normalize the input by creating the function below. Thanks, everybody!
public String normalizeText(String input) {
List<String> northOptions = Arrays.asList("north", "up");
List<String> southOptions = Arrays.asList("south", "down");
List<String> eastOptions = Arrays.asList("east", "right");
List<String> westOptions = Arrays.asList("west", "left");
if (northOptions.contains(input.toLowerCase())) {
return "north";
}
if (southOptions.contains(input.toLowerCase())) {
return "south";
}
if (eastOptions.contains(input.toLowerCase())) {
return "east";
}
if (westOptions.contains(input.toLowerCase())) {
return "west";
}
return "";
}
Just list those cases like that:
switch (input[1]) {
case "north": case "up":
case "east": case "right":
case "south": case "down":
case "west": case "left":
What are the ways of reducing code quantity in a method that contains schematic conditional statements?
What would be a good practice of placing such code. Should it be in a different method/class?
Example code in Java. It contains one scheme repeated twice:
if (calculation[i].equals("*")) {
if (stack.canDoOperation()) {
times();
} else {
operationFailed = true;
}
} else if (calculation[i].equals("+")) {
if (stack.canDoOperation()) {
sum();
} else {
operationFailed = true;
}
}
You could write a helper method, wrapping the given operation method into the commonly required checks. You could also put a try/catch in there, in case the operation can fail.
private boolean tryOperation(Runnable operation) {
if (stack.canDoOperation()) {
operation.run();
return true;
} else {
return false;
}
}
And use like this:
if (calculation[i].equals("*")) {
operationFailed = ! tryOperation(this::times);
} else if (calculation[i].equals("+")) {
operationFailed = ! tryOperation(this::sum);
}
Or, with Java 8, you can put the method references to those operations into a Map:
Map<String, Runnable> operations = new HashMap<>();
operations.put("*", this::times);
operations.put("+", this::sum);
...
Runnable operation = operations.get(calculation[i]);
if (operation != null && stack.canDoOperation()) {
operation.run();
} else {
operationFailed = true;
}
You can also combine the two approaches:
operationFailed = ! tryOperation(operations.get(calculation[i]);
Here is some example of how you can utilize repetitive statements. For more clarity you can extract stack.canDoOperation() to variable if it doesn't break your logic. Also you can consider moving it to assertion in beginning of the method and than put calculation[i] into switch statement.
if (calculation[i].equals("*") && stack.canDoOperation()) {
times();
}
} else if (calculation[i].equals("+") && stack.canDoOperation()) {
sum();
}
} else {
operationFailed = true;
}
You can use a switch statement into an if and maybe in a more logical way : check if you can do an operation, and if so find which one :
if (stack.canDoOperation()) {
switch(calculation[i]){
case "*": times(); break;
case "+": sum(); break;
} else {
operationFailed = true;
}
You can also give the value of operationFailed into the if statement :
operationFailed = !stack.canDoOperation() will be done first (if you cannot do an operation, operationFailed will true;
the value of !operationFailed (!!stack.canDoOperation() = stack.canDoOperation()) will be used in the if test
if (!(operationFailed = !stack.canDoOperation())) {
switch(calculation[i]){
case "*": times(); break;
case "+": sum(); break;
}
Since Java 7, it's possible to switch over Strings.
switch (calculation[i]) {
case "*":
times();
break;
case "+":
sum();
break;
}
Furthermore, for each calculation type, you are repeating the canDoOperation check. It's better that you bubble up this check:
if (stack.canDoOperation()) {
operationFailed = true;
}
else {
switch ... // Your switch statement
}
I suggest you move these operations to a separate method:
/**
* Performs the specified operation.
* #param The operation to perform.
* #return True if the operation was succeeded, false otherwise.
*/
boolean performOperation(String operation) {
if (!stack.canDoOperation()) {
return false;
}
switch (operation) {
case "*":
times();
break;
case "+":
sum();
break;
default:
return false;
}
return true;
}
However, without knowing the rest of your code, it's unclear whether this is a good solution.
I declared enum as an input to the switch statement since it doesn't allow String values.
public enum names{VALUE1, VALUE2}
I have a List of values (VALUE1, VALUE2, VALUE3)
for(int i=0; i<list.size();i++)
{
names n=new names(list.get(i).trim());
switch(n) {
case VALUE1:
System.out.println("1");
break;
case VALUE2:
System.out.println("2");
break:
default:
System.out.println("Nothing to print");
}
}
While executing the above-mentioned code, I am getting No Enum constant Class.data.VALUE3. error. Please help me resolve this error.
You can use names.valueOf(), but it will throw an exception if the name is not found:
for(int i=0; i<list.size();i++)
{
try {
names n=names.valueOf(list.get(i).trim());
switch(n) {
case VALUE1:
System.out.println("1");
break;
case VALUE2:
System.out.println("2");
break:
default:
System.out.println("Nothing to print");
}
} catch (IllegalArgumentException e) {
System.out.println("Nothing to print");
}
}
Otherwise, you need a loop:
private static names find(String name) {
for (names n: names.values()) {
if (n.name().equals(name)) {
return n;
}
}
return null;
}
but you would need to check for null before the switch:
for(int i=0; i<list.size();i++)
{
names n=find(list.get(i).trim());
if (n != null) {
switch(n) {
case VALUE1:
System.out.println("1");
break;
case VALUE2:
System.out.println("2");
break:
default:
System.out.println("Nothing to print");
}
} else {
System.out.println("Nothing to print");
}
}
I'm working on a card game app and i finished the basic stuff and now i'm trying to make it look professional.
the first thing I want to do is the effect of the distribution of cards,
i want to make a shuffle card effect.
when a card is given to a player, I want at least 500 milliseconds difference to the next card that will be distributed to him.
ideas?
this is a part from my code..
private void SetTheGame() {
SetShuffleSound();
for ( int i = 0; i < Imagename.length;i++) {
Imagename[i] = (ImageView) findViewById(WTF[i]);
CountCards();
Random = getRandom();
SwitchImages SwitchMe = new SwitchImages(myNewArray[Random]);
int first = SwitchMe.ChangeImages();
Imagename[i].setImageResource(myNewArray[Random]);
Imagename[i].setVisibility(View.VISIBLE);
CardsCount valueOfCard = new CardsCount(myNewArray[Random]);
int a = valueOfCard.WhatsMyValue();
String b = valueOfCard.TheFamily();
switch (i) {
case 0:
if (first != 0) {
Imagename[0].setImageResource(first);
}
FirstColumnComputer.add(a);
FirstColumnComputerFAMILY.add(b);
break;
case 1:
if (first != 0) {
Imagename[1].setImageResource(first);
}
SecondColumnComputer.add(a);
SecondColumnComputerFAMILY.add(b);
break;
case 2:
if (first != 0) {
Imagename[2].setImageResource(first);
}
ThirdColumnComputer.add(a);
ThirdColumnComputerFAMILY.add(b);
break;
case 3:
if (first != 0) {
Imagename[3].setImageResource(first);
}
FourColumnComputer.add(a);
FourColumnComputerFAMILY.add(b);
break;
case 4:
if (first != 0) {
Imagename[4].setImageResource(first);
}
FifthColumnComputer.add(a);
FifthColumnComputerFAMILY.add(b);
break;
case 5:
FirstColumnPlayer.add(a);
FirstColumnPlayerFAMILY.add(b);
break;
case 6:
SecondColumnPlayer.add(a);
SecondColumnPlayerFAMILY.add(b);
break;
case 7:
ThirdColumnPlayer.add(a);
ThirdColumnPlayerFAMILY.add(b);
break;
case 8:
FourColumnPlayer.add(a);
FourColumnPlayerFAMILY.add(b);
break;
case 9:
FifthColumnPlayer.add(a);
FifthColumnPlayerFAMILY.add(b);
break;
}
Cards.remove(Random);
// MakeTheCardPause();
}
SentTheLinkedList();
}
MakeTheCardPause() is the problem...
private void MakeTheCardPause() {
Thread Timer = new Thread()
{
public void run()
{
try{
sleep(1000);
}catch(InterruptedException e)
{
e.printStackTrace();
}finally
{
//do something...
}
}
};
Timer.start();
}
thanks!
Many ways you can do this. Thread.sleep(500) is the way was you suggested but it is not what I would recommend. Here are two alternatives
Message Handler
An example
Handler mHandler = new Handler(){
public void handleMessage(Message msg){
super.handleMessage(msg);
switch(msg.what){
case shuffle:
// Do something
break;
case doneShuffle:
//Do something
}
}
};
Asynch Tasks
Here is an example:
private class shuffleCards extends AsyncTask<Card, Integer, Long> {
protected Long doInBackground(Card card) {
//Do something
//shuffle deck
// Escape early if cancel() is called
if (isCancelled()) break;
}
return deck;
}
protected void onProgressUpdate(Integer... progress) {
//Number of shuffled cards??
}
protected void onPostExecute(Long result) {
//Show card
}
}
Remember this is just a background task to display results. Your main thread will be handling the actual card values and handing them over to the Asynch task.
Good Luck
What about this? You need to have the sleep in the working thread, your code above is creating a new thread and telling it to sleep, which has no noticeable effect to the user.
private void SetTheGame() {
SetShuffleSound();
for ( int i = 0; i < Imagename.length;i++) {
Imagename[i] = (ImageView) findViewById(WTF[i]);
CountCards();
Random = getRandom();
SwitchImages SwitchMe = new SwitchImages(myNewArray[Random]);
int first = SwitchMe.ChangeImages();
Imagename[i].setImageResource(myNewArray[Random]);
Imagename[i].setVisibility(View.VISIBLE);
CardsCount valueOfCard = new CardsCount(myNewArray[Random]);
int a = valueOfCard.WhatsMyValue();
String b = valueOfCard.TheFamily();
switch (i) {
case 0:
if (first != 0) {
Imagename[0].setImageResource(first);
}
FirstColumnComputer.add(a);
FirstColumnComputerFAMILY.add(b);
break;
case 1:
if (first != 0) {
Imagename[1].setImageResource(first);
}
SecondColumnComputer.add(a);
SecondColumnComputerFAMILY.add(b);
break;
case 2:
if (first != 0) {
Imagename[2].setImageResource(first);
}
ThirdColumnComputer.add(a);
ThirdColumnComputerFAMILY.add(b);
break;
case 3:
if (first != 0) {
Imagename[3].setImageResource(first);
}
FourColumnComputer.add(a);
FourColumnComputerFAMILY.add(b);
break;
case 4:
if (first != 0) {
Imagename[4].setImageResource(first);
}
FifthColumnComputer.add(a);
FifthColumnComputerFAMILY.add(b);
break;
case 5:
FirstColumnPlayer.add(a);
FirstColumnPlayerFAMILY.add(b);
break;
case 6:
SecondColumnPlayer.add(a);
SecondColumnPlayerFAMILY.add(b);
break;
case 7:
ThirdColumnPlayer.add(a);
ThirdColumnPlayerFAMILY.add(b);
break;
case 8:
FourColumnPlayer.add(a);
FourColumnPlayerFAMILY.add(b);
break;
case 9:
FifthColumnPlayer.add(a);
FifthColumnPlayerFAMILY.add(b);
break;
}
Cards.remove(Random);
long sleepMax = 1000L;
Random r = new Random();
long delay = (long) (r.nextDouble() * range);
Thread.sleep(delay);
}
SentTheLinkedList();
}
So I wrote a method today that incorporated the use of nested switch statements, and the code looked fairly clean and concise to me, but I was told that nested switch statements are not typically the best way to go as they can get confusing with the more switch statements that you add on. Here is a sample of what my code looked like:
EnumOne enumOne;
EnumTwo enumTwo = null;
EnumTwo enumThree = null;
switch (enumOne) {
case CASE_ONE:
switch (enumTwo){
case A: enumTwo = EnumTwo.B; break;
case C: enumTwo = EnumTwo.D; break;
default: break;
}
switch (enumThree) {
case AA: enumThree = EnumTwo.BB; break;
case CC: enumThree = EnumTwo.DD; break;
default: break;
}
break;
case CASE_TWO:
case CASE_THREE:
switch(EnumTwo) {
default: break;
}
switch (enumThree) {
case AA: enumThree = EnumTwo.XX; break;
case CC: enumThree = EnumTwo.YY; break;
default: break;
}
break;
default:
break;
}
So my question would be, essentially, what would be a suitable alternative to these switch statements?
As using a lot of switch becomes pretty hard to read.
And any time a new case arises then we have to modify code and add a CASE
we can consider using polymorphism in such cases
I am going to give a simple class just to let you understand.
Suppose a class earlier with switch case
class Test
{
Animal a;
public Test(Animal a)
{
this.a=a;
}
public moveThisAnimal()
{
switch(this.a)
{
case fish:
System.out.println("swim");
break;
case dog:
System.out.println("walk");
break;
case bird:
System.out.println("fly");
break;
}
}
}
now we replace these switch with our polymorphism logic
Interface Animal
{
String move();
}
Class Dog implements Animal
{
public String move()
{
return "walk";
}
}
Class Bird implements Animal
{
public String move()
{
return "fly";
}
}
Class Fish implements Animal
{
public String move()
{
return "swim";
}
}
now we have Test class without switch case
class Test
{
Animal a;
public Test(Animal a)
{
this.a=a;
}
public moveThisAnimal()
{
System.out.println(this.a.move()); // all switch case statements removed
}
}
and even if we have to add further cases we have to just add implementations no change here
See your complete code and see if It is possible to Do
I recommend you replace each nested switch statement with a call to a procedure which then executes the nested switch code.
Write something like this instead:
EnumOne enumOne;
EnumTwo enumTwo = null;
EnumTwo enumThree = null;
switch (enumOne)
{
case CASE_ONE:
nested_switch1();
case CASE_TWO:
case CASE_THREE:
nested_switch2();
break;
default:
break;
}
nested_switch1() {
switch (enumTwo)
{
case A:
enumTwo = EnumTwo.B;
break;
case C:
enumTwo = EnumTwo.D;
break;
default:
break;
}
switch (enumThree)
{
case AA:
enumTwo = EnumTwo.BB;
break;
case CC:
enumTwo = EnumTwo.DD;
break;
default:
break;
}
break;
}
nested_switch2() {
switch(EnumTwo)
{
default:
break;
}
switch (enumThree)
{
case AA:
enumTwo = EnumTwo.XX;
break;
case CC:
enumTwo = EnumTwo.YY;
break;
default:
break;
}
}
If you have integers X and Y and you need to switch on both, you can combine them in some unambiguous way and switch on the combination. For example, if y < 10:
switch (x*10+y)
{
case 0: // x == y == 0
case 1: // x ==0, y == 1
///
case 10: // x == 1, y == 0
case 11: // x == y == 1
//
}