I have a method which has result at the end,I would want to detect if number is not 0 and if it's -4.
0 Means good
-4 Means something that can be solve
And anything else is bad.
Like
if ( Result != 0)
{
MessageBox.Show("It's bad!")
}
else if ( Result == -4)
{
Thread.Sleep(20000);
MyMethod.TryAgain();
}
else
{
MessageBox.Show("It's good");
}
My problem is that -4 is not 0,so if i get result -4 it takes my Result != 0 method. How can I solve it? Thank you in advance.
Use switch and case.
switch (Result) {
case 0:
MessageBox.Show("It's good");
break;
case -4:
Thread.Sleep(20000);
MyMethod.TryAgain();
break;
default:
MessageBox.Show("It's bad!");
break;
}
Microsoft documentation: https://msdn.microsoft.com/en-us/library/06tc147t(v=vs.110).aspx
Just reorder your if-structure to the following:
if ( Result == 0)
{
MessageBox.Show("It's good")
}
else if ( Result == -4)
{
Thread.Sleep(20000);
MyMethod.TryAgain();
}
else
{
MessageBox.Show("It's bad");
}
So your initial problem, that the Result != 0 case is evaluated first, is gone.
Simply change order of branches
if (Result == -4) \\ solve
else if (Result != 0) \\ bad
else \\ good
When you are building a chain of non-exclusive conditions, start with the strongest one (i.e. the most specific condition). Otherwise the code for the weaker condition will execute, blocking access to more specific ones.
In your case, Result == -4 implies that Result != 0, meaning that the first condition is more specific than the second one. Hence you should check Result == -4 before Result != 0. Otherwise, Result == -4 would never be reached.
C# offers multiple ways of implementing this logic. As long as you follow a general rule of ordering your conditionals from most specific to least specific, picking a particular implementation is up to you.
Sorry, wrong code. See comment below.
switch(Result) {
case 0:
MessageBox.Show("It's bad!");
break;
case -4:
Thread.Sleep(20000);
MyMethod.TryAgain();
break;
default:
MessageBox.Show("It's good");
break;
}
Related
I'm writing a method that I will use in another code so I'm writing it separately first.
The code returns a boolean based on the first char of the input (yes, Yes, y, yeah, No, ...). But when the input is different from Y or N it starts acting up. In eg3 It stays in the loop until The Console.Read encounters a Y or an N or there are no chars left. In the last case, it will ask again for input.
Am I using the Console.Read wrong or is there another error in my code?
Thanks in advance
EDIT: Is the solution, in the end, an efficient one?
eg1:
Yes or No?
YeahIthinkso <--my input
True
eg2:
Yes or No?
Negative <--my input
False
eg3:
Yes or No?
Idontknow <--my input
You can only answer with Yes or No
Yes or No?
You can only answer with Yes or No
Yes or No?
You can only answer with Yes or No
Yes or No?
False
The Code:
static void Main(string[] args)
{
char YN = 'x';
bool ans = false;
while (YN == 'x')
{
Console.WriteLine("Yes or No?");
YN = char.ToUpper(Convert.ToChar(Console.Read()));
switch (YN)
{
case 'Y':
ans = true;
break;
case 'N':
ans = false;
break;
default:
Console.WriteLine("You can only answer with Yes or No");
YN = 'x';
break;
}
}
Console.WriteLine(ans);
Alternate solution based on #StuartLC's answer:
bool ans = true, loop = true;
do
{
switch (Console.ReadLine().ToUpper().FirstOrDefault())
{
case 'Y':
ans = true;
loop = false;
break;
case 'N':
ans = false;
loop = false;
break;
default:
Console.WriteLine("You can only answer with Yes or No");
break;
}
} while (loop==true);
Console.WriteLine(ans);
As per #Lasse's comment - if the user types in multiple characters, you'll loop on each character in the string typed in by the user, resulting in the printing a new line of output for each character the user typed. Instead, use of ReadLine will parse the input as a single string, and then the Linq extension FirstOrDefault() will safely obtain the first char in the string:
YN = char.ToUpper(Console.ReadLine().FirstOrDefault());
As an aside, instead of starting a while loop with a forced false condition, C# also supports a do-while loop syntax which fits your requirement better, i.e. at least one iteration through the loop, with a check at the end of the loop:
do
{
Console.WriteLine("Yes or No?");
YN = char.ToUpper(Console.ReadLine().FirstOrDefault());
switch (YN)
{
case 'Y':
ans = true;
break;
case 'N':
ans = false;
break;
default:
Console.WriteLine("You can only answer with Yes or No");
YN = 'x';
break;
}
}
while (YN == 'x');
Re OP's follow up question
Can I now remove the 'YN' completely and put a switch (Console.ReadLine().FirstOrDefault().ToUpper()) in the beginning and a while (ans == true || ans ==false) in the end?
Not quite - since ans is a boolean, it can only have two states (true or false), and you need to model at least 3 states (true, false, and invalid). Although you could use a nullable boolean (bool?) to model the 3 states (where null = invalid), I personally dislike using null to indicate something isn't known, as this invariably leads to the NullReferenceException abyss, and C# hasn't (yet) opted for the "Option" type / Monad (like Java's Optional).
If you're OK with C#8 pattern matching and tuples, you could possibly make the code a bit more concise and refactored as follows, by splitting out the concerns of 'is the input valid' and 'what is the valid input value'?. You could also refactor the switch expression into it's own method to split out the concerns of 'UI' from the parsing logic, which is always a good idea.
static void Main(string[] args)
{
bool ans;
bool isValid;
do
{
Console.WriteLine("Yes or No?");
(ans, isValid) = ParseInput(Console.ReadLine());
if (!isValid)
{
Console.WriteLine("You can only answer with Yes or No");
}
}
while (!isValid);
Console.WriteLine(ans);
(bool ans, bool isValid) ParseInput(string input) =>
char.ToUpper(input.FirstOrDefault()) switch
{
'Y' => (true, true),
'N' => (false, true),
_ => (default, false)
};
}
I have a try {} catch {} for each line my user inputs something, this is to ensure it's in the right format/range/acceptable. However it doesn't seem to... well work! Here is one of my examples.
string userAnswer;
bool errorHandling = true;
while (errorHandling){
try{
userAnswer = Console.ReadLine();
if (userAnswer == "1") {
singleGrade.grapher(acount, bcount, ccount, dcount, ecount, fcount);
}else{
if (userAnswer == "2"){
readIn.Classes(SingleGrade[1]);
}else{
if (userAnswer == "3"){
countAll.allGrades(multiGrade);
} else{
errorHandling = false;
}
}
}
}
catch (FormatException a){
Console.WriteLine(a.Message);
//Console.WriteLine("Error - please enter a number between 1 & 6.");
}
} // end of While loop
If someone could please explain to me why no error is caught when an invalid number is placed/not in the correct format.
There is no FormatException being thrown because valid strings are being entered. If you were to convert the user input to an integer, for example, that would throw a FormatException. But since you are leaving it as a string, no exception is being thrown.
However, since you are really only trying to restrict user input, and nothing truly exceptional is happening here, you should probably just handle it through you application logic.
What you are really looking for is probably something like this:
bool errorHandling = true;
while (errorHandling)
{
string userAnswer = Console.ReadLine();
switch (userAnswer)
{
case "1":
singleGrade.grapher(acount, bcount, ccount, dcount, ecount, fcount);
errorHandling = false;
break;
case "2":
readIn.Classes(SingleGrade[1]);
errorHandling = false;
break;
case "3":
countAll.allGrades(multiGrade);
errorHandling = false;
break;
// cases for 4, 5, and 6...
default:
Console.WriteLine("Error - please enter a number between 1 & 6.");
break;
}
} // end of While loop
You're not throwing and exception when the number is invalid, you're just handling a bunch of if statements - thus, since there is no throw statement, nothing can hit the catch statement, and insteadyou're seeing what we colloquially call a "Fall through error" - logic is proceeding past where it should.
If you want an exception when input is invalid, just add a throw new FormatException to the end of the if statements, so you get a "if we make it here there's a problem" behaviour.
The reason is that you are grabbing a string, and not trying to convert it to anything else, so there is no FormatException.
I would get away from using the try / catch for input validation, and instead use the TryParse method of the Int type.
What I usually do is write a separate function to get validated input from the user, then call that from my main code. In this case, since you have upper and lower bound requirements, you might consider writing something like this:
public static int GetBoundedIntFromUser(int minVal, int maxVal)
{
if (minVal >= maxVal)
{
throw new ArgumentException("minVal must be less than maxVal.");
}
int input;
while (true)
{
Console.Write("Please enter a number from {0} to {1}: ", minVal, maxVal);
if (int.TryParse(Console.ReadLine(), out input)
&& input >= minVal && input <= maxVal)
{
break;
}
Console.WriteLine("That input is not valid. Please try again.");
}
return input;
}
Then you can just call it from your main code (without any try catch), like:
switch (GetBoundedIntFromUser(1, 3))
{
case 1:
singleGrade.grapher(acount, bcount, ccount, dcount, ecount, fcount);
break;
case 2:
readIn.Classes(SingleGrade[1]);
break;
case 3:
countAll.allGrades(multiGrade);
break;
default:
break;
}
if (((turn % 2) != 0) && (vsComputer))
{
int generateAI = generateRandomAI(AI);
switch (generateAI)
{
case 0:
computerMedio();
break;
case 1:
computerDifficile();
break;
}
}
I want my 0/1 value to be the same for all the game.
With the code I wrote, on every move it selects a different AI mode.
It shouldn't be that hard to achieve, but I can't find a solution.
Thanks everyone!
Your issue is:
int generateAI = generateRandomAI(AI);
You are generating a new random value on every invocation of this code block. If you wish to keep the same value for all execution, just generate the value once and keep it in scope.
Ok I solved in the following way
public Boolean difficult;
in the newGame() method I generate the number which lasts for all the game.
then,
switch (generateAI)
{
case 0:
difficult = false;
break;
case 1:
difficult = true;
break;
}
into the game:
if (((turn % 2) != 0) && (vsComputer))
{
if (difficult)
{
computerDifficile();
}
else
{
computerMedio();
}
}
When I try to evaluate the SelectedIndex of a CheckBoxList and at bool. I receive a error on the case in my switch statement in C#. The error is Constant value '0' cannot be converted to a 'bool'. Is there a way that I can evaluate both with in a switch statement? I know I can use a if statement, but I would rather use a switch statement if I could.
Here is my code:
switch ((CBL_PO.SelectedIndex == 0) && (boolIsNotValid == true))
{
case 0: case true:
//Do Something
break;
}
Since the only values in the switch can be true or false, drop the case 0.
Alternatively, you could better use an if:
if (CBL_PO.SelectedIndex == 0 && boolIsNotValid)
{ }
else
{ }
Since I think you might be trying to do a check on both values in the switch: not possible. This is your best option:
switch (CBL_PO.SelectedIndex)
{
case 0:
{
if (boolIsNotValid)
{ }
else
{ }
break;
}
}
A switch statement can be thought of as a replacement for a stack of if/else statements. If you are doing a single comparison then use a simple if statement; switch is overkill.
if (CBL_PO.SelectedIndex == 0 && boolIsNotValid)
{
// Do something
}
If you really want to use a switch statement, then you want:
switch ((CBL_PO.SelectedIndex == 0) && (boolIsNotValid == true))
{
case true:
//Do Something
break;
case false:
//Do Something else
break;
}
I didn't know what else to use in this case but an if statement.
What I am trying to do is I am getting a value string direction; from a Windows form and checking if it has the value I am looking for. Then checking if the turtleDir which is a string value indicating the direction turtleDir has.
The problem comes here at else if statements, when the turtleDir is lookingleft it does all of the else if statements. What I want it to do is after it has done that else if statement it needs to stop and wait for the next command. not go through all the statements.
Can someone please advise me on how to fix it and what I am doing wrong?
Here is the code:
else if ( Program.form.direction == "right" )
{
if ( turtleDir == "left" )
{
angle = -1.6f;
turtleDir = "lookingLeft";
Program.form.direction = "";
}
else if ( turtleDir == "lookingLeft" )
{
angle = 3.15f;
turtleDir = "lookingDown";
}
else if ( turtleDir == "lookingDown" )
{
angle = 1.6f;
turtleDir = "lookingRight";
}
else if ( turtleDir == "lookingRight" )
{
angle = 0.0f;
turtleDir = "lookingUp";
}
}
You can use a switch statement on strings, too:
switch (turtleDir) {
case "left":
angle = -1.6f;
turtleDir = "lookingLeft";
Program.form.direction = "";
break;
case "lookingLeft":
angle = 3.15f;
turtleDir = "lookingDown";
break;
// other cases
}
This way, the switch block is always exited after your instructions are done. You can also specify what to do when the string matches none of these values by adding a case default: at the end. Remember each of these cases needs to be terminated by a break statement (or return/throw but i don't think you need those in this case).
If still every case is executed, your problem lies somewhere else. If a method contains this code and is called starting with e.g. turtleDir == "left", each successive call of the method will let turtleDir cycle until every case has been executed and turtleDir ends up with the final value "lookingUp". So look at your control flow and maybe keep track whether you already performed this check. Maybe keep track of the elapsed time and change turtleDir only if it has been in a particular state for a while (i don't know your requirements).
EDIT: You should set Program.form.direction = "" in every case statement. That's why your code gets executed over and over again. Also, if no direction is entered, clear it, too.
You can use an empty return;- Statement, but then you leave your method too...
Use a switch
switch (turtleDir)
{
case "left":
angle = -1.6f;
turtleDir = "lookingLeft";
Program.form.direction = "";
break;
case "lookingLeft":
angle = 3.15f;
turtleDir = "lookingDown";
break;
case "lookingDown":
angle = 1.6f;
turtleDir = "lookingRight";
break;
case "lookingRight":
angle = 0.0f;
turtleDir = "lookingUp";
break;
default:
// Optional, but place any actions if non of the above is matched
break;
}
There is something else going on here....
Only one branch of an IF/ELSE-IF statement will be executed. You might want to refactor to a SWITCH statement for readability reasons; but not because it would change your behaviour.
Look at this code:
if(0 == 0) { Console.WriteLine("Branch 1"); }
else if(true==true) { Console.WriteLine("Branch 2"); }
else if(false==false) { Console.WriteLine("Branch 3"); }
ALL of the conditions are true. And the first one executes. ONLY the first one.
In this code - only the second two are true:
if(0 == 2) { Console.WriteLine("Branch 1"); }
else if(true==true) { Console.WriteLine("Branch 2"); }
else if(false==false) { Console.WriteLine("Branch 3"); }
And ONLY the second one executes.
A series of else-if's won't all execute if the condition is true.
My guess is that you are looping through this really fast or something and the next iteration is entering the IF logic and executing the next branch. You might need to post more code so that you get more helpful answers for your particular situation.
The best way to track this down, IMHO, is to just place a breakpoint on the start of your IF logic and step-through the code one execution at a time. You should see that it only goes into one ELSE-IF branch and exits, and you can see if/why it re-enters.
Finally, the SWITCH statement doesn't allow you to implicitly execute multiple branches either.
switch(test)
{
case "one":
Console.WriteLine("Branch 1");
case "two":
Console.WriteLine("Branch 2");
}
That won't even compile. I believe in C/C++ you could fall though case statements unless you explicitly added break; or similar control statement. In C# that's not the case.