Branching Logic is the ability of a program to execute code paths dependent on specified conditions. This process allows user’s to guide the direction of the application. Branching logic can be implemented using conditional statements such as if-else statements or switch statements. To demonstrate branching logic in this post, we’ll walk through a Rock, Paper, Scissors(RPS) game together. We’ll explain the project setup, the branching logic, and much more. Let’s get started!
RPS Prompt
Create a console application that allows the user to play a game of rock-paper-scissors against the computer. The program should prompt the user to choose rock, paper, or scissors, and then generate a random choice for the computer. After both choices have been made, the program should determine the winner based on the following rules:
- Rock beats scissors
- Scissors beats paper
- Paper beats rock
The program should display the result of the game, along with a message that indicates whether the user has won, lost, or tied with the computer. After the game is finished, the program should prompt the user to play again or exit the program.
To accomplish this, you will need to use the Console class in C# to prompt the user for input, generate random values, and display output to the console. You will also need to use conditional statements to determine the winner of the game based on the user’s choice and the computer’s choice.
Project Setup
We’ll begin by opening a Visual Studio Console App with the title RockPaperScissors. Visual Studio is on v17.5.3 and running on .NET 6.0 during the creation of this post.
NOTE: Have a pen and paper with you to quickly sketch up ideas are solve math problems on the fly.
Create another class named Game.cs in your Solution Explorer with shortcut Ctrl+Alt+A or navigate Project>Add Class in the main toolbar.
Rock, Paper, Scissors!
We’ll create the foundations of the RPS game using fields, a constructor, and methods. A class diagram will help prepare the structure of the project.
Our game is projected to contain four fields and seven methods. Notice that the RandomGenerator field is using data type ‘Random’. This field will use C#’s Random Class to generate a random integer for the computer’s choice.
Let’s transfer this diagram into code, beginning with fields, then a constructor, and then methods.
// FIELDS
private string GameName;
private string GameDescription;
private int Score;
// place holder for the RandomGeneration variable
private Random RandomGeneration;
Note: Random Class Documenation show’s us how to generate random numbers with desired bounds
The next elements to be built is the Constructor and then the Methods.
// METHODS
public Game()
{
// Initializes anything game related
}
public void Start()
{
// Starts the game with player's confirmation
}
public void PlayRound()
{
// Begins a round between player and computer
}
public void Win()
{
// Increases the score of the player and tells them they won
}
public void Lose()
{
// Tells player they've lost
}
public void Tie()
{
// Tells player they tied with computer
}
public void AnotherRound()
{
// Asks the player if they want to play again
}
public void Stop()
{
// Stops the game
}
Great, we’ve gotten the structure of the RPS game in order.
Now, let’s initialize the constructor and add in some intro code.
public Game()
{
// Initializes anything game related
// Intro
Score = 0;
RandomGeneration = new Random();
GameName = "Rock... Paper... Scissors!";
GameDescription = "Rules:\\n > Rock beats Scissors\\n > Paper beats Rock\\n > Scissors beats Paper" +
"\\nYou can choose between Rock, Paper, & Scissors.";
}
public void Start()
{
// Starts the game with player's confirmation
Title = GameName;
WriteLine($"GameName");
WriteLine(GameDescription);
}
Run the code above, what do you get?
Does it say ‘Hello World!’?
If it does, we’ll fix this problem by heading back into our Program.cs file and creating an instance of the Game class. We chose to name it myGame.
Game myGame = new Game();
mygame.Start();
The class Game serves as a blueprint and the instance myGame is an instance or an object of that blueprint. So, code that is created within the blueprint Game class, can now be accessed by the myGame instance. If you’d like to learn more about the concept of classes as blueprints, click here.
In this case, to start our game, we would invoke the Start() method within the Program.cs file.
You should see the following output:
Branching Logic
For this section, we want the computer to continue, end, or restart the game based on the user’s input. We’ll need to use the user’s input and an if-else statement to instruct the computer on its next steps.
public void Start()
{
// Intro code...
// Player's input
// Trim() and Lower() used to caputure more inputs of 'yes'
WriteLine("Are you ready to play? (yes/no)");
string playerReady = ReadLine().Trim().ToLower();
// Code to begin the game
if (playerReady == "yes")
{
PlayRound();
}
// This code will end the game
else if (playerReady == "no")
{
Stop();
}
// If choices other than yes/no entered, restart
else
{
Clear();
Start();
}
}
These three conditions alone are enough to capture any input made by the user. If and else if covers ‘yes’ and ‘no’, while else captures everything that is not ‘yes’ or ‘no’. Depending on the input, the computer will follow a branch of code that will be executed. Look at the flowchart of the PlayRound() to visualize this conditional process.
Sometimes, conditionals come with a lot of clutter due to their repetitive nature, so to keep that clutter to a minimum, we’ll call methods to replace multiple lines of code.
The PlayRound() method will generate the computer’s choice, input the player’s choice, and determine the results of the round.
To generate the computer’s choice, we use Random.Next() method and specific parameters from the documentation. RandomGenerator.Next(0,3) will give us a random number from 1-3.
Why do we need the numbers 1-3? The arbitrary rules below determine our computer’s choice:
- 1 = ‘rock’
- 2 = ‘paper’
- 3 = ‘scissors’
Rather than keeping the computer’s choice an integer, we’ll convert the numbers into strings using our rules and conditionals.
public void PlayRound()
{
// Begins a round between player and computer
Clear();
// Computer's Choice
string computerChoice;
WriteLine("I'm also ready to play!");
int randomChoice = RandomGenerator.Next(0, 3);
// Convert int computerChoice into string using conditionals
if (randomChoice == 0) computerChoice = "rock";
else if (randomChoice == 1) computerChoice = "paper";
else computerChoice = "scissors";
// TODO: Input player's choice
// TODO: Based on player and cpu's choice,
// determine the results
}
Note: You can view the Random class documentation here.
We can now prompt the user to input rock, paper, or scissors into the command terminal, and we will validate this input with one big if-else statement.
public void PlayRound()
{
// prev code...
// Player's Choice
WriteLine("Choose your weapon: rock/paper/scissors");
string playerChoice = ReadLine().Trim().ToLower();
// Branching Logic to determine winner
if (playerChoice == "rock" || playerChoice == "paper" || playerChoice == "scissors")
{
// TODO: Timer for dramatic effect
// TODO: Output the computer's choice
// TODO: Determine results using if-else statements
}
// Invalid entries get reset
else { PlayRound(); }
// As each round ends, ask player if they want to play again
AnotherRound();
}
Reminder: Run code after every section and to find and fix bugs efficiently.
We opted for a Thread.Sleep(), click for documentation. It’s not necessary, but it adds a little more realism and fun to the game.
// TODO: Timer for dramatic effect
WriteLine("\\nRock...");
Thread.Sleep(500);
WriteLine("Paper...");
Thread.Sleep(500);
WriteLine("Scissors...");
Thread.Sleep(500);
Although, an if-else statement works fine here, switch statements are great for fixed data values. An example of switch and its case is:
If computerChoice == “rock”, it will output “I chose rock!”.
// TODO: Output the computer's choice
switch (computerChoice)
{
case "rock":
WriteLine("I chose rock!");
break;
case "paper":
WriteLine("I chose paper!");
break;
case "scissors":
WriteLine("I chose scissors!");
break;
default:
WriteLine("Your game is out of whack!");
break;
}
The branching logic to determine the winner uses ‘or’ and ‘and’ logical operators to keep the code concise and understandable. Depending on the values of playerChoice & computerChoice, the Win(), Lost(), or Tie() methods are invoked.
// TODO: Determine results using if-else statements
if (playerChoice == "rock" && computerChoice == "scissors" ||
playerChoice == "paper" && computerChoice == "rock" ||
playerChoice == "scissors" && computerChoice == "paper")
{
Win();
}
else if (playerChoice == "rock" && computerChoice == "paper" ||
playerChoice == "paper" && computerChoice == "scissors" ||
playerChoice == "scissors" && computerChoice == "rock")
{
Lose();
}
else if (playerChoice == "rock" && computerChoice == "rock" ||
playerChoice == "paper" && computerChoice == "paper" ||
playerChoice == "scissors" && computerChoice == "scissors")
{
Tie();
}
Win() method will increase the total score of the player by 1 using Increment Operators.
public void Win()
{
// Increases the score of the player and tells them they won
Score++;
WriteLine("You win!");
ShowScore();
}
The Lose() method will not increase or decrease the score, but it will output a lose message to the player.
public void Lose()
{
// Tells player they've lost
WriteLine("You lose.");
ShowScore();
}
The Tie() method, like the Lose() method will not effect the score, but it will tell the player they’ve tied with the computer.
public void Tie()
{
// Tells player they tied with computer
WriteLine("You tie...");
ShowScore();
}
After every round, we’d like to know if the player will continue playing. The AnotherRound() method will request an yes/no input to the question “Would you like to play again?”. If yes, play another round, if no, stop the game.
To validate the user’s input, create an else condition that restarts the method.
public void AnotherRound()
{
// Asks the player if they want to play again
WriteLine("Would you like to play again? (yes/no)");
string playAgain = ReadLine().Trim().ToLower();
if (playAgain == "yes")
{
PlayRound();
}
else if (playAgain == "no")
{
Stop();
}
else { AnotherRound(); }
}
The Stop() method triggers the outro of the RPS game. We’ll force shutdown the command prompt by using Enviorment.Exit(). Environment.Exit() will terminate the process and return an exit code to the operating system. Figure out why 0 is the parameter in the documentation here.
public void Stop()
{
// Shows there player's total score and a goodbye message
WriteLine("Thanks for playing!");
WriteLine($"Your final score was {Score}!");
WriteLine("Press any key to exit...");
ReadKey();
Environment.Exit(0);
}
Figure out why Enviorment.Exit() contains parameter 0 in documentation here.
The ShowScore() method displays the current score to the user when invoked. To make the score stand out between the text in the command terminal, the color of the text has been changed.
public void ShowScore()
{
// Shows the player their current score
ConsoleColor prevColor = ForegroundColor;
ForegroundColor = ConsoleColor.DarkYellow;
WriteLine($"Your Score is {Score}.");
ForegroundColor = prevColor;
}
We don’t want the new foreground color to bleed into the next lines of code, so the prevColor variable saves the original foreground color. Then, after the score has been shown to the user, the foreground color is set equal to the original color, reverting the changes we made.
Conclusion
Congratulations on completing your Rock, Paper, Scissors game!
In this lesson you learned branching logic, random generated values, and how to follow a prompt to create a program. We used conditionals to compare the player’s choice and the computer’s choice of either rock, paper, or scissors. The computer’s choice was randomly generated, converted into a string and compared with the user’s inputted choice. Based on the both of their choice’s we were able to determine if the player had won, lost, or tied.
You’re on the fast track to becoming a software developer. There is programming logic tied throughout the RPS game and I challenge you to recreate your own RPS game. That will prove the knowledge taught here has solidified within you. Thank you so much for learning here on LearningDot.NET, if you wish to learn more about .NET, check out some more posts! Happy Programming!
P.S. The Github source code contains the big hands that display rock, paper, and scissors in ASCII Text Art and the foreground color logic. Click here to see it!