I came across this situation however I don't know how do I handle this exception when the user enters a number outside of the index of the string or any other datatype. In that condition I want the program to display the exception and go back to the first if statement. The code must be as basic as possible as I have just started learning programming. I know the use of 'Try Catch' (or so I think) but I can't determine how to use it here.
choice = int.Parse(Console.ReadLine());
if (arr[choice] != 'X' && arr[choice] != 'O')
{
if (player % 2 == 0)
{
arr[choice] = 'O';
player++;
}
else
{
arr[choice] = 'X';
player++;
}
}
else
{
Console.WriteLine("Sorry the row {0} is already marked with {1}", choice,arr[choice]);
Console.WriteLine("\n");
}
You can do it like this:
int choice;
bool isValidChoice = int.TryParse(Console.ReadLine(), out choice) && choice >= 0 && choice < arr.Length;
if (isValidChoice && arr[choice] != 'X' && arr[choice] != 'O') {
if (player % 2 == 0) {
arr[choice] = 'O';
player++;
} else {
arr[choice] = 'X';
player++;
}
} else if (!isValidChoice) {
Console.WriteLine("Sorry you have not entered a valid in-range integer");
} else {
Console.WriteLine("Sorry the row {0} is already marked with {1}", choice, arr[choice]);
Console.WriteLine("\n");
}
Some explanations:
int.TryParse, is effectively the equivalent of
int choice;
bool isValid = false;
try {
choice = int.Parse(Console.ReadLine());
isValid = true;
} catch {}
&& will only be evaluated only when the previous statement is correct. So in
choice >= 0 && choice < arr.Length the choice < arr.Length will only be checked if the choice >= 0 is correct
If you want to retry as long as the input is invalid. Try using the while(!isValidChoice) loop. I will not tell you how, as I think it will be a good learning experience.
Related
I have a question about the following code I have written for a C# Programming course assignment. Everything seems to be functioning correctly except for the if statement on line 31 which checks if the input string fed into a conversion method matches the requirements given in the if statement.
The logic chain of the if statements is as follows:
If the user entered less than 2 chairs, tell them they must buy at least 2 chairs.
If the user entered 2 or more chairs, proceed to next iteration of loop and check the next else if statement.
If user entered 2 or more chairs and the wood variable is not string "pine", "maple", or "oak, enter this else if block.
Give user a chance to enter a value. Acceptable values are "p", "m", and "o".
Convert single-character string to string with woodType method, which returns "pine", "maple", or "oak" based on what they input.
If user did not enter an acceptable value, return to loop after telling the user to try again.
This is where the hang-up is. If they input a valid value, the logic chain should proceed to the final else if block, but it does not. See commented line 30. Uncomment this line and it returns the name of the wood correctly from the method.
Final else if block: if everything was good, repeat the order to the user, calculate the cost, and return the final cost.
For some reason, the logic is failing at step 7 and remaining in the loop, continuously demanding the user input a valid value even though it has received a valid value. Perhaps there is something wrong with how I am comparing the strings? Obviously, there is something wrong here, but I'm unable to put my finger on it.
Here is the source code:
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
public class Tables {
static int chairs = 0;
static string wood = string.Empty;
static bool run = true;
const double CHAIR_PRICE = 50.00;
static Dictionary<string, double> PRICES = new Dictionary<string, double> {
{ "pine", 250.00 },
{ "maple", 300.00 },
{ "oak", 350.00 }
};
public static void Main() {
while (run == true) {
if (chairs < 2) {
Console.WriteLine("Enter the number of chairs: ");
chairs = chairCount(Console.ReadLine());
//Console.WriteLine("{0}", chairs);//Debug
if (chairs < 2) {
Console.WriteLine("You must order at least two chairs.");
}
} else if (chairs >= 2 && (wood != "pine" || wood != "maple" || wood != "oak")) {
Console.WriteLine("Enter the type of wood - [p]ine, [m]aple, or [o]ak: ");
wood = woodType(Console.ReadLine());
//Console.WriteLine("{0}", wood);//Debug
if (wood != "pine" || wood != "maple" || wood != "oak") {
Console.WriteLine("You must enter p, m, or o for wood type.");
}
} else if (chairs >= 2 && (wood == "pine" || wood == "maple" || wood == "oak")) {
Console.WriteLine("You have ordered a {0} table with {1} chairs.", wood, chairs);
Console.WriteLine("Total price is {0}", costCalc(wood, chairs).ToString("C", new CultureInfo("en-us")));
run = false;
}
}
}
static int chairCount(string input) {
return Convert.ToInt32(input);
}
static string woodType(string input) {
if (input == "p") { return "pine"; }
else if (input == "m") { return "maple"; }
else if (input == "o") { return "oak"; }
else { return "invalid"; }
}
static double costCalc(string wood, int chairs) {
return PRICES[wood] + (chairs * CHAIR_PRICE);
}
}
This condition
(chairs >= 2 && (wood != "pine" || wood != "maple" || wood != "oak"))
is always going to be true if chairs >= 2
you mean
(chairs >= 2 && (wood != "pine" && wood != "maple" && wood != "oak"))
But this code can be made much much simpler
while(true){
Console.WriteLine("Enter the number of chairs: ");
chairs = chairCount(Console.ReadLine());
if (chairs < 2) {
Console.WriteLine("You must order at least two chairs.");
} else {
break
}
}
while(true){
Console.WriteLine("Enter the type of wood - [p]ine, [m]aple, or [o]ak: ");
wood = woodType(Console.ReadLine());
if (wood != "pine" && wood != "maple" && wood != "oak") {
Console.WriteLine("You must enter p, m, or o for wood type.");
} else{
break;
}
}
no big outer loop needed
I have the following C# Code
int amount_guesses = 2;
int c_answer = 4;
int u_answer = 0;
Console.WriteLine("Guessing Game");
Console.WriteLine("*Hint:The number is between 1 and 5");
Console.WriteLine("*Hint:You only get 2 guesses");
while (u_answer != c_answer || amount_guesses != 0)
{
u_answer = Convert.ToInt32(Console.ReadLine());
amount_guesses = amount_guesses-1;
if (u_answer == c_answer)
{
Console.WriteLine("Well Done that is the Correct Number");
}
else
{
Console.WriteLine("Wrong Number!Try again.You have {0} trys left", amount_guesses);
}
}
Console.WriteLine("Press any key to close");
Console.ReadLine();
But it's not jumping out of the loop when the requirements in the while statement are not met.
I also tried
while ((u_answer != c_answer) || (amount_guesses != 0))
But it's still not working, I ended changing the logic to this:
int amount_guesses = 2;
int c_answer = 4;
int u_answer = 0;
Console.WriteLine("Guessing Game");
Console.WriteLine("*Hint:The number is between 1 and 5");
Console.WriteLine("*Hint:You only get 2 guesses");
while (u_answer != c_answer && amount_guesses != 0)
{
u_answer = Convert.ToInt32(Console.ReadLine());
amount_guesses = amount_guesses-1;
if (u_answer == c_answer)
{
Console.WriteLine("Well Done that is the Correct Number");
amount_guesses = 0;
}
else
{
Console.WriteLine("Wrong Number!Try again.You have {0} trys left", amount_guesses);
}
}
Console.WriteLine("Press any key to close");
Console.ReadLine();
That works fine, but I wanted to know why my code at the top where I use || does not work?
A while loop continues as long as its condition is met. In your case, you want to continue loop as long as the player hasn't guessed the number and has guesses left. You should use an && (logical AND) condition, not an ||:
while (u_answer != c_answer && amount_guesses != 0)
{
// Here ----------------^
This is a common(ish) issue when using negation in boolean logic. OR sounds like it should be right as it matches are English way of speaking, but actually AND is what you want.
I try to always write the condition testing for equality and then negate it, so instead of:
u_answer != c_answer && amount_guesses != 0
You can write:
!(u_answer == c_answer || amount_guesses == 0)
Which is the same condition.
Take a look at De Morgams Law, also more easily remembered as
Break the line, change the sign
I'm working on a random number guessing game as a c# console program. It's done with the code and working. However, there is a part that I want to make better:
I declared an instance of a Guess class I created, now how to make this part more efficient?
int counter = 0;
do
{
myGuess.UserGuess = GetUserGuess(); //read user guess
if (myGuess.Compair() == "match")
{
Console.WriteLine("\n\t Correct!You WIN !");
}
else if (myGuess.Compair() == "high")
{
if (counter < 3)
Console.WriteLine("\n\tTry a lower number,");
else
Console.WriteLine("\n\tSorry you LOSE !, The right number is " + myGuess.RndNum);
counter++;
}
else if (myGuess.Compair() == "low")
{
if (counter < 3)
Console.WriteLine("\n\tTry a higher number,");
else
Console.WriteLine("\n\tSorry you LOSE !, The right number is " + myGuess.RndNum);
counter++;
}
} while (myGuess.Compair() != "match" && counter < 4);
Thanks in advance.
What does "Compair()" function look like? It seems like that could return an integer rather than a string for a simpler function. An example of that looks like:
// just an example implementation
public int Compair() {
if (UserGuess < actualValue) return -1;
if (UserGuess > actualValue) return 1;
return 0;
}
And then your routine becomes:
int counter = 0;
bool success = false;
do
{
myGuess.UserGuess = GetUserGuess();
int compair= myGuess.Compair()
switch (compair) {
case 0:
Console.WriteLine("\n\t Correct!You WIN !");
success = true;
break;
case 1:
case -1:
if (counter < 3) Console.WriteLine("\n\tTry a {0} number,", compair == -1 ? "lower" : "higher");
break;
}
counter++;
if (counter >= 3 && !success)
Console.WriteLine("\n\tSorry you LOSE !, The right number is " + myGuess.RndNum);
} while (!success && counter < 4);
That should do it! This should be faster because it isn't using string comparisons, it might be a bit easier to read and it should have fixed a few logical issues.
Note - I made a few assumptions about the use of properties so this example might not compile out of the get but it should get you most of the way there. Best of luck!
if (testModetrue)
{
try
{
Console.Write("What number do you want the roll to be set to? (1-6)");
string diceString = Console.ReadLine();
int diceCheck = int.Parse(diceString);
if ((diceCheck >= minDiceValue) || (diceCheck <= maxDiceValue))
{
diceNo = int.Parse(diceString);
}
else if ((diceCheck <= minDiceValue) || (diceCheck >= maxDiceValue))
{
Console.WriteLine("Please enter a number between 1-6.");
break;
}
}
catch (Exception)
{
Console.WriteLine("An error has occured.");
return;
}
}
This code checks to see whether the answer given doesn't go past 6 or below 1, however whenever I run it, it does it anyway then it throws the out of array error, anybody help?
int diceCheck = int.Parse(diceString);
if ((diceCheck >= minDiceValue) || (diceCheck <= maxDiceValue))
{
diceNo = int.Parse(diceString);
}
This conditional should be AND rather than OR. Also, since you're parsing the string before the conditional, you don't need to do it inside it, so you should change that part to:
int diceCheck = int.Parse(diceString);
if (diceCheck > maxDiceValue && diceCheck < minDiceValue)
{
Console.Writeline("Please write a number between 1 and 6");
break;
}
Your other if statement was also kind of redundant because you already have other variable (dicecheck) with the value, so remove it.
private const int maxDiceValue = 6;
private const int minDiceValue = 1;
Console.Write("What number do you want the roll to be set to? (1-6)");
string diceString = Console.ReadLine();
int diceCheck;
if (!int.TryParse(diceString, out diceCheck) ||
diceCheck < minDiceValue ||
diceCheck > maxDiceValue) {
Console.WriteLine("Please enter a number between 1-6.");
return;
}
// add diceCheck to array here
Lets imagine the user introduce -1.
In the first condition you are validating if -1 >= 1 which is false, but you are also validating if -1 <= 6 which is true.
Instead of && (AND ALSO) you are using || (Or Else).
Since one of the condition is always true, the validating will always return true and therefore the code will run throwing an error.
thanks to the community here I was able to write my first program. However, I still need some help to improve the program:
Console.WriteLine("BMI Rechner");
Console.WriteLine("===========");
Console.WriteLine();
Console.Write("Körpergewicht in kg: ");
int kg;
kg = Convert.ToInt32(Console.ReadLine());
Console.Write("Größe in cm: ");
int cm;
cm = Convert.ToInt32(Console.ReadLine());
Console.Write("Geschlecht (m/w):");
string Geschlecht = Console.ReadLine();
bool Auswahl = false;
switch(Geschlecht)
{
case "m":
Auswahl = true;
break;
case "w":
Auswahl = true;
break;
default:
Console.WriteLine("Ungültige Eingabe");
Console.WriteLine("(m)ännlich/(w)eiblich");
break;
}
if (Auswahl != false) {Console.WriteLine("Eingabe wird verarbeitet");}
double BMI = kg / ( (cm / 100.0) * (cm / 100.0) );
if (BMI < 19 & Geschlecht == "w")
{ Console.WriteLine("-> Untergewicht"); }
else if (BMI >= 19 & BMI <= 24 & Geschlecht == "w")
{ Console.WriteLine("-> Normalgewicht"); }
else if (BMI > 24 & Geschlecht == "w")
{ Console.WriteLine("-> Übergewicht"); }
if (BMI < 20 & Geschlecht == "m")
{ Console.WriteLine("-> Untergewicht"); }
else if (BMI >= 20 & BMI <= 25 & Geschlecht == "m")
{ Console.WriteLine("-> Normalgewicht"); }
else if (BMI > 25 & Geschlecht == "m")
{ Console.WriteLine("-> Übergewicht"); }
Console.ReadLine();
I made a switch thingie in the middle to prevent the program from crashing if a wrong input is given. It works and I get these lines:
Console.WriteLine("Ungültige Eingabe");
Console.WriteLine("(m)ännlich/(w)eiblich");
which is supposed to be my "loop" back to the options "m" and "w". However, if I enter m/w now, the program just closes, meaning that it doesn't work at all.
Is there an error in my code or am I just using the wrong command?
I apologize for my command of the programming lingo. This is my first time.
Thanks in advance!
To be honest I don't see any loop in your code.
You could do what you say using a do...while loop as such:
do
{
//...
}while (Geschlecht != "m" && Geschlecht != "w");
The do...while loop will check after the each iteration (not before, meaning it will always enter in the loop at least once). In this case the condition says that it will loop as long as Geschlecht is not "m" and is not "w".
Applying this to your code, you will get:
//...
bool Auswahl = false;
string Geschlecht;
do
{
Console.Write("Geschlecht (m/w):");
Geschlecht = Console.ReadLine();
switch(Geschlecht)
{
case "m":
Auswahl = true;
break;
case "w":
Auswahl = true;
break;
default:
Console.WriteLine("Ungültige Eingabe");
Console.WriteLine("(m)ännlich/(w)eiblich");
break;
}
}while (Geschlecht != "m" && Geschlecht != "w");
if (Auswahl != false) {Console.WriteLine("Eingabe wird verarbeitet");}
//etc...
Please notice I have taken two variable out of the loop, those are Auswahl and Geschlecht. The reason is because both are needed to be available outside of the loop, in particular Geschlecht is needed in the conditional.
Jimmy comments that it is possible to do this in such way that Auswahl is no longer needed... here is one way to do it (as valid as any other):
//...
Console.Write("Geschlecht (m/w):");
string Geschlecht = Console.ReadLine();
while (Geschlecht != "m" && Geschlecht != "w");
{
Console.WriteLine("Ungültige Eingabe");
Console.WriteLine("(m)ännlich/(w)eiblich");
Console.Write("Geschlecht (m/w):");
Geschlecht = Console.ReadLine();
}
Console.WriteLine("Eingabe wird verarbeitet");
//etc...
In this case we have a while loop, in code inside the loop will only execute if the condition is met (that is, the condition is verified before each iteration).
You may also consider to have a different data type for Geschlecht since the only valid values it has are "m" and "w"... but I digress.
I want to suggest the entry C# Loops Constructs at dotnetperls as an introducion to the different kinds of loops in C#.