0

Sorry if this is similar to an existing question - I did try looking!

Anyhow, I've got a program going as follows:

    static void Main(string[] args)
    {
        string temp;

        Console.WriteLine("question");
        temp = Console.ReadLine();

        if (temp == "a")
        {
            Console.WriteLine("Incorrect");
        }
        if (temp == "b")
        {
            Console.WriteLine("Incorrect");
        }
        if (temp == "c")
        {
            Console.WriteLine("Correct");
        }
        else
        {
            Console.WriteLine("Not a valid response");
        }

    }

And I'm trying to get it to ignore invalid responses until I give a valid response. If for example, I needed to press the key a, or b, or c but I pressed d, it would just tell me my answer isn't a valid option and wait until I gave a valid response.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
Joshua
  • 41
  • 3
  • 1
    you need a do...while loop. Console. Input till the user makes sense? That is what it is there for! Also those if's really look like they should be a swtich/case statement. – Christopher Feb 11 '20 at 15:30
  • Does this answer your question? [How to loop a Console App](https://stackoverflow.com/questions/1754282/how-to-loop-a-console-app) – 41686d6564 stands w. Palestine Feb 11 '20 at 15:31

4 Answers4

1

You can implement (extract) a method:

 private static char AnswerTheQuestion(string question, int answers) {
   Console.WriteLine(question);

   // Loop until...
   while (true) {
     // Let's be nice and tolerate leading / trailing spaces
     string answer = Console.ReadLine().Trim();

     if (answer.Length == 1) {
       char result = char.ToLower(answer[0]); // let's ignore case ('A' == 'a' etc.)

       if (result >= 'a' && result <= 'a' + answers)
         return result; // ...user provide an answer in expected format
     }

     // Comment it out if you want just to ignore invalid input 
     Console.WriteLine($"Sorry, provide an answer in [a..{(char)('a' + answers)}] range");
   }
 }

Then you can use it:

   static void Main(string[] args) { 
     char result = AnswerTheQuestion(string.Join(Environment.NewLine,
           "What is the capital of Russia?",
           "  a. Saint-Petersburg",
           "  b. Moscow",
           "  c. Novgorod"),
       3);

     Console.WriteLine($"{(result == 'b' ? "correct" : "incorrect")}");

     Console.ReadKey(); 
   }
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • I like this solution, however when I apply it, there's an error with this line: Console.WriteLine($"{(answer == 'b' ? "correct" : "incorrect")}"); The name answer doesn't exist within this context, am I doing something wrong or does this need correcting? – Joshua Feb 12 '20 at 00:13
  • @Joshua: I am sorry for the typo it should have been `result`, not `answer`; please, see my edt – Dmitry Bychenko Feb 12 '20 at 04:05
1

Not sure if this is what you intend:

public static void Main()
        {
            Console.WriteLine("question");
            bool tryAgain;
            do
            {
                tryAgain = true;
                var key = Console.ReadKey();
                switch (key.KeyChar)
                {
                    case 'a':
                    case 'b':
                        Console.WriteLine();
                        Console.WriteLine("Incorrect");
                        tryAgain = false;
                        break;
                    case 'c':
                        Console.WriteLine();
                        Console.WriteLine("Correct");
                        tryAgain = false;
                        break;
                    default:
                        Console.Write("\b \b");
                        break;
                }
            } while (tryAgain);
        }

All inputs are ignored except valid inputs ('a', 'b', 'c') if you type 'd' inputs is ignored.

UPDATE this version works with Enter to confirm input:

public static void Main()
        {
            Console.WriteLine("question");
            bool tryAgain;
            bool enterPressed;
            char input = ' ';
            do
            {
                enterPressed = false;
                do
                {
                    tryAgain = true;
                    var key = Console.ReadKey();
                    switch (key.KeyChar)
                    {
                        case 'a':
                        case 'b':
                        case 'c':
                            input = key.KeyChar;
                            tryAgain = false;
                            break;
                        default:
                            Console.Write("\b \b");//Delete last char
                            break;
                    }
                } while (tryAgain);
                var confirmkey = Console.ReadKey();
                if (confirmkey.Key == ConsoleKey.Enter)
                {
                    enterPressed = true;
                    Console.WriteLine();
                }
                else
                {
                    Console.Write("\b \b"); //Delete last char
                }
            } while (!enterPressed);
            switch (input)
            {
                case 'a':
                case 'b':
                    Console.WriteLine("incorrect");
                    break;
                case 'c':
                    Console.WriteLine("correct");
                    break;
            }
        }
Stefano Balzarotti
  • 1,760
  • 1
  • 18
  • 35
  • You got a empty WriteLine() in the a/b case? Usually inputs are confirmed with Enter, wich also does a newline. – Christopher Feb 11 '20 at 15:48
  • Yes because I used ReadKey instead of ReadLine, ReadLines adds a breackpoint automatically. If you use ReadLine, you cannot ignore the input. but I can add confirm with enter, if you need. – Stefano Balzarotti Feb 11 '20 at 15:52
0
void Main()
{
    string temp;

    Console.WriteLine("question");
    while (true)
    {
        temp = Console.ReadLine();

        if (temp == "a")
            Console.WriteLine("Incorrect"); 
        else if (temp == "b")
            Console.WriteLine("Incorrect");
        else if (temp == "c")
            Console.WriteLine("Correct");
        else if (temp == "exit") // providing a way to exit the loop
            break;
        else { } // ignore input            
    }
}

AliReza Sabouri
  • 4,355
  • 2
  • 25
  • 37
0

This is the textbook case for both do...while loops and switch/case statements. Asuming "a" is still a valid input:

bool validInput = false;

do{
  Console.WriteLine("question");
  string input = Console.ReadLine();

  switch(input){
    case "a":
      Console.WriteLine("Incorrect");
      validInput = true;
      break;
    //other cases and default omitted
  }

}while(!validInput);
Christopher
  • 9,634
  • 2
  • 17
  • 31
  • Just had to move the question outside of the loop & worked exactly how I specified, thank you! As for cleaner code, is yours or the other answer a 'better solution', if there's even an objective one? If not, what's the difference? – Joshua Feb 11 '20 at 15:41
  • @Joshua a switch...case is how you usually do with menus/input validation in Console. The other construct is a `TryParse()`. Both wrapped into a do...while "until the user starts making sense" (having the control at the back, guarantees at least one execution, but unlimited options for repition). The issue with the if/else thing is, that multiple cases could match. `"a"` would be incorrect. But also trigger the else region on exit. When you propably only want it triggered when *none* of the other cases apply. that is something switch's default case will handle. – Christopher Feb 11 '20 at 15:45
  • @Joshua Of course Stefano's answer is propably the best. – Christopher Feb 11 '20 at 15:47