C# Loop back to a previous part of code - c#

//Gender Creation:
while (correct == 0)
{
do
{
Console.Clear();
Console.WriteLine("Please choose a gender from the options below: ");
Console.WriteLine("Male|Female|Random");
Console.Write("Input: ");
Gender = Console.ReadLine().ToUpper();
if (Gender == "MALE")
{
Console.WriteLine("Is this the gender you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
Input = Console.ReadLine().ToUpper();
if (Input == "YES")
{
correct = 1;
}
else if (Input == "NO")
{
correct = 0;
}
}
else if (Gender == "FEMALE")
{
Console.WriteLine("Is this the gender you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
Input = Console.ReadLine().ToUpper();
if (Input == "YES")
{
correct = 1;
}
else if (Input == "NO")
{
correct = 0;
}
}
else if (Gender == "RANDOM")
{
correct = 2;
}
else
{
Console.WriteLine("ERROR, Please try again.");
Gender = Console.ReadLine().ToUpper();
}
} while (correct == 0);
//Random Gender Creation:
if (correct == 2)
{
do
{
if (randgender == 1)
{
Console.WriteLine("The gender: MALE was randomly chosen");
Console.WriteLine("Is this the gender you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
Input = Console.ReadLine().ToUpper();
if (Input == "YES")
{
correct = 1;
Gender = "MALE";
}
else if (Input == "NO")
{
correct = 2;
}
}
else if (randgender == 2)
{
Console.WriteLine("The gender: FEMALE was randomly chosen");
Console.WriteLine("Is this the race you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
Input = Console.ReadLine().ToUpper();
if (Input == "YES")
{
correct = 1;
Gender = "FEMALE";
}
else if (Input == "NO")
{
correct = 2;
}
}
} while (correct == 2);
correct = 0;
}
break;
}
When correct = 2 then the gender is being randomly generated, if the user inputs no when being asked if they are happy with the gender the code will just loop the random gender generator over and over constantly saying that the random gender is the same every time as the random number is never changing however when correct = 0 the code will just proceed when no is inputted and when the gender is printed it is just printed as RANDOM as that is the option the user initially chose.
How can I make it go back to the first do while loop to ask the user what gender they want their character to be?

As theMayer suggested, you'll need to break down your app into smaller pieces. There are also a few concepts that you may need to tackle before you can write C#, as such.
This example might help you get a little further along, as it illustrates several ways of achieving better control flow:
static void Main(string[] args)
{
Console.Clear();
var choosenGender = "";
var wasChoiceConfirmed = false;
while (wasChoiceConfirmed == false)
{
choosenGender = PromptForGender();
switch (choosenGender)
{
case "RANDOM":
var randomGender = GenerateRandomGender();
wasChoiceConfirmed = PromptForGenderConfirmation(randomGender, true);
break;
case "MALE":
case "FEMALE":
wasChoiceConfirmed = PromptForGenderConfirmation(choosenGender);
break;
default:
Console.WriteLine("Error, please try again. \n");
break;
}
}
}
static string PromptForGender()
{
Console.Write(
"\nPlease choose a gender from the options below: \n" +
"Male|Female|Random \n" +
"Input:");
return Console.ReadLine().Trim().ToUpper();
}
static bool PromptForGenderConfirmation(string gender, bool wasRandom = false)
{
var randomVerbiage = wasRandom ? "randomly " : "";
Console.Write(
$"\nThe gender: {gender} was {randomVerbiage}chosen \n" +
"Is this the gender you wish your character to be? Enter Yes/No: \n" +
"Input: ");
var confirmed = Console.ReadLine().Trim().ToUpper();
return confirmed == "YES";
}
static string GenerateRandomGender()
{
var randomNumber = new Random();
return randomNumber.Next(0, 1) == 0 ? "FEMALE" : "MALE";
}

I refactored your code so it helps me understand it better. This gives you the result you want and you don't need all those nested loops.
public class Program
{
public static void AskFirstQuestion()
{
Console.Clear();
Console.WriteLine("Please choose a gender from the options below: ");
Console.WriteLine("Male|Female|Random");
Console.Write("Input: ");
var gender = Console.ReadLine()?.ToUpper();
if (gender == "MALE" || gender == "FEMALE")
{
HandleGenderSelection(gender);
}
else if (gender == "RANDOM")
{
HandleRandom();
}
}
private static void HandleRandom()
{
var randomGender = GenerateRandomGender();
Console.WriteLine($"The gender: {randomGender} was randomly chosen");
Console.WriteLine("Is this the race you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
var input = Console.ReadLine()?.ToUpper();
switch (input)
{
case "YES":
Console.WriteLine("OK");
break;
case "NO":
AskFirstQuestion();
break;
}
}
private static string GenerateRandomGender()
{
//Have you logic to randomly create gender
return "MALE";
}
private static void HandleGenderSelection(string gender)
{
Console.WriteLine("Is this the gender you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
var input = Console.ReadLine()?.ToUpper();
if (input == "YES")
{
Console.WriteLine("OK!");
}
else if (input == "NO")
{
AskFirstQuestion();
}
}
static void Main(string[] args)
{
AskFirstQuestion();
}
}

Related

c# do while loop exit even when the return is false

I have this C# program that, and this loop doesn't want to exit, it just becomes a blank row until the user answers yes? Not sure why or how this is happening.
https://dotnetfiddle.net/A6vJtd
using System;
namespace Assignment2
{
class FunFeatures
{
private string name = "";
private string email = "";
static void Main(string[] args)
{
Console.Title = "Strings, selection and interation in C#";
FunFeatures funObj = new FunFeatures();
funObj.Start();
ContinueToNextPart(); //call the method below
}
private static void ContinueToNextPart()
{
Console.WriteLine("\nPress enter to continue to the next part");
Console.ReadLine();
Console.Clear();
}
public void Start()
{
Introduce();
bool done = false;
do
{
//Call method to read a number 1 to 7 and display
//name of the day (1 = Monday, 7 = Sunday with a comment
PredictTheDay();
//Calculate the length of a given text
CalculateStrengthLength();
//Run again or exit
done = RunAgain();
} while (!done);
Console.WriteLine("Welcome back, " + name);
}
public void CalculateStrengthLength()
{
Console.WriteLine("\nLength of text: Write a text with a number of characters and press Enter");
Console.WriteLine("It will then calculate the number of chars included in the text");
Console.WriteLine("Give me a text of any length, or press Enter to exit!");
string str = Console.ReadLine();
int strLength = str.Length;
Console.WriteLine("\n"+ str.ToUpper());
Console.WriteLine("Number of chars = " + strLength);
}
private void Introduce()
{
Console.WriteLine("\nLet me know about yourself!");
ReadName();
Console.Write("Give me your email please: ");
email = Console.ReadLine();
Console.WriteLine("\nHere is your full name and your email.");
//split first name and last name
var names = name.Split(" ");
string fName = names[0];
string lName = names[1];
Console.WriteLine(lName + ", " + fName + " " + email);
}
public void PredictTheDay()
{
Console.WriteLine(); // blank row
Console.WriteLine("\nI am a fortune teller.");
Console.Write("Select a number between 1 and 7: ");
string str = Console.ReadLine();
int day = int.Parse(str);
switch (day)
{
case 1:
// Monday
Console.WriteLine("Monday: Keep calm my friend! You can fall apart!");
break;
case 2:
//Tuesday
Console.WriteLine("Tuesday and Wednesday break your heart!");
break;
case 3:
//Wednesday
Console.WriteLine("Tuesday and Wednesday break your heart!");
break;
case 4:
//Thursday
Console.WriteLine("Thursday, OMG, still one day to Friday!");
break;
case 5:
//Friday
Console.WriteLine("It's Friday! You are in love!");
break;
case 6:
//Saturday
Console.WriteLine("Saturday, do nothing and do plenty of it!");
break;
case 7:
//Sunday
Console.WriteLine("And Sunday always comes too soon!");
break;
default: // if user gives a number out of range
Console.WriteLine("Not in a good mode? This is not a valid date!");
break;
}
}
public void ReadName()
{
Console.WriteLine("Your first name please: ");
string firstname = Console.ReadLine();
Console.Write("Your last name please: ");
string lastname = Console.ReadLine().ToUpper();
name = firstname + " " + lastname;
Console.WriteLine("Nice to meet you " + firstname + "!");
}
//Ask user to whether to continue,
//return true if the user answers Y, y or any word beginning
//with these, or N, n or any word beginning with these.
//Otherwise, return false.
private bool RunAgain()
{
bool done = false; //true = y, false = n
Console.WriteLine(); //blankline
Console.Write("Run again? (y/n) ");
do
{
string str = Console.ReadLine();
//change str to uppercase letters to make comparison
//easier
str = str.ToUpper();
if (str[0] == 'Y') //str[0]is the first letter in the string
{
// continue wit
done = true;
}
else if (str[0] == 'N')
{
// do not continue with calculation
done = false;
}
} while (!done); //if (!done) is same as: if (done == false)
return done;
}
}
}
You need to distinguish 2 different things here:
The user wants to continue (which you have)
The user made valid input (which you don't have)
You are trying to achieve everything with a single boolean, which will not work.
There are several possibilities to make this work. At your level of understanding, I'd say let's introduce a second boolean:
private bool RunAgain()
{
Console.WriteLine();
Console.Write("Run again? (y/n) ");
bool done = false; //true = y, false = n
bool validinput = false; // no input is invalid input
do
{
string str = Console.ReadLine();
str = str.ToUpper();
if (str[0] == 'Y')
{
done = true;
validinput = true;
}
else if (str[0] == 'N')
{
done = false;
validinput = true;
}
} while (!validinput);
return done;
}
Note that you have inverse logic here: the method is called RunAgain(), and the variable name is called done, where my understanding of done is that I don't want to continue.
Let's fix that and make shorter code like
private bool RunAgain()
{
Console.WriteLine();
Console.Write("Run again? (y/n) ");
while(true) // yes, it's endless ...
{
string str = Console.ReadLine();
str = str.ToUpper();
if (str[0] == 'Y')
{
return // ... except if you jump out
false; // False = not run again
}
else if (str[0] == 'N')
{
return // ... except if you jump out
true; // True = run again
}
}
}
This loop here:
do
{
string str = Console.ReadLine();
//change str to uppercase letters to make comparison
//easier
str = str.ToUpper();
if (str[0] == 'Y') //str[0]is the first letter in the string
{
// continue wit
done = true;
}
else if (str[0] == 'N')
{
// do not continue with calculation
done = false;
}
} while (!done); //if (!done) is same as: if (done == false)
doesn't have a leaving mechanism when you input no. You are checking if they entered yes or no and if they entered no you are just looping over and over again, since while(!false) means while(true) which means once they enter no you are commanding to loop again. You can do something like:
do
{
string str = Console.ReadLine();
//change str to uppercase letters to make comparison
//easier
str = str.ToUpper();
if (str[0] == 'Y') //str[0]is the first letter in the string
{
// continue wit
done = true;
}
else if (str[0] == 'N')
{
// do not continue with calculation
done = false;
break;
}
} while (!done); //if (!done) is same as: if (done == false)
return done;
This part is also wrong
do
{
//Call method to read a number 1 to 7 and display
//name of the day (1 = Monday, 7 = Sunday with a comment
PredictTheDay();
//Calculate the length of a given text
CalculateStrengthLength();
//Run again or exit
done = RunAgain();
} while (!done);
You are receiving a false from RunAgain() when the user answers no which means you should stop the loop but since you again have while(!done) you are resolving !false to true. It should be
do
{
//Call method to read a number 1 to 7 and display
//name of the day (1 = Monday, 7 = Sunday with a comment
PredictTheDay();
//Calculate the length of a given text
CalculateStrengthLength();
//Run again or exit
done = RunAgain();
} while (done);

Adding switch case

I want to add switch case to not allow the user to write string when entering temperature or when there is nothing to delete it says "there is nothing to delete, go back to menu".
List<string> Temp = new List<string>();
while (true)
{
string val;
Console.WriteLine("[L] ägg till temp-mätning: ");
Console.WriteLine("[S] kriv ut alla temperaturer och medeltemperatur");
Console.WriteLine("[T] ag bort temp-mätning");
Console.WriteLine("[A] vsluta");
Console.Write("Selection: ");
val = Console.ReadLine();
if (val == "l" || val == "L")
{
Console.WriteLine("add temperature : ");
Temp.Add(Console.ReadLine());
Console.Clear();
}
else if(val == "s" || val == "S")
{
int index = 1;
Console.Clear();
Console.WriteLine($"Your temperatures are: ");
Temp.ForEach(x => Console.WriteLine($"{index++} - {x}"));
}
else if (val == "t" || val == "T")
{
Console.Write($"Which temp do you want to delete [index from 1 to {Temp.Count}]: ");
int deleteIndex = int.Parse(Console.ReadLine()) - 1;
Temp.RemoveAt(deleteIndex);
}
else
{
Console.WriteLine("incorrect input: ");
Console.Clear();
break;
}
To control use input you can extract methods, e.g.
private static int ReadInteger(string title) {
while (true) {
if (!string.IsNullOrWhiteSpace(title))
Console.WriteLine(title);
if (int.TryParse(Console.ReadLine(), out int result))
return result;
Console.WriteLine("Incorrect syntax, please, try again.");
}
}
then you can put
val = Console
.ReadLine()
.Trim() // Let's be nice and tolerate leading / trailing spaces, e.g. " L "
.ToUpper();
val = val.Substring(0, Math.Max(1, val.Length));
switch (val) {
case "L":
// We read valid integer, turn it to string and out to Temp
Temp.Add(ReadInteger("add temperature : ").ToString());
Console.Clear();
break;
case "T":
int deleteIndex = ReadInteger(
"$"Which temp do you want to delete [index from 1 to {Temp.Count}]: ");
if (deleteIndex >= 0 && deleteIndex < Temp.Count)
Temp.RemoveAt(deleteIndex);
else
Console.WriteLine("Index out of range");
break;
...
}
Please check C# reference websites or books before asking questions.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/
Here is the code you wanted, hope this helps you:
List<string> Temp = new List<string>();
while (true)
{
menu:
string val = string.Empty;
Console.WriteLine("[L] ägg till temp-mätning: ");
Console.WriteLine("[S] kriv ut alla temperaturer och medeltemperatur");
Console.WriteLine("[T] ag bort temp-mätning");
Console.WriteLine("[A] vsluta");
Console.Write("Selection: ");
val = Console.ReadLine();
switch (val.ToLower())
{
case "l":
addTemperature:
Console.WriteLine("add temperature : ");
string temperatureInput = Console.ReadLine();
int temperatureToAddToList;
try
{
temperatureToAddToList = Convert.ToInt32(temperatureInput); //This line trys to convert string variables to integer variables. If string variable includes any character, it will throw an exception.
}
catch (Exception error) //If an exception was thrown, this code block gets activated, which will give out the message you asked for.
{
Console.Clear();
Console.WriteLine("Please enter a number instead of a string!");
goto addTemperature;
}
Temp.Add(temperatureInput.Trim());
Console.Clear();
break;
case "s":
int index = 1;
Console.Clear();
Console.WriteLine($"Your temperatures are: ");
Temp.ForEach(x => Console.WriteLine($"{index++} - {x}"));
break;
case "t":
if (Temp.Count == 0)
{
Console.Clear();
Console.WriteLine("There is nothing to delete, go back to menu.");
goto menu;
}
else
{
Console.Write($"Which temp do you want to delete [index from 1 to {Temp.Count}]: ");
int deleteIndex = int.Parse(Console.ReadLine()) - 1;
Temp.RemoveAt(deleteIndex);
break;
}
default:
Console.WriteLine("incorrect input: ");
Console.Clear();
break;
}
I have revised and updated my code example to better solve your problem.

Decline a string in a string variable

I need to decline the ability to write strings in my console application, at the moment, when text is entered instead of numbers, the console crashes.
I have something along the lines of this right now
class Program
{
static void Main(string[] args)
{
string[] names = new string[2];
string age;
bool agetest = false;
Console.WriteLine("Hello, I am the NameBot2000, What is your first name?");
names[0] = Console.ReadLine();
Console.WriteLine("Well done. What is your surname?");
names[1] = Console.ReadLine();
Console.WriteLine("What year were you born in?");
age = Console.ReadLine();
int.Parse(age);
if (Enumerable.Range(0,2015).Contains(age));
int year = 0;
string wow = "";
if (Enumerable.Range(0,31).Contains(year))
wow = "young";
else if (Enumerable.Range(31,51).Contains(year))
wow = "old";
else if (Enumerable.Range(51,500).Contains(year))
wow = "ancient";
Console.WriteLine("Well done. You said your name was {0} {1}, and you are {2} years old!", names[0], names[1], year);
Console.WriteLine("You are so {0}!", wow);
Console.ReadLine();
}
}
I have tried to incorporate a boolean but I am unsure how to compare the variable to check which format it is in.
Thanks heaps in advance!
Instead of Parse, use TryParse.
int age = 0;
if (Int32.TryParse(Console.Readline, out age)
// Correct format.
else
// error!
What TryParse() will do, is take the user input, Try to Parse it to an int, and if successful, will output an int (and a bool = true), otherwise it will output a bool = false.
use a try catch
string age = console.readline();
bool validage = false;
While(!validage)
{
try
{
int myage = int.parse(age);
validage = true;
}
catch
{
console.write("Please Enter an Integer value for age:");
age = console.readline();
}
}
You can check ConsoleKeyInfo to make sure user can only enter digits for age.
Console.WriteLine("Enter Age : ");
ConsoleKeyInfo key;
string ageStr = "";
do
{
key = Console.ReadKey(true);
if (key.Key != ConsoleKey.Backspace && key.Key != ConsoleKey.Enter)
{
if (char.IsNumber(key.KeyChar))//Check if it is a number
{
ageStr += key.KeyChar;
Console.Write(key.KeyChar);
}
}
else
{
if (key.Key == ConsoleKey.Backspace && ageStr.Length > 0)
{
ageStr = ageStr.Substring(0, (ageStr.Length - 1));
Console.Write("\b \b");
}
}
}
while (key.Key != ConsoleKey.Enter);
Console.WriteLine("Age is {0}", ageStr);

Rock Paper Scissors c# debut how to show winrate?

I recently started making a RPS game console app it worked and I decided to give myself more of a challenge and decided it will be cool if it had a win rate for both computer and player and for some reason it's not showing the win rates on the left side
EDIT: So I got it to show left but the percents remain at 0 any idea how to fix this?
abstract class Participant
{
public int wins;
int _winRate;
public int winRate
{
get
{
return _winRate;
}
set
{
if (value < 0 || value > 100)
{
throw new Exception("value cannot be less than 0 or greater than 100");
}
_winRate = value;
}
}
public abstract string Choice();
public abstract void PrintWinRate();
}
class Computer : Participant
{
string[] Rock_Paper_Scissor = {"rock","paper","scissor"};
Random rand = new Random();
public override string Choice()
{
string element = Rock_Paper_Scissor[rand.Next(3)];
return element;
}
public override void PrintWinRate()
{
winRate = (wins / Game_Logic.gamesPlayed) * 100;
string _winRate = "computer win rate: "+winRate.ToString()+"%".PadRight(10);
Console.WriteLine(_winRate);
}
}
class Player : Participant
{
public override string Choice()
{
string playerChoice = Console.ReadLine().Trim();
return playerChoice;
}
public override void PrintWinRate()
{
winRate = (wins / Game_Logic.gamesPlayed) * 100;
string _winRate = "player win rate: " + winRate.ToString()+"%".PadRight(10);
Console.WriteLine(_winRate);
}
}
class Game_Logic
{
public static int gamesPlayed;
static void Main()
{
Console.BackgroundColor = ConsoleColor.Red;
Console.ForegroundColor = ConsoleColor.Black;
Computer comp = new Computer();
Player player = new Player();
string computerChoice;
string playerChoice;
ConsoleKeyInfo input;
bool playAgain;
int computerWins = comp.wins;
int playerWins = player.wins;
do
{
Console.Clear();
computerChoice = comp.Choice();
playerChoice = player.Choice();
Console.Clear();
while (playerChoice == computerChoice)
{
computerChoice = comp.Choice();
}
Console.WriteLine("Player: "+ playerChoice);
Console.WriteLine("\n"+"Computer: " + computerChoice);
if (playerChoice == "rock" && computerChoice == "scissor" || playerChoice == "paper" && computerChoice == "rock")
{
playerWins++;
Console.WriteLine("\n" + "You won!");
}
else if (playerChoice == "scissor" && computerChoice == "rock" || playerChoice == "rock" && computerChoice == "paper")
{
computerWins++;
Console.WriteLine("\n" + "Computer won!");
}
else if (playerChoice == "scissor" && computerChoice == "paper")
{
playerWins++;
Console.WriteLine("\n" + "You won!");
}
else if (playerChoice == "paper" && computerChoice == "scissor")
{
computerWins++;
Console.WriteLine("\n" + "Computer won!");
}
else
{
Console.WriteLine("\n" + "invalid value");
}
Game_Logic.gamesPlayed++;
Console.WriteLine("\n"+"Play again? <y/n>");
Console.WriteLine("\n");
comp.PrintWinRate();
player.PrintWinRate();
input = Console.ReadKey(true);
playAgain = input.KeyChar == 'y';
} while (playAgain);
}
}
First things first, I think there is a problem with the increment logic, not being able to increment the actual values of participant object. playerWins and computerWins are local variables of your main, and considered as new variable, not just as reference of your participant objects. Change the following lines:
playerWins++ to player.wins++ //Change the actual values of participant
computerWins++ to comp.wins++
Next, when you say left? What format specifically would you want? For now try the following lines:
string _winRate = string.Format("player win rate: {0}%", winRate);
Your game is displaying the scores but instantly clears the screen or exits.
Placing the 'PrintWinRate' calls before 'Console.ReadKey' should give you the desired behaviour!
Like this:
Console.WriteLine("\n" + "Play again? <y/n>");
Console.WriteLine("\n");
comp.PrintWinRate();
player.PrintWinRate();
input = Console.ReadKey(true);
Edit: There also seems to be a bug in the calculation for winRate.
You might want to change your value type for 'wins' from 'int' to 'float' so that it can store the fractional part of the calculation. As it is, when you expect a player to have 50% winRate it will show 0. This is because 'int' data types can not hold fractional values and will cut that part off, leaving the whole number - in this case 0.
This code should be closer to what you want:
winRate = (int)((wins / Game_Logic.gamesPlayed) * 100);
Remember to change 'wins' in your base class 'Participant' to be a float!

get user confirmation inside a loop

After searching for a Solution with a do-while Loop, I'm now stuck and this point, and just cant figure out what I am doing wrong.
static void StartUp()
{
bool confirmChoice = false;
Console.WriteLine("Hey, Enter your Character Name!");
string name = Console.ReadLine();
do
{
Console.WriteLine("Is " + name + " correct? (y) or would you like to change it (n)?");
string input = Console.ReadLine();
if (input == "n")
{
Console.WriteLine("Allright, enter your new Name then!");
name = Console.ReadLine();
break;
}
else
{
confirmChoice = true;
}
}while(confirmChoice);
}
Your code is almost right - all you need to do is inverting the condition of your do/while loop to while (!confirmChoice)
However, you could do better than that: make a forever loop, and use break to exit it:
while (true) {
Console.WriteLine("Please, Enter your Character Name!");
string name = Console.ReadLine();
Console.WriteLine("Is " + name + " correct? (y) or would you like to change it (n)?");
string input = Console.ReadLine();
if (input == "y") {
break;
}
}
This is a common solution for situations when the decision to exit is made in the middle of the loop body.
you should change the termination condition for your loop
it should be while(!confirmChoice);
and you should change the break; line to continue;
Your Condition is wrong it should be while(confirmChoice==false) and don't use break;
static void StartUp()
{
bool confirmChoice = false;
Console.WriteLine("Hey, Enter your Character Name!");
string name = Console.ReadLine();
do
{
Console.WriteLine("Is " + name + " correct? (y) or would you like to change it (n)?");
string input = Console.ReadLine();
if (input == "n")
{
Console.WriteLine("Allright, enter your new Name then!");
name = Console.ReadLine();
}
else
{
confirmChoice = true;
}
}while(confirmChoice==false);
}

Categories