Aafflalo
Aafflalo

Reputation: 25

possibility of writing a switch-case condition inside a switch-case condition?

I have this code which runs the way it is supposed to do. But I want to implement something extra if a user clicks either 1, 2 or 3 once the first value has been inserted. As you can see if a user press 2 the second time, a list of players by first name will show (at least that is my intention). So my question is if this can be done by inserting a switch-case condition inside of the previous? I have tried something like this: See further below for more code.

 var isValidMenuItem = false;

        while (!isValidMenuItem)
            isValidMenuItem = Menu();

        Console.WriteLine();
        Console.ReadKey(true);

    }

    private static bool Menu()
    {
        Console.WriteLine("You have now entered the 2017 Wimbledon tournament!" + "\n" + "\n");
        Console.Write("Choose one of the 6 options:" + "\n" + "Press 1 for Default tournament:" + "\n" + "Press 2 for Women's single:" + "\n" +
            "Press 3 for Men's single:" + "\n" + "Press 4 for Women's double:" + "\n" + "Press 5 for Men's double:" + "\n" +
            "Press 6 for Mix double:" + "\n" + "Insert your choice...: ");

        var userValue = Console.ReadKey().KeyChar;
        Console.WriteLine();

        switch (userValue)
        {
            case '1':
                Console.WriteLine("\n"+ "You have entered a default tournament");
                break;
            case '2':
                Console.WriteLine("\n" + "You have entered women's single");
                Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" + 
                    "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
                break;
            case '3':
                Console.WriteLine("\n" + "You have entered men's single");
                Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" +
                    "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
                break;
            case '4':
                Console.WriteLine("\n" + "You have entered women's double");
                Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" +
                    "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
                break;
            case '5':
                Console.WriteLine("\n" + "You have entered men's double");
                Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" +
                    "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
                break;
            case '6':
                Console.WriteLine("\n" + "You have entered mix double");
                Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" +
                    "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
                break;
            default:
                Console.WriteLine("\n" + "Sorry! You have to choose one of the 6 tournament options");
                return false;
        }

Like this: ... But it doesn't seem to work? Do you guys have any ideas?

         case '2':
                Console.WriteLine("\n" + "You have entered women's single");
                Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" + 
                    "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
                {
                    switch (userValue)
                    {
                        case '1':
                            Console.WriteLine("Hello");
                            break;
                    }
                    break;
                }

Upvotes: 2

Views: 107

Answers (7)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236318

First of all, you don't need nested switches here. You have to select two things in a consecutive way:

  1. Tournament type
  2. Action for selected tournament type

So, you can create the enum for tournament type:

public enum TournamentType
{
    Default,
    SingleWomen,
    SingleMen,
    DoubleWomen,
    DoubleMen,
    DoubleMix
}

Then you need to get selected option. You can use switch statement here, but you can also create an option selector class:

public class OptionSelector<T>
{
    private readonly List<Option> options = new List<Option>();
    public T SelectedOption { get; private set; }

    public OptionSelector<T> WithOption(T value, string title)
    {
        options.Add(new Option { Value = value, Title = title });
        return this;
    }

    public bool SelectOption()
    {
        if (!options.Any()) return true;            

        Console.WriteLine($"Choose one of the {options.Count} options:");    
        for(int i = 0; i < options.Count; i++)
            Console.WriteLine($" {i + 1} - {options[i].Title}");

        Console.Write("Your choice: ");
        var key = Console.ReadKey().KeyChar;
        Console.WriteLine();    
        int choice = key - '0';
        if (!Char.IsDigit(key) || choice == 0 || options.Count < choice) {
            Console.WriteLine($"Sorry, only digits 1..{options.Count} are allowed");
            return false;
        }

        SelectedOption = options[choice - 1].Value;
        return true;
    }

    private class Option {
        public T Value { get; set; }
        public string Title { get; set; }
    }
}

Few lines of code, but good functionality - this class allows to build a set of options in the fluent way and then accept user input. If input is valid, then selected option will be available via SelectedOption property. Otherwise verbose error message will be displayed. Nice thing here is that options selector is a generic class. Each option can be literally anything - integer, string, enum value, or even a method. With this class all your code can be collapsed to:

Console.WriteLine($"You have now entered the 2017 Wimbledon tournament!\n");
var tournamentTypeSelector = new OptionSelector<TournamentType>()
    .WithOption(TournamentType.Default, "Default tournament")
    .WithOption(TournamentType.SingleWomen, "Women's single")
    .WithOption(TournamentType.SingleMen, "Men's single")
    .WithOption(TournamentType.DoubleWomen, "Women's double")
    .WithOption(TournamentType.DoubleMix, "Mix double");

while (!tournamentTypeSelector.SelectOption()) { /*Console.Clear();*/ }

var tournamentType = tournamentTypeSelector.SelectedOption;
var actionSelector = new OptionSelector<Action>()
    .WithOption(() => StartTournament(tournamentType), "Start the tournament")
    .WithOption(() => Console.WriteLine("Not implemented"), "List players by first name")
    .WithOption(() => Console.WriteLine("Not implemented"), "List players by last name");

while (!actionSelector.SelectOption()) { /*Console.Clear();*/ }
actionSelector.SelectedOption(); // invoke selected action

Woo-hoo! No switches at all

First selector here selects tournament type. Second selector selects an actionto be invoked. And the nice thing here is that you can pass arguments to those actions (e.g. tournament type). Btw StartTournament is the method which contains corresponding functionality:

private static void StartTournament(TournamentType tournamentType)
{
    // your code here
    Console.WriteLine("Tournament started");
}

Check the Fiddle to see how it works. Note that fiddle dont support Console.ReadKey so you should press enter each time.

Upvotes: 0

B Wyss
B Wyss

Reputation: 45

Switch inside a switch should work!

int x = 1;

    switch(x)
    {
        case 1: // Enters Here cause x = 1
            Console.WriteLine("test"); //prints
            switch(x) // x still = 1
            {
                case 1: //enters here cause x = 1
                Console.WriteLine("works"); //prints
                break;
            }
            break;
        default:
            Console.WriteLine("doesnt work");
            break;
    }

(Output will be: "test" "works")

you just happened to write weird "{}", is that the problem?

If you want to enter different Switch cases you have to change the value of the switch(value) to enter different cases.

In your case thats:

case '2':
            Console.WriteLine("\n" + "You have entered women's single");
            Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" + 
                "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
            //Ask for a new input here = (NEWVALUE)
            switch (NEWVALUE)
            {
                case '1':
                Console.WriteLine("Hello");
                break;
            }
            break;

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727077

Apart from hurting readability, nesting a switch inside another switch is fine. The language fully supports it.

In your case your switch does not work because you are switching on a variable that has not changed since entering the outer switch, so the construct is effectively useless. Add code to modify userValue before entering the nested switch, like this:

case '2':
    Console.WriteLine("\n" + "You have entered women's single");
    Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" + 
        "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
    var userChoice = Console.ReadKey().KeyChar; // <<<<<==== Add this line
    switch (userChoice) {
        case '1':
            Console.WriteLine("Hello");
            break;
    }
    break;

Upvotes: 0

LocEngineer
LocEngineer

Reputation: 2917

You need to re-read the value first.

case '2':
    Console.WriteLine("\n" + "You have entered women's single");
    Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" +
        "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
    userValue = Console.ReadKey().KeyChar;
    {
        switch (userValue)
        {
            case '1':
                Console.WriteLine("Hello");
                break;
        }
    }
    break;

Upvotes: 0

DevRenanGaspar
DevRenanGaspar

Reputation: 373

It seems to me there is an extra curly brackets there? Isn't it? Shouldn't it be:

  case '2':
            Console.WriteLine("\n" + "You have entered women's single");
            Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" + 
                "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
             switch (userValue)
             {
                 case '1':
                     Console.WriteLine("Hello");
                     break;
                 default
                     return false;
             }
             break;

Upvotes: 0

FreezyLemon
FreezyLemon

Reputation: 11

The switch statement itself should be fine as is.

The problem lies within the variable userValue. You only evaluate var userValue = Console.ReadKey().KeyChar; once, so the value is set to that one key value.

For instance, in your example, the outer switch statement enters case '2', because that is what userValue is set to. But then, when entering the inner switch statement, it uses the same value AGAIN since the ReadKey() function is not evaluated again. So then your switch statement will see "userValue" as 2 without even expecting or waiting for any input at all, so it just falls out of the switch.

EDIT here: You could just call the ReadKey() function again to solve this, or use a second variable:

//Inner switch statement:
//{ (bracket is redundant)
    userValue = Console.ReadKey().KeyChar;
    switch (userValue)
    {
        // switch body here...
    }
//}

Upvotes: 1

Torben
Torben

Reputation: 478

There are two things in your code

First

if your switch value is the same, as it is in your code, it can´t work, because one variable can only have one value.

Second

Remove the brackets

case '2':
                Console.WriteLine("\n" + "You have entered women's single");
                Console.Write("Press 1 to start the tournament:" + "\n" + "Press 2 to list the players by first name:" + "\n" + 
                    "Press 3 to list the players by last name:" + "\n" + "Insert your choice...: ");
                //{          <- remove
                    switch (userValue)
                    {
                        case '1':
                            Console.WriteLine("Hello");
                            break;
                    }
                    break;
                //}          <- remove

Upvotes: 0

Related Questions