Skip to content

C# Adventure 12: Menu-Driven Navigation

In this chapter we'll create an alternative framework that incorporates some new concepts: checking for numeric values, recursion, TryParse, and tracking player success.

Alternative Framework

Now that you are more familiar with C#, you could take a different approach to your game's framework. There are many ways to create applications, and the way that we built this game isn't the only option. We've used certain structures to cover a variety of fundamental concepts, and so that you would have examples of how they work.

Let's test your C# knowledge by walking through the creation of an alternative framework. For each task write the code in your project before you check the example code.

Menu Driven Structure

The game we've built is a branching narrative which focuses on moving through several scenarios. If you wanted a game that was centered around exploration, for example, a menu-driven option might be a better choice.

Alternative framework example
Alternative framework example
Alternative framework example: menu driven
Alternative framework example: menu driven

Create A New Project

Create a new console application project in Visual Studio.

You can name your project whatever you like.

How much have you learned? For each task write your own code before looking at the example. If you get stuck, there are code examples to help, but it is important for you to try on your own first!

Game Class

The Game and Program class structure is almost identical to the ones in our first project.

Game
Run: Boolean
Choice: Integer
Goal: Boolean
Start()
End()
Play()
Menu()
Program
[no attributes]
Main()

Add a Game class. Inside create three static properties as diagrammed above. Initialize Run as true, and Goal as false.

Framework with Static Properties

using System;

namespace ExplorationGame
{
    class Game
    {
        static bool Run = true;
        static int Choice;
        static bool Goal = false;

    class Program
    {
        static void Main()
        {
            
        }
    }
}

Game Methods

Create four static methods in the Game class: Menu, Start, End, Play.

Framework with Game Methods

using System;

namespace ExplorationGame
{
    class Game
    {
        static bool Run = true;
        static int Choice;
        static bool Goal = false;

        public static void Menu()
        {
           
        }
        public static void Start()
        {
          
        }
        public static void End()
        {
           
        }
        public static void Play()
        {
           
        }
    }
    class Program
    {
        static void Main()
        {
            
        }
    }
}

Invoke Play

Inside of Program's Main method, add a statement that calls Game's Play method. We won't be making an instance of our Game class, so you can just use the class name.

Method Call

using System;

namespace ExplorationGame
{
    class Game
    {
        static bool Run = true;
        static int Choice;
        static bool Goal = false;

        public static void Menu()
        {
           
        }
        public static void Start()
        {
          
        }
        public static void End()
        {
           
        }
        public static void Play()
        {
           
        }
    }
    class Program
    {
        static void Main()
        {
            Game.Play();            
        }
    }
}

Start Method

Create a Start method. The Start method will have several statements. First, it will clear the console window. Then introductory text to outline a goal. Finally, a ReadLine and an instruction for the player (such as "press enter to continue").

Start Method

using System;

namespace ExplorationGame
{
    class Game
    {
        static bool Run = true;
        static int Choice;
        static bool Goal = false;

        public static void Menu()
        {
           
        }
        public static void Start()
        {
            Console.Clear();
            Console.WriteLine("Adventure Game");

            Console.WriteLine("introductory text to outline a goal");
            Console.WriteLine("press enter to continue");
            Console.ReadKey();
        }
        public static void End()
        {
           
        }
        public static void Play()
        {
           
        }
    }
    class Program
    {
        static void Main()
        {
            Game.Play();            
        }
    }
}

End Method

Add an end method. The End method will check to see if the objective was accomplished. The objective is tracked with Goal; if Goal is true the player is congratulated, and the game exits. Otherwise a suggestion is shown that the player should try again, and the player is brought back to the start of the game.

End Method

public static void End()
{
    if (Goal)
    {
	Console.WriteLine("Success!");

	Console.WriteLine("Press enter to continue...");
	Console.ReadLine();
    }
    else
    {
	Console.WriteLine("Try again!");

	Console.WriteLine("Press enter to continue...");
	Console.ReadLine();
	Run = true;
	Play();
    }           
}

Play Method

Create a Play Method. First, the Play method will call the Start method. Next is a loop. Inside the loop is a call to the Menu method. As long as Run is true, the game will show the Menu and wait for player input. If Run is false, the loop will stop and the End method is invoked.

Play Method

public static void Play()
{
    Start();
    while (Run == true)
    {
	Menu();
    }
    End();
}

Menu Method Overview

Add a Menu Method.

The Menu method will clear the console window and print out a menu. Depending on what choice the player enters, different content is shown. When the option to quit or exit is chosen, Run will be set to false which will end the loop in the Play method. The End method will then run.

This is where the bulk of your content will go. Within each of the case statements you can build out what the location looks like, and what is happening there. You can even have smaller menus inside each case if you have location specific options. Perhaps there are people the player can talk to? Actions they can take?

Checking Input and Recursion

If the player enters a number out of the range we've asked for (for example, something that isn't 1-5 in the example below), we can have a default case statement which will remind them to choose within the range. After they read the message and press enter, we'll make a recursive call to the Menu.

Recursion is when a method calls itself. It can be very helpful, but you need to be careful that it doesn't become an infinite loop, or a loop that will run excessively.

Menu Method

public static void Menu()
{
    Console.Clear();
    Console.WriteLine("1) A 2) B 3) C 4) D 5) Exit");
    Choice = Convert.ToInt32(Console.ReadLine());
    if (Choice == 5)
    {
	Run = false;
    }
    else
    {
	switch (Choice)
	{
	    case 1:
		Console.WriteLine("A content...");
		//content here....
		Console.WriteLine("Press enter to continue...");
		Console.ReadLine();
		break;

	    case 2:
		Console.WriteLine("B content...");
		//content here....
		Console.WriteLine("Press enter to continue...");
		Console.ReadLine();
		break;

	    case 3:
		Console.WriteLine("C content...");
		//content here....
		Console.WriteLine("Press enter to continue...");
		Console.ReadLine();
		break;

	    case 4:
		Console.WriteLine("D content...");
		//content here....
		Console.WriteLine("Press enter to continue...");
		Console.ReadLine();
		break;
	    default:
		//if a number other than 1-5 is entered, request
		//player enter a number in that range
		//wait for them to press enter, then call
		//the menu again
		Console.WriteLine("Please enter a number 1-5.");
		Console.WriteLine("Press enter to continue...");
		Console.ReadLine();
		Menu();
		break;
	}
    }
}

Checking for Numeric Values

What if the player types a letter instead of a number at the menu prompt? Have you tried it?

We can check to make sure that the player is entering the type of information we've requested with a few more lines of code. We'll save what the player types, then check to see if it is a number.

Add another static string to the Game class. In the example it is named "Input".

class Game
{
    static bool Run = true;
    static int Choice;
    static string Input;
    static bool Goal = false; 
[...]

After the menu is written to the console window, read in what the player types and save it as Input. This will replace the statement that is currently there; the one that reads in what the player enters and saves it as Choice.

Console.WriteLine("1) A 2) B 3) C 4) D 5)Exit");
Input = Console.ReadLine();

TryParse

To check whether or not what was entered is a number, we'll use TryParse. TryParse tries to convert a value to a number. If it is successful, it returns a value.

Our if/else and switch statements will be nested within another conditional statement. We will be checking to see if the TryParse method returns a value. If it does, then Input is a number and that number will be saved as Choice.

What if a value isn't returned? That means that TryParse was not successful, and what the player entered is not a number. We can print out a message requesting that the correct input is entered. Just like in the default for the switch statement we'll wait for them to read the message and press enter, then make a recursive call to the Menu function.

Update your code to check whether player input is a number.

Input = Console.ReadLine();
if (int.TryParse(Input, out Choice))
    {
	if (Choice >= 5)
	{
	    Run = false;
	}
	else
	{
	   //switch statement here
	}
    }
    else
    {
	Console.WriteLine("Please enter a number 1-5.");
	Console.WriteLine("Press enter to continue...");
	Console.ReadLine();
	Menu();
    }

Player Success

We want to track when the player accomplishes the goal, but that could happen in multiple places depending on how you build out your content.

Wherever the player accomplishes the game goal add this code:

Goal = true;
Run = false;

This will move the player to the game's end. If Run is false, when the player hits enter to continue the End method will be called (instead of showing the menu again). Once the End method runs, if Goal is true a success message will be displayed.

You've created another framework option for your game!

This is just one of many possibilities. Can you think of another? Can you write up a framework for it?

Next Step

In the next section we will finish up the series!