methods program not working of guessing a number - c#

I'm having issues creating a program that is a number guessing program. I think I have the written part right but possibly not the order of it? I have to use multiple methods such as a method for number generator of the number that is supposed to be guessed, a method for collecting the guess input, and method for checking the guess to see if it's right. I've literally have tried just about everything for days but all I get is rather a repeat of, "Enter the number: " even if its right, although it's supposed to repeat if it's too high or low. Or sometimes the console won't print anything. what is wrong? Here is the code:
using System;
namespace GuessTheNumber
{
class Program
{
public static int RandomNumberGenerator()
{
Random random = new Random();
return random.Next(1, 21);
}
public static int InputGetter()
{
Console.Write("Enter in a number: ");
int guess = Convert.ToInt32(Console.ReadLine());
return guess;
}
public static String GuessChecker(int guess, int secretNumber)
{
if(guess > secretNumber)
{
return "Too high!";
}
else if (guess < secretNumber)
{
return "Too low!";
}
else
{
return "Correct";
}
}
static void Main(string[] args)
{
int secretNumber = 10;
Console.WriteLine("" + secretNumber);
while (true)
{
while (InputGetter() != secretNumber)
{
InputGetter();
GuessChecker(InputGetter(), secretNumber);
}
if (GuessChecker(InputGetter(), secretNumber) == ("Correct!"))
{
Console.WriteLine("Would you like to play again?");
String input = Console.ReadLine();
if (GuessChecker(InputGetter(), secretNumber) == ("Yes"))
{
secretNumber = RandomNumberGenerator();
}
else if (GuessChecker(InputGetter(), secretNumber) == ("No"))
{
break;
}
}
}
}
}
}

You are invoking InputGetter() multiple times and your logic is incorrect.
It has nothing to do with Random instance being used.
I have quickly modified your code and it should work now as follows:
New number is generated, if you enter low/high message is displayed, if you enter correct number you are presented with the Would you like to try again message.
EDIT: I did not want to change original code much,In general Comparing strings is bad, you should not use it. Creating enum like and comparing would be much better
class Program
{
public static int RandomNumberGenerator()
{
Random random = new Random();
var generatedNumber = random.Next(1, 21);
Console.WriteLine($"New Number generated! {generatedNumber}");
return generatedNumber;
}
public static int InputGetter()
{
Console.Write("Enter in a number: ");
int guess = Convert.ToInt32(Console.ReadLine());
return guess;
}
public static String GuessChecker(int guess, int secretNumber)
{
if (guess > secretNumber)
{
Console.WriteLine("Too High");
return "Too high!";
}
else if (guess < secretNumber)
{
Console.WriteLine("Too low!");
return "Too low!";
}
else
{
Console.WriteLine("Correct");
return "Correct";
}
}
static void Main(string[] args)
{
int secretNumber = 10;
Console.WriteLine("" + secretNumber);
while (true)
{
int enteredNumber = 0;
do
{
enteredNumber = InputGetter();
} while (GuessChecker(enteredNumber, secretNumber)!="Correct");
Console.WriteLine("Would you like to play again?[Yes/No]");
String input = Console.ReadLine();
if (input=="Yes")
{
secretNumber = RandomNumberGenerator();
}
else
{
break;
}
}
}
}

Related

How to determine input when the can have a variable?

I'm working on this commandline based dice. And I want it to be able to output statistics and reset those internal statistics. Currently I have the following classes: Dice and DiceInterface.
I want the user to be able to use the following format for input: "'Throw' to throw the dice, alternate use 'Throw(x)', 'Stat(side)' to see how many times (side) has been thrown, or 'Reset' to reset thrown statistics"
I need a way to determine if the user has typed Throw, Throw(x), Stat(side) or Reset. Throw and Reset are obvious to me but I find it quite difficult to imagine a way to do Throw(x) and Stat(side). Does anyone have any tips or a solution?
Thanks in advance!
using System;
using System.Collections.Generic;
using System.Text;
namespace Oefening_2
{
class DiceInterface
{
static void Main()
{
StartProgram();
}
static void StartProgram()
{
Console.WriteLine("Hello, how many sides would you like the dice to have?");
var input = Console.ReadLine();
if (Int32.TryParse(input, out int number))
{
int desiredSides = number;
Dice NewDice = new Dice(desiredSides);
Console.WriteLine("What would you like to do? ");
Console.WriteLine("Type: 'Throw' to throw the dice, alternate use 'Throw(x)', 'Stat(side)' to see how many times (side) has been thrown, or 'Reset' to reset thrown statistics");
MainIO(NewDice);
}
else
{
Console.WriteLine("That is not an integer! The program will restart now...");
StartProgram();
}
}
static void MainIO(Dice CurrentDice)
{
Console.Write("Input: ");
string input = Console.ReadLine();
//Throw
if (input == "Throw")
{
Console.WriteLine(CurrentDice.Throw());
MainIO(CurrentDice);
}
//Throw(x)
else if(input == "")
//Thrown(side)
//Reset
else if (input == "Reset")
{
CurrentDice.ResetStatistics();
MainIO(CurrentDice);
}
}
}
}
using System;
namespace Oefening_2
{
class Dice
{
public int Sides { get; set; }
private readonly Random _rnd = new Random();
public int[] Thrown;
public Dice(int sides)
{
Sides = sides;
Thrown = new int[sides--];
}
public Dice():this(6)
{
}
public int Throw()
{
int thrownNumber = _rnd.Next(1, Sides);
Thrown[thrownNumber]++;
return thrownNumber;
}
public int NrOfTimesThrown(int side)
{
int result;
result = Thrown[side];
return result;
}
public void ResetStatistics()
{
for(int i = 0 ; i < Sides; i++)
{
Thrown[i] = 0;
}
}
}
}
This can be fairly simply done with StartsWith to check if a string starts with some prefix, and use .Remove to get anything after this prefix:
if(input.StartsWith("Stat"){
var parameterString = input.Remove(0, "Stat".Length);
if(int.TryParse(parameterString , out var side){
...
}
}
If I correctly understood your problem, it could be solved with an approach like this:
Console.WriteLine("Enter a value");
var s = Console.ReadLine();
if(s.Contains('('))
{
int pFrom = s.IndexOf("(");
int pTo = s.LastIndexOf(")");
var myChoice = s.Substring(0, pFrom);
var myValue = s.Substring(pFrom + 1, pTo - pFrom);
Console.WriteLine($"You choosed : {myChoice}");
Console.WriteLine($"With a value of: {myValue}");
}
This is just a brief example of how to "understand" if there is a value and then recover it.
I hope this could help you somehow.

goto - not within scope (C#)

I am very new to code. Can anyone in a simple way explain why I cant use the goto statement like this, to make the code start over again? Or, how this could have been done in the correct way? And also, why I get an error message on the use of "static".
**
"No such label "Start" within the scope of the goto statmenet"
"The modifier static is not valid for this item"
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
Start:
Random numberGenerator = new Random();
int num1 = numberGenerator.Next(1,11);
int num2 = numberGenerator.Next(1, 4);
Console.WriteLine("What is " + num1 + " times " + num2 + "?");
int svar = Convert.ToInt32(Console.ReadLine());
if (svar == num1 * num2)
{
Console.WriteLine("well done!");
}
else
{
int responseIndex = numberGenerator.Next(1, 4);
switch (responseIndex)
{
case 1:
Console.WriteLine("Wrong, try again? [Y or N]");
AskUser();
break;
case 2:
Console.WriteLine("The answer was incorrect");
AskUser();
break;
default:
Console.WriteLine("You can do better than that");
AskUser();
break;
}
static void AskUser() {
string jaellernei = Console.ReadLine().ToUpper();
if (jaellernei == "Y")
{
goto Start;
} else
{
return;
} }
}
}
}
}
Firstly, your AskUser method is incorrectly nested inside the other method - move it out.
Secondly: goto is only valid within a single method; you can jump around a single stack frame - you cannot jump between stack frames.
Thirdly: the number of times you should be using goto... well, it isn't quite zero, but it asymptotically approaches zero.
Don't use goto unless you MUST to !
and As #Marc Gravell said, it's valid within a single method.
Alternatively : you can make a method of the code u used in the Main method, and then call it from both, main method and the other method where you used goto statement.
Like :
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
someFunction();
}
static void someFunction()
{
Random numberGenerator = new Random();
int num1 = numberGenerator.Next(1, 11);
int num2 = numberGenerator.Next(1, 4);
Console.WriteLine("What is " + num1 + " times " + num2 + "?");
int svar = Convert.ToInt32(Console.ReadLine());
if (svar == num1 * num2)
{
Console.WriteLine("well done!");
}
else
{
int responseIndex = numberGenerator.Next(1, 4);
switch (responseIndex)
{
case 1:
Console.WriteLine("Wrong, try again? [Y or N]");
AskUser();
break;
case 2:
Console.WriteLine("The answer was incorrect");
AskUser();
break;
default:
Console.WriteLine("You can do better than that");
AskUser();
break;
}
}
}
static void AskUser()
{
string jaellernei = Console.ReadLine().ToUpper();
if (jaellernei == "Y")
{
someFunction();
}
else
{
return;
}
}
}
}
You could do it like this
public static Random randd = new Random();
public static void FlachCards()
{
Start:
if (AskAUser() == "Y")
{
goto Start;
}
}
public static String AskAUser()
{
Console.WriteLine("Enter Y to play again");
return Console.ReadLine();
}

Noob needing help on breaking out of loop

I'm very sorry this is such an easy question, I'm just starting out. I've created code that allows a user to enter a number of random dice rolls, and outputs the sum of those rolls. I've now been asked to create a loop that repeats these steps, including the prompt, until the user types 'quit'. My issue is that my code converts the string to an integer, so typing anything kills the code. Any tips of how to insert the loop and break? My code is:
static void Main(string[] args)
{
Random random = new Random();
Console.WriteLine("Enter a number of dice to roll:");
string numberDiceString = Console.ReadLine();
int numberDice = Convert.ToInt32(numberDiceString);
int total = 0;
for (int index = 0; index < numberDice; index++)
{
int DieRoll = random.Next(6) + 1;
total += DieRoll;
}
Console.WriteLine(total);
Console.ReadKey();
}
I wouldn't use a "while(true)" statement. As someone pointed out in the comments i would prefer using the right condition in there.
That being said i would do it this way:
static void Main(string[] args)
{
Random random = new Random();
string numberDiceString;
int numberDice;
Console.WriteLine("Enter a number of dice to roll:");
while ((numberDiceString = Console.ReadLine()) != "quit")
{
bool parsed = int.TryParse(numberDiceString, out numberDice);
if (!parsed)
{
//Handle the error. The user input was not a number or "quit" word
break;
}
int total = 0;
for (int index = 0; index < numberDice; index++)
{
int DieRoll = random.Next(6) + 1;
total += DieRoll;
}
Console.WriteLine(total);
Console.WriteLine("Enter a number of dice to roll:");
}
}
I have to say that i prefer this way because you can easily see when the loop will stop. Also i added an error handling that you should be doing (What happen if the user enters any words that are not numbers?).
Hope this helps.
This change should be fairly simple. What you need to do is to create a while loop, and then a check before you actually parse for an int. The psuedocode for this would be something like.
while(true) {
//Ask for input
//Check if it equals "quit"
//If so -> break;
//If not convert to int
//For Loop for dice rolls
//Print Total
}
I'm sure it could be a little more elegant than this, and you would want to put some more checks to make sure that invalid input doesn't crash the program, but it should get the job done.
This is a very simple solution that shows how to parse the user input.
using System;
namespace Simpleton
{
class Program
{
static public int GetChoice()
{
int choice = 0;
while (true)
{
Console.Write("Enter number of rolls or \"quit\" to finish: ");
var answer = Console.ReadLine();
if (String.Compare(answer, "quit", true) == 0)
{
return 0; // Done
}
if (Int32.TryParse(answer, out choice))
{
return choice;
}
}
}
static void Main(string[] args)
{
var choice = 0;
while ((choice = GetChoice()) > 0)
{
Console.WriteLine($"You'll be looping {choice} times.");
for (int tries = 0; tries < choice; tries++)
{
// Looping
}
}
}
}
}
Try this code:
static void Main(string[] args)
{
Random random = new Random();
while(true)
{
String numberDiceString = "";
int numberDice = 0;
Console.WriteLine("Enter a number of dice to roll:");
numberDiceString = Console.ReadLine();
if (numberDiceString == "quit") { return; }
int total = 0;
if (Int32.TryParse(numberDiceString, out numberDice))
{
total = 0;
for (int index = 0; index < numberDice; index++)
{
int DieRoll = random.Next(6) + 1;
total += DieRoll;
}
}
Console.WriteLine(total);
}
}
I'm not a C# programmer, but you can test for "quit" explicitly and use a goto
BeginLoop:
Console.WriteLine("Enter a number of dice to roll:");
string numberDiceString = Console.ReadLine();
if (numberDiceString == "quit")
{
goto EndLoop;
}
int numberDice = Convert.ToInt32(numberDiceString);
/* Rest of code you want to do per iteration */
goto BeginLoop;
EndLoop:

Changing ConsoleKeyInfo into int

I am new to the programing c#. I tried to program a simple program that would run in cmd. I thought that it would randomly creat a noumber and the user would put in the numbers and he/she would try to guess the randomly created one. The program would tell you if it is lower or higher then the number you putted in... I started programing but I came to the problem... I can not compare noumber putted in by user and the randomly generated one.
This is the code...
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Guess the number!");
Random randomObject = new Random();
int RandNoumber = randomObject.Next(9999) + 1;
ConsoleKeyInfo keyinfo = Console.ReadKey();
if (keyinfo < RandNoumber) //This is where I got an error msg
{
}
}
}
Thank you for all the support!
MP
You could use Consol.ReadLine and then parse the value the user entered
static void Main(string[] args)
{
Console.WriteLine("Guess the number!");
Random randomObject = new Random();
int RandNoumber = randomObject.Next(9999) + 1;
int enteredNumber;
while (true)
{
bool parsed = int.TryParse(Console.ReadLine(), out enteredNumber);
if (parsed)
{
if (enteredNumber < RandNoumber)
{
Console.WriteLine("Wrong it's higher");
}
else if (enteredNumber > RandNoumber)
{
Console.WriteLine("Wrong it's lower");
}
else
{
Console.WriteLine("Good Job!");
//Do victory dance
return;
}
}
else
{
Console.WriteLine("Please enter a number");
}
}
}

How can I catch five consecutive numbers in an array of int[5] in C#?

I wrote this little program that catches five integer numbers that are entered consecutively at the console.
This works as expected - except for one thing:
I did not find a way to accept 0 as one of the numbers being entered.
Of course, a solution with another collection type is easy.
But the challenge here is to do it with an array of five integers.
I tried to set a boolean flag "zeroEntered", tried with a counter, tried to count j backwwards. It all does not work.
Perhaps this is not possible? Would somebody know for sure?
Here is the code:
class Program
{
static void Main(string[] args)
{
#region Catch5IntegerInArrayOfInt[5]
// I try to catch five integers in an array of int[5]
// This works as expected except I cannot catch 0 as one of the numbers
// Cannot wrap my head around this one it seems
// because all ints are initialized with 0
Console.WriteLine("Please enter five unique numbers consecutively.");
int[] fiveNumbers = new int[5]; // do it using an array just the same (as collections were not part of the lectures so far)
for (int i = 0; i < fiveNumbers.Length; i++)
{
Console.WriteLine("Please enter your {0} number:", (Countables)i);
CatchUsersNumbers(fiveNumbers, i);
}
DisplayResult(fiveNumbers);
Console.WriteLine("\n");
}
#endregion
#region HelperMethods
private static bool CheckWhetherInteger(string userInput)
{
bool result = Int32.TryParse(userInput, out myInteger);
if (result == false)
{
Console.Clear();
Console.WriteLine("You did not enter an integer.");
}
return result;
}
private static bool CheckUniqueness(int[] fiveNumbers, int userInput)
{
for (int i = 0; i < fiveNumbers.Length; i++)
{
if (userInput == 0)
{
for (int j = i ; j <fiveNumbers.Length; j--)
{
if (j == 0)
break;
if (fiveNumbers[j] == 0)
{
return false;
}
}
}
else if (fiveNumbers[i] == userInput)
{
return false;
}
}
return true;
}
private static void CatchUsersNumbers(int[] fiveNumbers, int i)
{
while (true)
{
userInput = Console.ReadLine().Trim();
if (CheckWhetherInteger(userInput) && CheckUniqueness(fiveNumbers, myInteger))
{
fiveNumbers[i] = myInteger;
break;
}
else
Console.Clear();
Console.WriteLine("You did not enter a unique integer number, try again...");
}
}
private static void DisplayResult(int[] fiveNumbers)
{
Console.Clear();
Array.Sort(fiveNumbers);
Console.WriteLine("These are the five interger numbers you entered \nand that were stored in the array:\n");
for (int i = 0; i < fiveNumbers.Length; i++)
{
if (i != fiveNumbers.Length - 1)
Console.Write(fiveNumbers[i] + ", ");
else
Console.Write(fiveNumbers[i]);
}
}
#endregion
#region Class Variables
private static int myInteger = 0;
private static string userInput;
private enum Countables
{
first = 0,
second,
third,
fourth,
fifth
}
#endregion
}
Thank you.
It is possible, but your array of 5 ints will be initialized to 5 zeroes, so when scanning for uniqueness, your check fails, especially because of this piece of code:
if (fiveNumbers[j] == 0)
{
return false;
}
So instead of looping through the entire array, you should keep a counter to keep track of how many items you already have in your array. Then, when performing the check, only check upto that index, and don't include the other items in the check, because they contain 0, but you should treat them as uninitialized.
You could also solve this using other data types. For instance, you could create an array of nullable integers, so you can actually check whether an item already got a value. Or (maybe the best solution) you could use a List instead of array.
Your Only error here is that int.TryParse() takes 0 as invalid you could make another if statement to handle the exception but this looks less clean
private static bool CheckWhetherInteger(string userInput)
{
if (userInput == "0")
{
myInteger = 0;
return true
}
else
{
bool result = Int32.TryParse(userInput, out myInteger);
if (result == false)
{
Console.Clear();
Console.WriteLine("You did not enter an integer.");
}
}
return result;
}
I just post the solution - using nullable integers - as suggested by Golez Trol. Here it is, should somebody be interested:
class Program
{
static void Main(string[] args)
{
#region Catch5IntegerInArrayOfInt[5]
// The solution to catching five integers in an array of int[5]
// is to use nullable integers.
// Keeping a counter when entering an integer to the array does not appeal to me.
// With normal integers I cannot catch 0 as one of the numbers
// because all ints are initialized with 0
Console.WriteLine("Please enter five unique numbers consecutively.");
var fiveNumbers = new int?[5]; // do it using an array just the same (as collections were not part of the lectures so far)
for (int i = 0; i < fiveNumbers.Length; i++)
{
Console.WriteLine("Please enter your {0} number:", (Countables)i);
CatchUsersNumbers(fiveNumbers, i);
}
DisplayResult(fiveNumbers);
Console.WriteLine("\n");
}
#endregion
#region HelperMethods
private static void CatchUsersNumbers(int?[] fiveNumbers, int i)
{
while (true)
{
userInput = Console.ReadLine().Trim();
if (CheckWhetherInteger(userInput) && CheckUniqueness(fiveNumbers, myInteger))
{
fiveNumbers[i] = myInteger;
break;
}
else
{
Console.Clear();
Console.WriteLine("You did not enter a unique integer number, try again...");
}
}
}
private static bool CheckWhetherInteger(string userInput)
{
bool result = Int32.TryParse(userInput, out myInteger);
if (result == false)
{
Console.Clear();
Console.WriteLine("You did not enter an integer.");
}
return result;
}
private static bool CheckUniqueness(int?[] fiveNumbers, int userInput)
{
for (int i = 0; i < fiveNumbers.Length; i++)
{
if (fiveNumbers[i] == userInput)
{
return false;
}
}
return true;
}
private static void DisplayResult(int?[] fiveNumbers)
{
Console.Clear();
Array.Sort(fiveNumbers);
Console.WriteLine("These are the five interger numbers you entered \nand that were stored in the array:\n");
for (int i = 0; i < fiveNumbers.Length; i++)
{
if (i != fiveNumbers.Length - 1)
Console.Write(fiveNumbers[i] + ", ");
else
Console.Write(fiveNumbers[i]);
}
}
#endregion
#region Class Variables
private static int myInteger = 0;
private static string userInput;
private enum Countables
{
first = 0,
second,
third,
fourth,
fifth
}
#endregion
}
Thank you for your hints - I was truly stuck.

Categories