What is wrong with my while statement? Else statement won't write - c#

Everything runs correctly except the else statement. It gets skipped over once the numbers are equal to each other. It doesn't say "You got it" at the end.
//declare variables
int number = 4;
int guessCount = 0;
int guess;
//get first number
Console.WriteLine("Guess a number between 1 and 10:");
guess = Convert.ToInt32(Console.ReadLine());
guessCount = guessCount + 1; //increment counter
while (guess != number) //keep repeating until number is chosen
{
guessCount = guessCount + 1; //increment counter
if (guess < number) //if statement if guess is less than number
{
Console.WriteLine("Your guess is too low.");
}
else if (guess > number) //if statement if guess is more than number
{
Console.WriteLine("Your guess is too high.");
}
else //
{
Console.WriteLine("You got it!!");
}
//end of while to ask for a new guess
Console.WriteLine("Guess again: ");
guess = Convert.ToInt32(Console.ReadLine());
}
//display output
Console.WriteLine("You figured it out in " + guessCount + " guesses.");
Console.ReadLine(); //keep window open

Your while expression states: guess != number which is true as long as the user does not type in 4 (your hardcoded value). You are setting guess right before the while expression gets checked, so if the user types in the right number, the while expression will be false and it will be jumped over. I commented your code at the problems' locations.
//declare variables
int number = 4;
int guessCount = 0;
int guess;
//get first number
Console.WriteLine("Guess a number between 1 and 10:");
// Problem A: user types in 4 -> guess becomes equal to number -> while expression gets false -> while body will not be executed
guess = Convert.ToInt32(Console.ReadLine());
while (guess != number) //keep repeating until number is chosen
{
guessCount = guessCount + 1; //increment counter
if (guess < number) //if statement if guess is less than number
{
Console.WriteLine("Your guess is too low.");
}
else if (guess > number) //if statement if guess is more than number
{
Console.WriteLine("Your guess is too high.");
}
else //
{
Console.WriteLine("You got it!!");
}
//end of while to ask for a new guess
Console.WriteLine("Guess again: ");
// Problem B: user types in 4 -> guess becomes equal to number -> while expression gets false -> loop ends
guess = Convert.ToInt32(Console.ReadLine());
}

When it is coming into the while loop, it means that guess is != number and the only state that is possible here is guess < number and guess > number that you have already checked for, and guess = number is meaningless because if the guess is equal to number it doesn't even comes into the while loop. This is why your else statement never executes because the only state that your else statement is checking for is guess == number.

Related

How to ignore a line/block of code if the condition is met?

Is there a way to ignore a line/block of code if the condition is met?
I'm doing a C# .NET tutorial, and the application is a number guessing game.
I added a hint option if the user enters a wrong number (else if part):
// While guess is not correct
while (guess != correctNumber)
{
//Get users input
string input = Console.ReadLine();
// Make sure it's a number
if (!int.TryParse(input, out guess))
{
// Print error message
PrintColorMessage(ConsoleColor.Red, "Please use an actual number");
// Keep going
continue;
}
// Cast to int and put in guess
guess = Int32.Parse(input);
// Check if guess is close to correct number
if(guess == correctNumber + 2 || guess == correctNumber - 2)
{
// Tell the user that he is close
PrintColorMessage(ConsoleColor.DarkCyan, "You are close!!");
}
// Match guess to correct number
else if (guess != correctNumber)
{
// Print error message
PrintColorMessage(ConsoleColor.Red, "Wrong number, please try again");
AskForAHint(correctNumber);
}
}
// Print success message
PrintColorMessage(ConsoleColor.Yellow, "You are CORRECT!");
Basically I am asking a user if he wants a hint, and if he writes Y, the hint will be displayed. However, is there an option to display this question only once since this if statement is included in a while loop?
It would be annoying if "Do you want a hint?" question keeps displaying even if the user says Y.
My AskForAHint function:
static void AskForAHint(int num)
{
// Ask user if he wants a hint
Console.WriteLine("Do you want a hint? [Y/N]");
// Take his answer
string ans = Console.ReadLine().ToUpper();
// If the user wants a hint
if (ans == "Y")
{
// First hint number
int beginning = (num - num % 10);
// Second hint number
int finish = beginning + 10;
// Give user a hint
Console.WriteLine("The correct number is somewhere betweer {0} and {1}", beginning, finish);
}
else if (ans == "N")
{
return;
}
}
Thanks
Another way to do it would be to make the number of hints configurable (allowing the caller to specify how many hints they want to let the user ask for), and then keep track of the number of hints given in the method itself.
This would require a slight change to the AskForAHint method, however, since we don't know if the user answered "Y" or "N" to the hint question. Since AskForHint has no return value, we could have it return a bool that indicates how the user responded to the question:
static bool AskForAHint(int num)
{
var answer = GetUserInput("Do you want a hint? [Y/N]: ", ConsoleColor.Yellow);
if (!answer.StartsWith("Y", StringComparison.OrdinalIgnoreCase))
{
return false;
}
var beginning = num - num % 10;
var finish = beginning + 10;
Console.WriteLine($"The correct number is somewhere between {beginning} and {finish}");
return true;
}
Now we can keep track of how many hints the user has received by incrementing a counter in our "Game" method:
// Only ask for a hint if they have any hints (and guesses) remaining
if (hintCount < maxHints && guessCount < maxGuesses)
{
// If they asked for a hint, increase the hint count
if (AskForAHint(correctNumber)) hintCount++;
// If they didn't want a hint, max out hint count so we don't ask again
else hintCount = maxHints;
}
To test out the sample code above, I used this method below, which also allows us to configure how many total guesses the user has, what the min and max values of the range should be, and if they should be given a "directional hint", like "too high!" or "too low!":
private static readonly Random Random = new Random();
private static void PlayGuessingGame(int maxHints = 1, int maxGuesses = 10,
int rangeMin = 1, int rangeMax = 100, bool giveDirectionalHint = true)
{
if (rangeMax < rangeMin) rangeMax = rangeMin;
var correctNumber = Random.Next(rangeMin, rangeMax + 1);
var guessCount = 0;
var hintCount = 0;
WriteMessage("Welcome to the guessing game!", ConsoleColor.White);
WriteMessage("-----------------------------\n", ConsoleColor.White);
WriteMessage($"I'm thinking of a number from {rangeMin} to {rangeMax}. ", ConsoleColor.Green);
WriteMessage("Let's see how many guesses it takes you to guess it!\n", ConsoleColor.Green);
do
{
WriteMessage($"(You have {maxGuesses - guessCount} guesses left)");
var input = GetUserInput("Enter the number I'm thinking of: ", ConsoleColor.White);
int guess;
if (!int.TryParse(input, out guess))
{
WriteMessage("Please enter a whole number", ConsoleColor.Red);
continue;
}
// Only increment guesses if they entered an actual number
guessCount++;
if (guess == correctNumber) break;
if (Math.Abs(guess - correctNumber) == 2)
{
WriteMessage("You are close!!", ConsoleColor.DarkCyan);
}
if (giveDirectionalHint)
{
WriteMessage("Wrong number - too " + (guess < correctNumber ? "low!" : "high!"),
ConsoleColor.Red);
}
else
{
WriteMessage("Wrong number, please try again", ConsoleColor.Red);
}
// Only ask for a hint if they have any hints (and guesses) remaining
if (hintCount < maxHints && guessCount < maxGuesses)
{
// If they asked for a hint, increase the hint count
if (AskForAHint(correctNumber)) hintCount++;
// If they didn't want a hint, max out hint count so we don't ask again
else hintCount = maxHints;
}
} while (guessCount < maxGuesses);
WriteMessage("You are CORRECT!", ConsoleColor.Yellow);
GetKeyFromUser("\nDone! Press any key to exit...");
}
This uses the helper functions:
public static void WriteMessage(string message, ConsoleColor color = ConsoleColor.Gray)
{
Console.ForegroundColor = color;
Console.WriteLine(message);
Console.ResetColor();
}
private static string GetUserInput(string prompt, ConsoleColor color = ConsoleColor.Gray)
{
Console.ForegroundColor = color;
Console.Write(prompt);
Console.ResetColor();
return Console.ReadLine();
}
Output
You can see in the output below, I was only given a single hint. However that, combined with the directional hints, made the game easy to win:
I think you can do an "if" with a counter.
Try It
Int cont = 0; //global
// While guess is not correct
while (guess != correctNumber)
{
//Get users input
string input = Console.ReadLine();
// Make sure it's a number
if (!int.TryParse(input, out guess))
{
// Print error message
PrintColorMessage(ConsoleColor.Red, "Please use an actual number");
// Keep going
continue;
}
// Cast to int and put in guess
guess = Int32.Parse(input);
// Check if guess is close to correct number
if(guess == correctNumber + 2 || guess == correctNumber - 2)
{
// Tell the user that he is close
PrintColorMessage(ConsoleColor.DarkCyan, "You are close!!");
}
// Match guess to correct number
else if (guess != correctNumber)
{
// Print error message
PrintColorMessage(ConsoleColor.Red, "Wrong number, please try again");
if(cont == 0){
AskForAHint(correctNumber);
}
}
}
// Print success message
PrintColorMessage(ConsoleColor.Yellow, "You are CORRECT!");
And in the function add
static void AskForAHint(int num)
{
// Ask user if he wants a hint
Console.WriteLine("Do you want a hint? [Y/N]");
// Take his answer
string ans = Console.ReadLine().ToUpper();
// If the user wants a hint
if (ans == "Y")
{
cont = 1;
// First hint number
int beginning = (num - num % 10);
// Second hint number
int finish = beginning + 10;
// Give user a hint
Console.WriteLine("The correct number is somewhere betweer {0} and {1}", beginning, finish);
}
else if (ans == "N")
{
return;
}
}
Use a Member Variable Boolean, its similar to how you can avoid recursive calls.
private bool alreadyHinted = false;
static void AskForAHint(int num)
{
if (alreadyHinted) return;
alreadyHinted = true;
At some point you will need to set alreadyHinted back to false;

How can I get a message to appear only once if a random number doesn't equal one in a vector?

I am making a small lottery game. Everything works fine but I can't get the message I want to be displayed if the user doesn't guess the correct number to only appear once. I don't know how to get it to appear only once and I know why it appears multiple times.
static void Main(string[] args)
{
int[] userGuessNums = new int[10];
Console.WriteLine("Input 10 numbers between 1-50.");
for (int i = 0; i < userGuessNums.Length; i++)
{
try
{
Console.Write("Number " + (i + 1) + ": ");
string numbers = Console.ReadLine();
int userNumbers = Convert.ToInt32(numbers);
userGuessNums[i] = userNumbers;
}
catch
{
Console.WriteLine("Invalid input");
}
}
Console.Clear();
Random randomer = new Random();
int randomNumber = randomer.Next(1, 51);
Console.WriteLine("The numbers you have chosen:");
foreach (int element in userGuessNums)
{
Console.Write(element + " ");
}
Console.WriteLine();
Console.WriteLine("Press 'Enter' to see if you have won.");
Console.ReadLine();
Console.WriteLine("The winning number is: " + randomNumber);
for (int i = 0; i < userGuessNums.Length; i++)
{
if (userGuessNums[i] == randomNumber)
Console.WriteLine("Congratulations! You won!");
else if (userGuessNums[i] != randomNumber)
{
Console.WriteLine("Sorry, you lose.");
}
}
}
You can check to see if the random number is in the array input by the user.
Import Linq at the top of your code
using System.Linq;
And after Console.WriteLine("The winning number is: " + randomNumber); replace the for-loop with
if (userGuessNums.Contains(randomNumber))
{
Console.WriteLine("Congratulations! You won!");
}
else
{
Console.WriteLine("Sorry, you lose.");
}
Modify your last for loop like so. Loop through your array and find a winning number then set your win prompt outside the loop.
Why does this work? Let's break it down. Mainly I'm separating the prompt for the win from the loop; this is going to stop it from continually displaying, which is what you want. However, we still need to isolate the element within the array that is an acceptable condition. By setting our userWonNum outside of the for loop with a value of -1 (An impossible win condition), it protects from an accidental win. Then we loop through our array and find a winning number and assign it to that variable. Once the loop is completed, then it will move to the next block and check if we had one.
Exciting tip on this. If you loop through with more than one winning number, it will re-assign multiple times if you implement more than one winning number, but for now, it will work.
int userWonNumber = -1;
for (int i = 0; i < userGuessNums.Length; i++)
{
if (userGuessNums[i] == randomNumber)
{
userWonNumber = randomNumber;
}
}
if (userWonNumber == randomNumber)
{
Console.WriteLine("Congrats, you won!");
}
else
{
Console.WriteLine("Sorry you lost!");
}

cannot figure out while random number generator game is not working c#

I am programming a game that generates a random number and then has the user try to guess the number when the user inputs a number the program will respond with either too high or too low depending on the number generated.The problem I am having is that the loop will just keep executing and the program will not take another user input if the number is incorrect.I have tried using different types of loops like a do while and for loop but keep getting the same problem I feel as though I am missing something simple or making a simple mistake thanks
string usernumber;
Random rnd = new Random();
int value = rnd.Next(1,50); //generates a random number upto 50
int guess = 0;
Console.WriteLine("please enter a number"); //asks for and takes user input
usernumber = Console.ReadLine();//stores user input
guess = Convert.ToInt32(usernumber);
while (guess != value) //this stands for not equals to
{
//guess = Convert.ToInt32(usernumber);
if (value > guess)
{
Console.WriteLine("too high");
}
else if (value < guess)
{
Console.WriteLine("too low");
}
else if (value == guess)
{
Console.WriteLine("bang on the answer was" + value);
}
else
{
Console.WriteLine("errrrrrrrrr");
}
}
Thread.Sleep(2000); //delays the program closing for a bit
You can use this corrected and refactored to have more explicit variables names.
We add 1 to 50 because the Random.Next last parameter is the upper bound excluded.
We use a do...while loop to have a concise algorithm.
We use int.TryParse to get the int from the user. This method returns false and sets the value to 0 in case of conversion error instead of an exception.
We use Console.ReadKey instead of Thread.Sleep, that is more UX friendly.
var random = new Random();
int numberTarget = random.Next(1, 50 + 1);
int numberUser;
do
{
Console.Write("Please enter a number between 1 and 50: ");
if ( int.TryParse(Console.ReadLine(), out numberUser) )
{
if ( numberUser > numberTarget )
{
Console.WriteLine("Too high, retry.");
}
else
if ( numberUser < numberTarget )
{
Console.WriteLine("Too low, retry.");
}
else
{
Console.WriteLine($"Bang on the answer was {numberTarget}.");
}
}
else
{
Console.WriteLine("You didn't enter a valid number, retry.");
}
}
while ( numberUser != numberTarget );
Console.WriteLine("Press a key to exit.");
Console.ReadKey();
In your while loop, you forgot to make another ReadLine.
while (guess != value) //this stands for not equals to
{
if (value > guess)
{
Console.WriteLine("too high");
guess = Convert.ToInt32(Console.ReadLine());
}
else if (value < guess)
{
Console.WriteLine("too low");
guess = Convert.ToInt32(Console.ReadLine());
}
else if (value == guess)
{
Console.WriteLine("bang on the answer was" + value);
}
else
{
Console.WriteLine("errrrrrrrrr");
}
}

How could I convert this goto into a do while loop?

class Program
{
static void Main(string[] args)
{
string choice = string.Empty;
do
{
start:
int output = 0;
int number = 0;
Console.WriteLine("Please input a number for it to be counted!");
bool conversion = int.TryParse(Console.ReadLine(), out output);
if (number < 1000)
{
switch (conversion)
{
case true:
while (number <= output)
{
Console.Write(number + " ");
number += 2;
}
break;
case false:
Console.WriteLine("ERROR: INVALID INPUT!");
goto start;
}
}
else
{
Console.WriteLine("APPLICATION ERROR: NUMBER MUST BE BELOW OR AT 1000 TO PREVENT OVERFLOW!");
return;
}
do // Here is the beginning of the do code
{
Console.WriteLine("\n Do you want to continue - Yes or No");
choice = Console.ReadLine();
if (choice.ToUpper() != "YES" && choice.ToUpper() != "NO")
{
Console.WriteLine("ERROR INVALID INPUT: Only input Yes or No!");
}
} while (choice.ToUpper() != "YES" && choice.ToUpper() != "NO");
} while (choice.ToUpper() == "YES");
}
}
I'm using several do while loops in this statement however I'm trumped on how I would put in a loop "ERROR INVALID INPUT:" result when a user puts in anything other than the limits of the assigned integers (i.e. putting decimals or fractions) or if they put a string. I simply used goto because I'm having trouble finding out where to put the do while loop statement. If someone could simply show me how I might replace that one goto with a do while loop then I would be very greatful. (Note if you show me ways I could optimize my code better since I'm still new I probably won't understand it but your welcome to give it your best shot!)
Short answer:
The keyword continue means to go back to the beginning of the loop. Note that this will recheck the loop condition and break if it is false. Also, most people find do-while loops less readable (and they are really rarely necessary), so try using while loops instead.
There is also the keyword break which will simply exit the loop. (not just for switch-case!)
A more readable version would look something like this:
string userAnswer = "yes";
// while is usually more readable than do-while
while (userAnswer == "yes")
{
Console.WriteLine("Please input a number for it to be counted!");
int number;
// Ask for new input until the user inputs a valid number
while (!int.TryParse(Console.ReadLine(), out number))
{
Console.WriteLine("Invalid number, try again");
}
if (number < 1000)
{
// Print from 0 to number, jumping in 2's
for (int i = 0; i <= number; i += 2)
Console.WriteLine(i + " ");
}
else
{
Console.WriteLine("APPLICATION ERROR: NUMBER MUST BE BELOW OR AT 1000 TO PREVENT OVERFLOW!");
continue; // Jump back to the start of this loop
}
Console.WriteLine("Continue? (Yes / No)");
userAnswer = Console.ReadLine().ToLower();
// Ask for new input until the user inputs "Yes" or "No"
while (userAnswer != "yes" && userAnswer != "no")
{
Console.WriteLine("Invalid input. Continue? (Yes / No)");
userAnswer = Console.ReadLine().ToLower();
}
}
Hey I'll post some code that may help and offer some advice. Basically declare a bool named 'loopCompleted' which will continue the do while loop until you set it to true. The downside is that it will not instantly exit the loop like return/goto/etc but this is not a problem in most cases.
You may want to use if/else instead of switch(conversion), its sort of interesting to see it done that way but its a bit over the top :)
If Int.TryParse() doesnt already return false for fractional values (e.g. [15.08] returns [true] with [15] ). Then you can store Console.ReadLine() before using TryParse, then use stringName.Contains() to check for the '.' Basically, if the conversion succeeds you also check if it contained the decimal point.
Another way to check is to do float.TryParse() then check if it is a fractional value.
bool fraction = false;
if( number % 1.0f > 0)
fraction == true;
% is called modulus, it returns the remainder of A / B
If a number has a remainder when divided by 1 it must be a fractional value.
//start:
bool loopCompleted = false;
do
{
int output = 0;
int number = 0;
Console.WriteLine("Please input a number for it to be counted!");
bool conversion = int.TryParse(Console.ReadLine(), out output);
if (conversion && number < 1000)
{
while (number <= output)
{
Console.Write(number + " ");
number += 2;
}
loopCompleted = true;
}
else
{
if(conversion == false)
{
Console.WriteLine("ERROR: INVALID INPUT!");
}
else
{
Console.WriteLine("APPLICATION ERROR: NUMBER MUST BE BELOW OR AT 1000 TO PREVENT OVERFLOW!");
}
}
} while(!loopCompleted)

I want the program to terminate after 3 incorrect guesses

I'm making a game that gives user 3 guesses and if the user guesses the right number then they will win a car. I also want the user to only have 3 attempts.
static void Main(string[] args)
{
double numberToGuess = 3595.96;
double userGuess = 0;
while (userGuess != numberToGuess)
{
Console.Write("Enter your price guess: ");
userGuess = Convert.ToDouble(Console.ReadLine());
if (userGuess > numberToGuess)
{
Console.WriteLine("£{0} is too high!", userGuess);
}
else if (userGuess < numberToGuess)
{
Console.WriteLine("£{0} is too low!", userGuess);
}
else
{
Console.WriteLine("£{0} is right! Congratulations.", userGuess);
}
} Console.ReadKey();
}
I love school assignments :)
You should create a new variable like int attempts = 0 and increase it at the end of the while loop.
If the attempts greater than 2 you should break the loop.
example:
int attempts = 0;
while (userGuess != numberToGuess)
{
}
attempts++;
if (attempts > 2)
{
Console.WriteLine("Too bad, you didn't make it within three guesses.");
break;
}
} Console.ReadKey();
Clearly, you need a counter to measure how many attempts they've made. What should the type and name of that counter be? The initial value?
Then you need logic that tests that counter against the value 3.
You know how to do that test, right?
And when the test indicates the user has reached 3 guesses, it should exit.
You know how to exit, right?
So whats the problem?
int guessCount = 0;
do
{
// guess logic
...
else
{
// guess is correct
break;
}
}while( ++guessCount < 3 )

Categories