What I want to do is to to change the console depending on what the user has pressed.
So I have a console with three options like this:
> Option 1
Option 2
Option 3
Basically, if the user presses the down arrow, the console becomes like this:
Option 1
> Option 2
Option 3
And if the user presses the up arrow, the console goes back to it's initial state.
I know how to read the user's input with Console.ReadKey(), but I don't know how to modify output that is already written.
One last thing is that when the user presses enter, the console does not create a new line, but chooses one of the options and calls a delegate.
This isn't too difficult to achieve using Console.ReadKey and some variables to hold the state of the selected option.
The following code is a very quick and lazy implementation of what you are looking for. Take the time to rewrite it yourself properly - this is to give you an idea of how you could achieve what you are looking for.
static void Main(string[] args)
{
bool IsRunning = true;
int Selected = 1;
while (IsRunning)
{
ConsoleKeyInfo NextKey = new ConsoleKeyInfo();
if (Selected < 1)
Selected = 3;
else if (Selected > 3)
Selected = 1;
Console.Clear();
if (Selected == 1)
Console.Write("> ");
Console.WriteLine("Option 1");
Console.WriteLine();
if (Selected == 2)
Console.Write("> ");
Console.WriteLine("Option 2");
Console.WriteLine();
if (Selected == 3)
Console.Write("> ");
Console.WriteLine("Option 3");
Console.WriteLine();
Console.Write("Choose an option (Q to Quit): ");
while (!(NextKey.Key == ConsoleKey.DownArrow ||
NextKey.Key == ConsoleKey.UpArrow ||
NextKey.Key == ConsoleKey.Q ||
(NextKey.KeyChar >= '1' &&
NextKey.KeyChar <= '3')))
{
NextKey = Console.ReadKey();
}
switch (NextKey.Key)
{
case ConsoleKey.D1:
// Do something
break;
case ConsoleKey.D2:
// Do something
break;
case ConsoleKey.D3:
// Do something
break;
case ConsoleKey.DownArrow:
Selected++;
break;
case ConsoleKey.UpArrow:
Selected--;
break;
case ConsoleKey.Q:
IsRunning = false;
break;
}
}
}
The code will loop whilst the 'Q' key has not been pushed to quit the application.
Pushing the down or up arrow will rotate through the options available.
Upon pushing 1, 2, or 3, you will cause the // Do something lines inside the switch statement to be run. You should here call whatever functionality exists for each of the options.
In order to update the 'menu' with the chosen option, the console output is cleared and then re-output. The correct option is identified via the Selected variable.
There are several other ways to implement the above, some much tidier. I wanted to give you an idea of where to start. I am not saying that this is the best or most tidy solution.
EDIT
A thought occurs - you wanted to use Enter to select the option.
I've modified the code a little to provide that functionality:
while (!(NextKey.Key == ConsoleKey.DownArrow ||
NextKey.Key == ConsoleKey.UpArrow ||
NextKey.Key == ConsoleKey.Q ||
NextKey.Key == ConsoleKey.Enter))
{
NextKey = Console.ReadKey();
}
switch (NextKey.Key)
{
case ConsoleKey.Enter:
// Do something depending on Selected option
switch (Selected)
{
case 1:
// Do something
break;
case 2:
// Do something
break;
case 3:
// Do something
break;
}
break;
case ConsoleKey.DownArrow:
...
Here's a similar approach with a little less code, which hides the cursor and shows our own custom cursor that indicates the selected menu item.
The method takes in a menu header, a list of options for the user to select from, and a cursor character. It prints out the header and an underline, and then each option with 3 spaces before each one. Then we move the cursor to the first option (row index 3 since the header is 0, underline is 1, and blank space is 2), second character, and write a backspace character followed by our cursor (the backspace erases the first character so we can write a new one).
As the user presses keys, we only handle the up and down arrows and the enter key. By passing true to Console.ReadKey(), the user input is "thrown away" and not displayed on the window. This allows us to switch on only the keys we care about.
When they press an arrow key we move the cursor to the second column in the current row, print a backspace and then a space (to erase the old cursor), then move up or down one row, and from the second column we print a backspace and then our cursor character.
When the user presses Enter, we enable the console cursor again and return the row that the cursor was on to indicate which item was selected at that time:
private static int GetMenuChoice(string header, List<string> options, char cursor = '>')
{
// Clear console and hide cursor
Console.Clear();
Console.CursorVisible = false;
// Write our header with an underline
Console.WriteLine(" " + header);
Console.WriteLine(" " + new string('-', header.Length));
Console.WriteLine();
// Write out each option with spaces before it
options.ForEach(option => Console.WriteLine($" {option}"));
// Move to the first option and, from the second character,
// write a backspace and then the cursor symbol
Console.SetCursorPosition(1, 3);
Console.Write($"\b{cursor}");
// Move cursor when user presses arrow keys, and get selection when they press enter
while (true)
{
// Pass 'true' to ReadKey so the input is not written
var input = Console.ReadKey(true);
switch (input.Key)
{
case ConsoleKey.UpArrow:
if (Console.CursorTop > 3)
{
Console.CursorLeft = 1;
Console.Write("\b ");
Console.SetCursorPosition(1, Console.CursorTop - 1);
Console.Write($"\b{cursor}");
}
break;
case ConsoleKey.DownArrow:
if (Console.CursorTop < options.Count + 2)
{
Console.CursorLeft = 1;
Console.Write("\b ");
Console.SetCursorPosition(1, Console.CursorTop + 1);
Console.Write($"\b{cursor}");
}
break;
case ConsoleKey.Enter:
var selection = Console.CursorTop - 3;
Console.CursorVisible = true;
Console.SetCursorPosition(0, options.Count + 4);
return selection;
}
}
}
This can be tested out with a sample ATM menu:
private static void Main()
{
var options = new List<string>
{
"Open a new account",
"Deposit Money",
"Withdraw money",
"Check balance",
"Exit"
};
var selectedItem = GetMenuChoice("ATM Machine", options);
Console.WriteLine($"You selected option: '{options[selectedItem]}'");
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output
Related
I'm trying to make a program which has two options based on the key is pressed by the user, it'will execute a different action. The second option has to do to displaying some information about operations performed in the first option. The main point is to try to make a navigation menu that the user can come back to the main menu through pressing "ESC" or "Enter" to continue in whatever he chooses
Console.WriteLine("\nCAMPAIGN 2022\nSelect what you want to consult:\n1) Votin Urn\n2) DataBase"); // to make clear, database will display info about votes quantity
int options = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("----------------------");
if (options == 1)
{
ConsoleKeyInfo menu;
Console.WriteLine("\nVOTING URN");
while (exit == false)
{
Console.WriteLine("\nSelect your vote:\n1) Jair Bolsonaro;\n2) Luiz
Inacio Lula da Silva;\n3) White;\n4) NulL");
vote = Convert.ToInt32(Console.ReadLine());
while (vote != 1 & voto != 2 & vote!= 3 & vote != 4)
{
if (increment == 0)
{
Console.WriteLine("\nInvalid Vote. Try again:");
}
vote = Convert.ToInt32(Console.ReadLine());
increment += 1;
The thing is: i'm using an if statement and because of local scope when the user selects option 2, to know who have more votes for example, the value is gonna be 0. I tried using switch but it's the same thing. What can I do?
Also, when the user press "ESC" to come back to select "Voting Urn" or "Database" the first letter of the text displayed is cut, like instead of "Campaign" it's "ampaing". I'm using the ConsoleKeyInfo:
Console.WriteLine("Press \"Enter\" to continue or \"Escape\" to return to the main menu");
menu = Console.ReadKey();
if (menu.Key == ConsoleKey.Escape)
{
exit = true;
}
if (menu.Key == ConsoleKey.Enter)
{
exit = false;
}
I would put the while loop so it covers the menu aswell and then just add another choice that is "Go back to main menu / exit application" in a swtich statement. And then have everything inside that switch statement and maybe do some fucnctions like TotalVotes() and Vote().Then do create variable names with each person you can vote for and just ++ each variable inside an if statement if they get a vote. Also this is probably a typo? "voto != 2". It seems like your structure is making it harder that it has to for you.
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
This question already has answers here:
Use a variable from another method in C#
(2 answers)
Closed 2 years ago.
I've been searching for answers to solve this tiny bit of code, but without luck. I figure I have to declare the variable for "item" outside the method, but I can't seem to find a way to do so.
beginner
namespace Items
{
class Program
{
static void Main(string[] args)
{
bool myBool = true;
while (myBool)
{
Console.WriteLine("Welcome");
Console.WriteLine("[1] - add item");
Console.WriteLine("[2] - see content");
Console.WriteLine("[3] - erase content");
Console.WriteLine("[4] - close");
int input = Convert.ToInt32(Console.ReadLine());
switch (input)
{
case 1:
Console.WriteLine("add item");
var item = (Console.ReadLine());
Console.WriteLine("you just added: " + item);
break;
case 2:
Console.WriteLine("items added: " + items);
break;
case 3:
myBool = false;
break;
}
}
}
}
}
welcome to Stack Overflow! It's not quite clear what you're asking here - questions should typically include what you expect the code to do, and what it actually does. That said, I think I can see what you're going for. I've updated the code, and added some comments to describe the changes.
using System;
using System.Collections.Generic; // This namespace contains the 'List<>' class
namespace Items
{
class Program
{
static void Main(string[] args)
{
// I've moved this outside of the loop - I assume users would want the help message
// displayed on startup, not every single time they do something.
Console.WriteLine("Welcome");
Console.WriteLine("[1] - add item");
Console.WriteLine("[2] - see content");
Console.WriteLine("[3] - erase content");
Console.WriteLine("[4] - close");
// The list of items is created here, outside of the main loop.
var items = new List<string>();
// You don't need to declare a variable 'myBool' here
// We can just loop until the user exits the whole program
while (true)
{
int input = Convert.ToInt32(Console.ReadLine());
switch (input)
{
case 1:
Console.WriteLine("add item");
var newItem = Console.ReadLine();
Console.WriteLine("you just added: " + newItem);
break;
case 2:
Console.WriteLine("items added:");
foreach (var item in items)
Console.WriteLine(item);
break;
case 3:
items.Clear();
break;
case 4:
return;
}
}
}
}
}
I would recommend following some tutorials first, so you get an idea of variable scope - how long a variable lives for and where it can be accessed from.
It depends what you're trying to do here. On line 33, do you want to show all the items, or just the previous item to be added?
The error you're getting is that the variable "items" doesn't exist. If you just want to show the previous item to be added, then you can replace the word "items" with "item", and move the line where you declare "item" to outside the switch statement, to look like this:
static void Main(string[] args)
{
bool myBool = true;
var item;
while (myBool)
{
Console.WriteLine("Welcome");
Console.WriteLine("[1] - add item");
Console.WriteLine("[2] - see content");
Console.WriteLine("[3] - erase content");
Console.WriteLine("[4] - close");
int input = Convert.ToInt32(Console.ReadLine());
switch (input)
{
case 1:
Console.WriteLine("add item");
item = (Console.ReadLine());
Console.WriteLine("you just added: " + item);
break;
case 2:
Console.WriteLine("items added: " + item);
break;
case 3:
myBool = false;
break;
}
Now, we're declaring the variable item in the Main method rather than in the switch statement. Before, when you were declaring it in the switch statement, it was being reset every time you restarted the loop. Now, when the user changes it by inputting a value, it will be saved when you go back to the start of the loop, and so if the user inputs "2", they will be shown the last item they inputted.
If you want the user to be shown every item they have inputted, you'll need to use an array or collection.
Total beginner here, literally started learning programming for the first time in my life yesterday, so please don't judge!
I'm trying to make a program that allows the user to enter the name and score of videogames, then show these scores upon request. I'm trying to make a menu. I noticed the program would crash if the user presses enter without entering any number, and I wanted to avoid that, but I'm stuck. If I press enter it doesn't crash. However, if I enter 1 or 2, the menu keeps going anyways, and if I press enter without entering anything after that, then it crashes? I'm lost.
namespace videogaems
{
class Program
{
static void Main(string[] args)
{
menu();
}
static void menu()
{
int option = 0;
Console.WriteLine("Select what you want to do: ");
Console.WriteLine("1- add game");
Console.WriteLine("2- show game rating");
bool tryAgain = true;
while (tryAgain)
{
try
{
while (option != 1 || option != 2)
{
option = Convert.ToInt32(Console.ReadLine());
tryAgain = false;
}
}
catch (FormatException)
{
option = 0;
}
}
}
Convert.ToInt32(Console.ReadLine()) will throw an exception if the string cannot be converted to an integer. Instead, you should use int.TryParse, which takes in a string and an out parameter that gets set to the converted value (if successful). It returns a bool which indicates if it was successful or not.
For example, the following code will loop as long as int.TryParse fails, and when it succeeds, userInput will contain the converted number:
int userInput;
while (!int.TryParse(Console.ReadLine(), out userInput))
{
Console.WriteLine("Please enter a whole number");
}
Another option, however, is to simply use Console.ReadKey(), which returns a ConsoleKeyInfo object that represents the key that the user pressed. Then we can just check the value of the key character (and ignore any keys that are invalid).
For example:
static void Menu()
{
bool exit = false;
while (!exit)
{
Console.Clear();
Console.WriteLine("Select what you want to do: ");
Console.WriteLine(" 1: Add a game");
Console.WriteLine(" 2: Show game rating");
Console.WriteLine(" 3: Exit");
ConsoleKeyInfo userInput = Console.ReadKey();
Console.WriteLine();
switch (userInput.KeyChar)
{
case '1':
// Code to add a game goes here (call AddGame() method, for example)
Console.Clear();
Console.WriteLine("Add a game was selected");
Console.WriteLine("Press any key to return to menu");
Console.ReadKey();
break;
case '2':
// Code to show a game rating goes here (call ShowRating(), for example)
Console.Clear();
Console.WriteLine("Show game rating was selected");
Console.WriteLine("Press any key to return to menu");
Console.ReadKey();
break;
case '3':
// Exit the menu
exit = true;
break;
}
}
}
I'm trying to make a simple menu where you select one option or the other to proceed. Instead of "yes" or "no" this menu uses "read" or "write" as the two options but the concept is of course the same. The code looks like this...
public void Start()
{
char selection;
do
{
Console.WriteLine("Would you like to read (r) or write (w) to a file?");
selection = (char) Console.Read();
} while (selection != 'r' || selection != 'w');
}
Now not only does this not stop looping when you DO type in either 'r' or 'w' but it types out 3 lines of the WriteLine text after you press enter anytime after.
Can anyone shed some light on how to fix this? I'm assuming I'm improperly using the Read() method but being the newbie that I am I find it hard to simply trial and error my way through some things. Any help at all would be amazing. Thank you in advance.
EDIT
public void Start()
{
char selection = 'y';
while(selection == 'y')
{
Console.Write("Would you like to continue...");
selection = (char)Console.Read();
Flush();
}
}
public void Flush()
{
while(Console.In.Peek() != -1)
{
Console.In.Read();
}
}
selection != 'r' || selection != 'w' is always true. If selection is r, then the selection != 'w' part is true, and if selection is not r, then the selection != 'r' part is true, so you either have false || true (which is true), or true || ... (the latter operand doesn't matter) which is also true.
You probably want while (selection != 'r' && selection != 'w').
Console.Read() will give you the characters as they are typed. As soon as they type the 'r' is stops. Isn't that what you want?
Hitting ENTER actually generates 2 characters, so it will print out the prompt 2 more times.
Maybe you just want this:
public void Start()
{
char selection;
Console.WriteLine("Would you like to read (r) or write (w) to a file?");
do
{
selection = (char) Console.Read();
} while (selection != 'r' && selection != 'w');
}
Another way to resolve your question is break the loop with a break call and then return the inserted value.
Example:
class Program
{
static void Main(string[] args)
{
char selection = read_or_write();
Console.WriteLine("char in main function: "+selection);
Console.WriteLine("press enter to close");
Console.ReadLine(); //clean with enter keyboard
}
public static char read_or_write()
{
char selection;
Console.WriteLine("Would you like to read (r) or write (w) to a file?");
do
{
selection = (char)Console.Read();
Console.ReadLine();//clean with enter keyboard
if (selection == 'r')
{
Console.WriteLine("You pressed r");
break;
}
else if (selection == 'w')
{
Console.WriteLine("You pressed w");
break;
}
else
{
Console.WriteLine("You pressed a wrong key!");
}
} while (selection != 'r' || selection != 'w');
return selection;
}
}