I'm just starting out so I'm in the middle of writing my first console application from scratch. I have this line of code, when I hit d it correctly takes me to the next step and sets disadvantage to true, however if I hit a it executes the else statement for some reason. Any ideas what the cause is?
Console.WriteLine("Press the A key for advantage, or the D key for disadvantage");
var rollType = Console.ReadKey();
Console.WriteLine(System.Environment.NewLine);
if (rollType.Key == ConsoleKey.A)
{
advantage = true;
}
if (rollType.Key == ConsoleKey.D)
{
disadvantage = true;
}
else
{
Console.WriteLine("Invalid Input");
StartApp();
}
Just add make this small change! (Adding else in your second conditional)
if (rollType.Key == ConsoleKey.A)
{
advantage = true;
}
else if (rollType.Key == ConsoleKey.D)
{
disadvantage = true;
}
else
{
Console.WriteLine("Invalid Input");
StartApp();
}
What was happening before is your Console would read an A key and enter the first conditional. Since the second and third conditional was separate from the first, the second would also be checked and if not true (which in this case it would not be true) it would no matter what enter the else statement. Hope this helps.
Seems like the program is being executed exactly as you’ve written it to.
if (rollType.Key == ConsoleKey.A)
{
advantage = true;
} // First conditional check ends here
// This is another conditional block
if (rollType.Key == ConsoleKey.D)
{
disadvantage = true;
}
else // You pressed A, so this block is executed
{
Console.WriteLine("Invalid Input");
StartApp();
}
If you hit A, it will excude A and else part of D. After all, A equals A but A does not equal D.
What you want is propably a switch/case statement.
switch(rollType){
case ConsoleKey.A:
advantage = true;
break;
case ConsoleKey.D:
disadvantage = true;
break;
default:
Console.WriteLine("Invalid Input");
break;
}
switch/case statement and do/while loop - these two are the fundament of console programm flow.
Related
I am having trouble figuring out how to break out of a loop that contains a switch statement.
i need to press 0 twice to exit the console why?
how can i fix it to exit from the first time
public void Start()
{
int choice = 0;
bool trueNumber = false;
do
{
ShowMenu(); // display the menu
Console.Write("Your Choice : ");
trueNumber = int.TryParse(Console.ReadLine(), out choice);
if (!trueNumber)
Console.WriteLine("Your Choice must be an integer. Try again.");
switch (choice) // select the relevant function based on user input
{
case 1:
CalculateCelsiusToFahrenheit();
break;
case 2:
CalculateFahrenheitToCelsius();
break;
case 0:
return; // exit when i press 0
default:
Console.WriteLine("Invalid Option: Choose 0, 1, or 2 Thank you ");
break;
}
} while (choice != 0);
}
If you are running this from an IDE (like Visual Studio), the default behavior for console applications is to end with a "Press any key to continue." so it waits with the output displayed.
related answer: VS setting
The code below is a snippet from a working code that is for a castle maze game in c#.
The if else structure only prints correctly the dun.roomend == true). The tow.roomEnd now displays when the tre.isExit should be displayed. The tre.isExit doesn't display at all.
I have declared the current variables as:
public bool isExit;
public bool deadEnd;
public bool roomEnd;
tre.isExit = true;
dun.deadEnd = true;
tow.roomEnd = true;
if (dun.roomEnd == true)
{
Console.WriteLine("You've fallen into the Dungeons of the Dead. Try again");
return;
}
if (tow.roomEnd == true)
{
Console.WriteLine("You been caught by the Kings guard and have been placed in the tower for life.Try again");
return;
}
else if (tre.isExit == true)
{
Console.WriteLine("You have found the treaure... now run!!");
return;
}
else
{
Console.WriteLine("Too scared.....");
}
That's because you immediately return when one of your conditions is true.
// Don't explicitly compare to true - just write if (dun.roomEnd)
if (dun.roomEnd == true)
{
Console.WriteLine("You've fallen into the Dungeons of the Dead. Try again");
// You end the method here, so none of the rest of the code after this will execute
return;
}
Also, the fact that you do
else if (tre.isExit == true)
means that this won't execute if
tow.roomEnd == true
is also true. "Else if" means "if the current condition is true and the previous condition is false", so
if (A) {
// do work
}
else if (B) {
// Do work
}
is semantically equivalent to
if (A) {
// Do work
}
if (!A && B) {
// Do work
}
Finally, I mentioned this in passing, but I'd like to reiterate that it's not necessary to explicitly compare to true or false, so
if (tow.roomEnd == true)
should just be
if (tow.roomEnd)
Also, I don't think it makes sense for all of those conditions to be true at once. Can something actually be a room end, a dead end, and an exit at the same time? At a minimum, it seems like a particular location can't be both an exit and a dead end. If the data says that several of those things are true at once, it needs to be corrected in order for the program to function properly.
In every if statement you have keyword return;. The return statement terminates execution of the method and because of that only first Console.WriteLine is shown.
Read carefully: return (C# Reference)
Reading through what you've done, if I'm understanding this correctly what you're after is as follows.
public bool isExit;
public bool deadEnd;
public bool roomEnd;
tre.isExit = true;
dun.deadEnd = true;
tow.roomEnd = true;
if (dun.roomEnd == true)
{
Console.WriteLine("You've fallen into the Dungeons of the Dead. Try again");
}
else if (tow.roomEnd)
{
Console.WriteLine("You been caught by the Kings guard and have been placed in the tower for life.Try again");
}
else if (tre.isExit)
{
Console.WriteLine("You have found the treaure... now run!!");
}
else
{
Console.WriteLine("Too scared.....");
}
return
This will evaluate each condition individually, and then return once complete.
What this code is effectively saying is "if condition 1 is true, display the text and exit the if block, then return. Otherwise if condition 2 is true do the same, condition 3 / 4 do the same thing also.
I think this is what you're after at least. It could be refactored to make it a little simpler but don't have the time to go over that at the moment.
Assuming it is showing the Dungeons of the Dead and the Kings Guard message, you need to add an "else" to the if for tow.roomEnd.
I'm trying to use an if statement with a bool that will make it that if a code runs once it will not run again. Here is the code I am using.
int random = Program._random.Next(0, 133);
if (random < 33) {
bool done = false;
if(done)
{
continue; // Error is shown for this statement
}
Console.WriteLine("Not done!");
done = true;
}
The error that Visual Studio is displaying is: "No enclosing loop out of which to break or continue".
Depending on the class/method requirements, you could possibly reverse your logic:
if (!done)
{
Console.WriteLine("Not done!");
done = true;
}
You can't use a continue only inside a loop. So you must live without this:
int random = Program._random.Next(0, 133);
if(random < 33)
{
bool done = false;
if(!done)
{
Console.WriteLine("Not done!");
done = true;
}
}
In this case, you should reverse the if with if (!done) { ... }
You can't use continue like that, it can only be used in a loop. The continue statement will go to the end of the loop and continue with the next iteration, without a loop there is no end of the loop to go to.
You can use else instead:
if (done) {
// anything to do?
} else {
Console.WriteLine("Not done!");
done = true;
}
If there is nothing to do if the variable is true, you can just reverse the expression instead:
if (!done) {
Console.WriteLine("Not done!");
done = true;
}
Note: You need to store the variable done outside the scope. Now you have a local variable that is always set to false, so the code will never be skipped.
The exception is telling you that continue is ineffective here. It simply has nothing to do, and doesn't know where to continue. It is meant to be used within the iteration of a loop.
I sometimes have myself writing code which requires several layers of if/else statements incorporated into each other (example can be found below).
I was wondering if I could shorten it up a bit, because sometimes I have trees of if/else statements of over 70 lines of code, and they are honestly just filling way too much compared to how many of the lines seem redundant.
Here's an example code:
if (labelGiveTip1.Visible == true)
{
if (labelGiveTip2.Visible == true)
{
labelGiveTip3.Visible = true;
if (labelGiveTip3.Visible == true)
{
Custom_DialogBox.Show("All of your hints for this assignment is used, do you want annother assignmment?", //main text argument
"Error: No more hints", //header argument
"Back", //first button text argument
"Get a new assignment"); //second button text argument
//this is a custom dialog box
result = Custom_DialogBox.result;
switch (result)
{
case DialogResult.Yes:
buttonNextAssignment.PerformClick();
break;
case DialogResult.Cancel:
break;
default:
break;
}
}
}
else
{
labelGiveTip2.Visible = true;
}
}
else
{
labelGiveTip1.Visible = true;
}
In my code I tend to check the false condition first and return ASAP. This approach has helped me over years to reduce deeply nested if else. Other than that try to separate related functionalities in to different methods. The example method provided crams too much of logic into one method. If you have ReSharper, it suggests nice improvements and over a period of time, it becomes a habit.
You may check the negated variant of the condition and use else if conditions to avoid that much nesting. E.g. a simplified version for your code:
if (!labelGiveTip1.Visible)
labelGiveTip1.Visible = true;
else if(!labelGiveTip2.Visible)
labelGiveTip2.Visible = true;
else
{
labelGiveTip3.Visible = true;
Custom_DialogBox.Show("All of your hints for this assignment is used, do you want annother assignmment?", //main text argument
"Error: No more hints", //header argument
"Back", //first button text argument
"Get a new assignment"); //second button text argument
//this is a custom dialog box
result = Custom_DialogBox.result;
switch (result)
{
case DialogResult.Yes:
{
buttonNextAssignment.PerformClick();
break;
}
case DialogResult.Cancel:
{
break;
}
default:
{
break;
}
}
}
It is also unnecessary to write labelGiveTip1.Visible == true or labelGiveTip1.Visible == false when they are already boolean values.
I am trying to make a simple console game that starts with a title screen. The user inputs 'N' for a new game, 'L' to load a game, or 'E' to exit. I have this set up as a switch, but I need to know how to make the program ignore any input other than the aforementioned keys. I've Googled this question but didn't find an answer. Please help if you can.
I don't see much point in posting the code as 10 lines of a simple switch probably wouldn't be terribly helpful to solving the problem. Also, if there would be an easier / more efficient way than a switch, I would love to know.
Thanks.
You can use a default: statement to handle the other (unknown) cases:
switch(inputString.ToLower())
{
case "n":
// Handle new
break;
//.. handle known cases
default:
Console.WriteLine("Unknown option chosen. Please enter valid option:");
// Re-read values, etc?
break;
}
Anything not specified in one of your other cases will fall into the default case, which you can then use to prompt for valid input.
If you want to actually ignore all keys other than valid ones you could do something like this:
public static char ReadKey(IEnumerable<char> validKeys)
{
var validKeySet = new HashSet<char>(validKeys);
while (true)
{
var key = Console.ReadKey(true);
if (validKeySet.Contains(key.KeyChar))
{
//you could print it out if you wanted.
//Console.Write(key.KeyChar);
return key.KeyChar;
}
else
{
//you could print an error message here if you wanted.
}
}
}
When you use ReadKey(true) the true indicated that it will intercept that key and not display it on the console. This gives you the option of determining if it's valid or invalid.
If a switch statement does not have a default block, and if the expression being switched on does not match any of the case blocks, the switch statement does nothing.
When you have only 3 cases, a switch isn't much more efficient than just a simple if-else construct.
if (input == "N")
{
// New game
}
else if (input == "L")
{
// Load game
}
else if (input == "E")
{
// Exit game
}
// if none of the cases match, the input is effectively ignored.
If you insist on using a switch, then your construct is very similar:
switch (input)
{
case "N":
//New Game
break;
case "L":
//Load Game
break;
case "E":
//Exit Game
break;
default:
//Do nothing (ignore unmatched inputs)
break;
}
Thanks for the replies, guys. I managed to solve the problem by doing the following:
static void titleInput()
{
ConsoleKeyInfo titleOption = Console.ReadKey(true);
switch (titleOption.Key)
{
case ConsoleKey.N:
Console.Clear();
break;
case ConsoleKey.L:
break;
case ConsoleKey.E:
Environment.Exit(0);
break;
default:
titleInput();
break;
}
}
I'm not sure how 'proper' this is, but it does what I need it to do. Any keys other than 'N', 'L', and 'E' no longer do anything.