We'll create a game where the player will try to guess a random number. Fundamental programming concepts will be covered as we build the C# console application.
Numeric Guessing Game Framework
The framework for our game will have two classes: Program and Game. A method (Play) in the Game class will hold the statements that will run the game.
Two variables will be used. One to track the number the player enters (Guess), and one that will be the target number (Target).
Program |
---|
[no attributes/properties] |
Main() |
Game |
---|
Guess: integer Target: integer |
Play() |
Program Class Changes
Add a call in Main to Game's Play method. That will be our only addition to the Program class.
class Program { static void Main() { Game.Play(); } }
Why Main?
Program's Main method is the entry point to the application. Statements within Main run first when the application is launched. To have our Play method start, we call it from inside Main.
Modifiers: Static and Public
Add the keyword static to the Play method and our variables. We'll make this game without creating an instance of our Game class. After we've finished, we'll make another game that does instantiate the Game class so you can have a comparison of the two approaches.
We also need to add the keyword Public to our Play method so that we can access it from Main.
Our skeletal framework is now set up:
using System; namespace GuessingGame { class Game { static int Guess; static int Target; public static void Play() { //statements to run the game } } class Program { static void Main(string[] args) { Game.Play(); } } }
Player Instructions
Now that we have a starting point, let's add some statements to the Play method. First we should write out an instruction to our player. We can make it simple or fanciful.
A simple statement would be something along the lines of "Enter a number:". A more creative example would be "I look deep into the depths of my crystal ball and see a number floating to the surface. Can you guess what it is?". Write an instruction for the player in whichever style you like.
Player Input
For the first version we can just assume that when we ask for a number, a number will be given. Later we can add code to check for the correct type of input. We'll use a Console.ReadLine() to read in what the player types.
Guess = Console.ReadLine();
Type Conversion
The ReadLine() method reads input as a string. To compare what the player types to a number, we'll need to convert it to a numeric value. There are several ways to convert data. In this example we'll use Convert.ToInt32().
We could convert player input from a string to a number in two steps:
string GuessInput = Console.ReadLine(); Guess = Convert.ToInt32(GuessInput)
Or we could do the same thing in just one step. We can pass Console.ReadLine() to Convert.ToInt32() as an argument:
Guess = Convert.ToInt32(Console.ReadLine());
Feedback
Add another line that let's the player know if they guessed the number correctly.
Console.WriteLine("You guessed " + Guess + " and the number I was thinking of was " + Target);
Code Progress
To test out our code, let's give Target a value:
static int Target = 5;
We also want to call Console's ReadKey() method. ReadKey() accepts single key input (such as the player clicking the enter key or the spacebar). A side effect of using Readkey() is that the console window stays open, allowing the player to read the results. Otherwise the window would close fast, and the player wouldn't have time to read text on the screen. There are many other ways to keep the console window open; we are using this option because it is simple for new programmers.
With these changes in place, test your application and see if everything is working correctly.
Example Code: Numeric Guessing Game 1.0
using System; namespace GuessingGame { class Game { static int Guess = 0; static int Target = 5; public static void Play() { Console.Write("Guess what number I am thinking of... "); Guess = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("You guessed " + Guess + " and the number I was thinking of was " + Target); Console.ReadKey(); } } class Program { static void Main() { Game.Play(); } } }
Conditional Statements
The game tells the player what they entered, and what the target number was. It doesn't congratulate them if they got it right, or give a different message if the numbers don't match. We need a conditional statement so separate messages can be shown for each situation.
Add your own style of message to the code below where the comments indicate.
if (Guess == Target) { //match - congratulations! } else { //no match - try again }
Random Number
We currently have a hard-coded number as the target. After the first time someone plays, they'll know the answer and playing again won't be much fun.
We can use .NET Framework's Random to make it less predictable. At the top of the Game class create an instance of Random, and add the keyword static.
class Game { static int Guess = 0; static int Target = 5; static Random RandomNumber = new Random(); [...]
Inside our Play method call the Next method, and pass in an integer representing the range of numbers it should pull a random number from. Save the value returned (with + 1) as Target.
Target = RandomNumber.Next(10) + 1;
Usually in a guessing game we ask for a number in a range that starts with 1. For example, "Guess a number between 1 and 10". Without the +1 the range of numbers in the above line of code would be 0 to 9. Adding +1 the range is now 1 to 10.
The Next method is overloaded so you could alternatively pass in two values that would return a range between them. For example, to return values 1 through 10 you would use:
RandomNumber.Next(1, 11)
Let the player know what the range of numbers is by updating the instructions that are written to the console window.
public static void Play() { Target = RandomNumber.Next(10) + 1; Console.Write("Guess what number between 1 and 10 I am thinking of... "); [...]
Numeric Values (TryParse)
Let's check to make sure that the player is entering the type of information we are asking for. Right now if the player accidentally enters a letter instead of a number, there will be an error. Using TryParse we can check to see if Guess is a numeric value.
Add another variable to the Game class - Input. This will be a string. If the value of the string is numeric, we'll save it as Guess.
class Game { static int Guess = 0; static int Target = 5; static string Input = ""; static Random RandomNumber = new Random(); [...]
Within the first set of curly braces in our new conditional, we can put the code that should run if the Input is a number. In the else block we can ask the player to make sure they are entering a number and to try again. A recursive call to Play() will start the game code again so they can give it another try.
if (int.TryParse(Input, out Guess)) { //It is a number } else { //it isn't a number }
Example Code
After adding these last elements, we have a working version of the game.
Example Code: Numeric Guessing Game 1.5
An example of a Numeric Guessing Game.
using System; namespace GuessingGame { class Game { static int Guess = 0; static int Target = 5; static string Input = ""; static Random RandomNumber = new Random(); public static void Play() { Target = RandomNumber.Next(10) + 1; Console.Write("Guess what number I am thinking of... "); Input = Console.ReadLine(); if (int.TryParse(Input, out Guess)) { if (Guess == Target) { Console.WriteLine("Congratulations! You guessed " + Guess + " and the number I was thinking of was " + Target + "."); } else { Console.WriteLine("Too bad. You guessed " + Guess + " and the number I was thinking of was " + Target + ". Try again!"); } } else { Console.WriteLine("Please enter a number."); Console.WriteLine("Press enter to continue..."); Console.ReadLine(); Play(); } Console.ReadKey(); } } class Program { static void Main() { Game.Play(); } } }
Finishing Touches
Now that you have a functional example, can you improve the interface and make it look more interesting?
- Design elements: Console Application ASCII Design
- Color: Console Application Color: Text and Background
- Console window properties: Console Application Window Properties
Next Step
Compare the approach taken with this numeric guessing game to another; make a version that instantiates the Game class and asks the player to guess a random word instead of a number. Word Guessing Game: C# Console Application