C# console random number guess game - c#

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!

Related

Exception Handling, C#

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.

If statement not working C#

I'm not sure if I'm just really tired and missing something obvious or there is something wrong with my program. Basically my if statement condition is not working.
public bool check(string nextvaluebinary)
{
bool test = true;
for (int i = -1; i < 8; ++i)
{
i++;
System.Console.WriteLine(nextvaluebinary[i] + " " + nextvaluebinary[i + 1]);
if (nextvaluebinary[i] == 1)
{
System.Console.WriteLine("Activated");
if (nextvaluebinary[i + 1] == 0)
{
test = false;
System.Console.WriteLine("false");
}
}
else
{
test = true;
}
if (test == false)
{
break;
}
}
return test;
}
I'm passing in the string 0001010110 and im getting an output of:
0 0
0 1
0 1
0 1
1 0
but no "activated" or "false" even though the last one is "1 0". Again sorry if this is a dumb question and any insight or help would be greatly appreciated.
You're comparing a char against an int. The check you're attempting carries a completely different meaning than what you're trying to accomplish. You need to either check if its equal to '1' or cast the char to an int first so you can do a numeric comparison.
if (nextvaluebinary[i] == '1')
Since nextvaluebinary is a String, this comparison will succeed only if that string has a null character, i.e. '\0':
if (nextvaluebinary[i + 1] == 0)
It looks like you are looking for a zero digit character, instead, so you should write
if (nextvaluebinary[i + 1] == '0')
Equals is used with char to int. So that will use char code.
Use this
public static bool check(string nextvaluebinary)
{
bool test = true;
for (int i = -1; i < 8; ++i)
{
i++;
System.Console.WriteLine(nextvaluebinary[i] + " " + nextvaluebinary[i + 1]);
if (nextvaluebinary[i] == '1')
{
System.Console.WriteLine("Activated");
if (nextvaluebinary[i + 1] == '0')
{
test = false;
System.Console.WriteLine("false");
}
}
else
{
test = true;
}
if (test == false)
{
break;
}
}
return test;
}

Index array out of bounds

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.

WebUtility.HtmlDecode vs HttpUtilty.HtmlDecode

I was using WebUtilty.HtmlDecode to decode HTML. It turns out that it doesn't decode properly, for example, – is supposed to decode to a "–" character, but WebUtilty.HtmlDecode does not decode it. HttpUtilty.HtmlDecode, however, does.
Debug.WriteLine(WebUtility.HtmlDecode("–"));
Debug.WriteLine(HttpUtility.HtmlDecode("–"));
> –
> –
The documentation for both of these is the same:
Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.
Why are they different, which one should I be using, and what will change if I switch to WebUtility.HtmlDecode to get "–" to decode correctly?
The implementation of the two methods are indeed different on Windows Phone.
WebUtility.HtmlDecode:
public static void HtmlDecode(string value, TextWriter output)
{
if (value != null)
{
if (output == null)
{
throw new ArgumentNullException("output");
}
if (!StringRequiresHtmlDecoding(value))
{
output.Write(value);
}
else
{
int length = value.Length;
for (int i = 0; i < length; i++)
{
bool flag;
uint num4;
char ch = value[i];
if (ch != '&')
{
goto Label_01B6;
}
int num3 = value.IndexOfAny(_htmlEntityEndingChars, i + 1);
if ((num3 <= 0) || (value[num3] != ';'))
{
goto Label_01B6;
}
string entity = value.Substring(i + 1, (num3 - i) - 1);
if ((entity.Length <= 1) || (entity[0] != '#'))
{
goto Label_0188;
}
if ((entity[1] == 'x') || (entity[1] == 'X'))
{
flag = uint.TryParse(entity.Substring(2), NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out num4);
}
else
{
flag = uint.TryParse(entity.Substring(1), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out num4);
}
if (flag)
{
switch (_htmlDecodeConformance)
{
case UnicodeDecodingConformance.Strict:
flag = (num4 < 0xd800) || ((0xdfff < num4) && (num4 <= 0x10ffff));
goto Label_0151;
case UnicodeDecodingConformance.Compat:
flag = (0 < num4) && (num4 <= 0xffff);
goto Label_0151;
case UnicodeDecodingConformance.Loose:
flag = num4 <= 0x10ffff;
goto Label_0151;
}
flag = false;
}
Label_0151:
if (!flag)
{
goto Label_01B6;
}
if (num4 <= 0xffff)
{
output.Write((char) num4);
}
else
{
char ch2;
char ch3;
ConvertSmpToUtf16(num4, out ch2, out ch3);
output.Write(ch2);
output.Write(ch3);
}
i = num3;
goto Label_01BD;
Label_0188:
i = num3;
char ch4 = HtmlEntities.Lookup(entity);
if (ch4 != '\0')
{
ch = ch4;
}
else
{
output.Write('&');
output.Write(entity);
output.Write(';');
goto Label_01BD;
}
Label_01B6:
output.Write(ch);
Label_01BD:;
}
}
}
}
HttpUtility.HtmlDecode:
public static string HtmlDecode(string html)
{
if (html == null)
{
return null;
}
if (html.IndexOf('&') < 0)
{
return html;
}
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb, CultureInfo.InvariantCulture);
int length = html.Length;
for (int i = 0; i < length; i++)
{
char ch = html[i];
if (ch == '&')
{
int num3 = html.IndexOfAny(s_entityEndingChars, i + 1);
if ((num3 > 0) && (html[num3] == ';'))
{
string entity = html.Substring(i + 1, (num3 - i) - 1);
if ((entity.Length > 1) && (entity[0] == '#'))
{
try
{
if ((entity[1] == 'x') || (entity[1] == 'X'))
{
ch = (char) int.Parse(entity.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
}
else
{
ch = (char) int.Parse(entity.Substring(1), CultureInfo.InvariantCulture);
}
i = num3;
}
catch (FormatException)
{
i++;
}
catch (ArgumentException)
{
i++;
}
}
else
{
i = num3;
char ch2 = HtmlEntities.Lookup(entity);
if (ch2 != '\0')
{
ch = ch2;
}
else
{
writer.Write('&');
writer.Write(entity);
writer.Write(';');
continue;
}
}
}
}
writer.Write(ch);
}
return sb.ToString();
}
Interestingly, WebUtility doesn't exist on WP7. Also, the WP8 implementation of WebUtility is identical to the desktop one. The desktop implementation of HttpUtility.HtmlDecode is just a wrapper around WebUtility.HtmlDecode. Last but not least, Silverlight 5 has the same implementation of HttpUtility.HtmlDecode as Windows Phone, and does not implement WebUtility.
From there, I can venture a guess: since the Windows Phone 7 runtime is based on Silverlight, WP7 inherited of the Silverlight version of HttpUtility.HtmlDecode, and WebUtility wasn't present. Then came WP8, whose runtime is based on WinRT. WinRT brought WebUtility, and the old version of HttpUtility.HtmlDecode was kept to ensure the compatibility with the legacy WP7 apps.
As to know which one you should use... If you want to target WP7 then you have no choice but to use HttpUtility.HtmlDecode. If you're targeting WP8, then just pick the method whose behavior suits your needs the best. WebUtility is probably the future-proof choice, just in case Microsoft decides to ditch the Silverlight runtime in an upcoming version of Windows Phone. But I'd just go with the practical choice of picking HttpUtility to not have to worry about manually supporting the example you've put in your question.
The methods do exactly the same. Moreover if you try to decompile them the implementations look like one was just copied from another.
The difference is only intended use. HttpUtility is contained in the System.Web assembly and is expected to be used in ASP.net applications which are built over this assembly. WebUtility is contained in the System assembly referenced by nearly all applications and is provided for more general purpose or client use.
Just to notify others who will find this in search. Use any function that mentioned in the question, but never use Windows.Data.Html.HtmlUtilities.ConvertToText(string input). It's 70 times slower than WebUtilty.HtmlDecode and produce crashes! Crash will be named as mshtml!IEPeekMessage in the DevCenter. It looks like this function call InternetExplorer to convert the string. Just avoid it.

Using a for loop inside switch/case

Can I use a for loop inside a switch/case?
Example code:
String[,] drinks = new String[,] { { "Cola", "20" }, { "Fanta", "20" }, { "Sprite", "20" }, { "Tuborg", "25" }, { "Carlsberg", "25" } };
switch (menuChoice)
{
case 0:
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
break;
for (int i = 0; i < drinksCount; i++)
{
case i+1:
buyDrink(drinks[i,0];
break;
}
(More code and methods is in between these)
Basically, I create an array with the drinks this machine sells, and then I want to create a menu where to chose these drinks, but also the ability to add more drinks within the GUI.
Is this even possible?
You can use loops inside switch statement but not the way you are using it currently. Try to replace your code with below code:
if (menuChoice == 0)
{
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
}
else if (menuChoice > 0 && menuChoice < drinksCount)
{
buyDrink(drinks[menuChoice, 0]);
}
ADDED:
As per valuable comments, why don't you just use -1 as menuChoice for Exit, this way:
if (menuChoice == -1)
{
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
}
else if (menuChoice > 0 && menuChoice <= drinksCount)
{
buyDrink(drinks[menuChoice - 1, 0], Convert.ToDouble(drinks[menuChoice - 1, 1]));
}
This way you can call your static method as shown:
static void buyDrink(String drink, double drinkPrice)
A better title for this question might be: Is it possible to have variable case statements?
case i+1:
This is an invalid case statement. A the value of a case statement must be a constant. If i were a constant in this case, it would be allowed. However, i isn't, and therefore the case statement will not compile.
Having said that, although the answer to the title question is yes, as shown by other answers, the real answer here is: Not the way you're trying to do it.
It doesn't make sense to have code after break.
You break from the case how do you expect it to execute?
case 0:
{
break;//If you break here, it exits the block.. your loop never executes
for (int i = 0; i < drinksCount; i++)
{
case i+1:
buyDrink(drinks[i,0];
break;
}
}
And even if it is possible I fail to see the point.
You will execute the case as long as it is greater than 0 right?
So why not just use an if statement, help yourself and others?
if(menuChoice ==0)
{
//dosomething
}
else if(menuChoice >0)
{
//buy drink
}
if(menuChoice == 0) {
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
} else if(menuChoice > 0 && menuChoice <= drinksCount) {
buyDrink(drinks[menuChoice - 1, 0]);
}
That code could not work at all.
A break is the final (and required) statement of a case.
Looking at your example you could simply write
if(menuChoice == 0)
{
Console.WriteLine("Goodbye!");
Thread.Sleep(500);
Environment.Exit(0);
}
else
{
buyDrink(drinks[menuChoice-1,0]);
}
EDIT: Seeing your comment about buyDrink as static method and the parameters required then you should change the call to buyDrink prepending the class name where the buyDrink method is defined and add the parameter for the price (as double value)
.......
else
{
BeverageClass.buyDrink(drinks[menuChoice-1,0], Convert.ToDouble(drinks[menuChoice-1,1]));
}

Categories

Resources