I'm trying to write a program that consists of some items (only 2 of them for now). It doesn't show any errors in the console, but when I try to call the Main function more than once, it doesn't execute the loops inside. Here's the code by the way.
public static class Program
{
public static string input = Convert.ToString(Console.ReadLine());
public static int health = 100;
public static int energy = 100;
public static void Main()
{
Console.WriteLine("This is a game used for testing items");
Console.WriteLine("Would you like to use items or get them? (Typing in status shows the value of your health and energy)");
if (Program.input == "get")
{
Items.GetItems();
}
if (Program.input == "use")
{
ItemUser();
}
if (Program.input == "status")
{
StatusChecker();
}
}
public static void StatusChecker()
{
Console.WriteLine("Your health is " + Program.health);
Console.WriteLine("Your energy is " + Program.energy);
}
public static void ItemUser()
{
Console.WriteLine("What do you want to use?");
string useChecker = Convert.ToString(Console.ReadLine());
if (useChecker == "healthPotion")
{
health += 100;
Items.healthPotion--;
}
if (useChecker == "energyDrink")
{
energy += 100;
Items.energyDrink--;
}
}
}
public static class Items
{
public static int healthPotion = 0;
public static int energyDrink = 0;
public static void GetItems()
{
Console.WriteLine();
string itemChecker = Convert.ToString(Console.ReadLine());
if ( itemChecker == "health potion")
{
healthPotion++;
Program.Main();
}
if (itemChecker == "energy drink")
{
energyDrink++;
Program.Main();
}
}
So I wanted the program to get the values after updating them, but it just stops after I call Main method more than once. Can anyone help me?
(I'm not that great at coding so I couldn't make really efficient code)
You don't have any loops inside your Main method and every time you run the application you start from scratch and each of your variables contain initial values. If I get right what you're trying to achieve, I would suggest you to write the Main method like this to have loop which will ask a user for a command until the user enters "quit":
static void Main(string[] args)
{
Console.WriteLine("This is a game used for testing items");
while (true)
{
Console.WriteLine("Would you like to use items or get them? (Typing in status shows the value of your health and energy)");
string userAnswer = Console.ReadLine();
if (userAnswer == "quit") break;
if (userAnswer == "get")
{
Items.GetItems();
}
if (userAnswer == "use")
{
ItemUser();
}
if (userAnswer == "status")
{
StatusChecker();
}
}
}
I noticed also that when you call ItemUser method you update static variables of your Items class, but in the StatusChecker method you write to the console variables of your Program class. They are actually different, so I think in your StatusChecker method you may want do the following:
public static void StatusChecker()
{
Console.WriteLine("Your health is " + Items.health);
Console.WriteLine("Your energy is " + Items.energy);
}
You are assigning a variable here:
public static string input = Convert.ToString(Console.ReadLine());
So the next time you call your "Main" method it will use the value you typed in the first time your app executed. If you want it to ask each time you'll need to do something like this:
public static void Main()
{
input = Convert.ToString(Console.ReadLine());
...
}
Another thing is that it can exit after the first call if you type in i.e. "status".
Issue number 3 is that this is not the "nice" way to write a program. The Main method is supposed to be executed when your app starts as it is the entry point (more on that here).
Related
I have trouble figuring out a bug. My game initializes several queues to store the game prompts and, in the "Start" button, the function StartDialogue() fills each of the queues and goes to DisplayNext(). The DisplayNext() function is supposed to dequeue the first prompt from certain queues and put them into the dialogue boxes. Afterwards, the player selects the correct button to answer and it calls DisplayNext() to advance to the next prompt.
However, my problem is that my sen_queue count is setting itself to 0 when the correct button calls DisplayNext(). The debug output first displays 4 when "Start" is pressed, but when the correct button is pressed, it displays 0. With the first correct button press, it goes to the EndDialogue() function. I have attached my code below. I have no clue how to fix this so any help would be greatly appreciated! Thank you so much in advance!
However, my problem is that my sen_queue count is setting itself to 0 when the correct button calls DisplayNext(). The debug output first displays 4 when "Start" is pressed, but when the correct button is pressed it displays 0. With the first correct button press it goes to the EndDialogue() function. I have attached my code below. I have no clue how to fix this, so any help would be greatly appreciated! Thank you so much in advance!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class QuestionManager : MonoBehaviour
{
public Text dialogueText;
public Text topText;
public Text botText;
public Queue<string> sen_queue;
public Queue<string> top_queue;
public Queue<string> bot_queue;
public Queue<string> wrong_queue;
private bool prev_wrong;
public GameObject finalsaltwater;
public GameObject water;
public GameObject sand;
public GameObject salt;
public GameObject filtersand;
public GameObject platewater;
void Start()
{
Screen.SetResolution(1600, 900, true);
sen_queue = new Queue<string>();
top_queue = new Queue<string>();
bot_queue = new Queue<string>();
wrong_queue = new Queue<string>();
prev_wrong = false;
finalsaltwater.SetActive(false);
filtersand.SetActive(false);
platewater.SetActive(false);
}
public void StartDialogue(Question question, Question topprompt, Question botprompt, Question wrong)
{
sen_queue.Clear();
top_queue.Clear();
bot_queue.Clear();
wrong_queue.Clear();
foreach (string sentence in question.sentences)
{
sen_queue.Enqueue(sentence);
}
foreach (string sentence in topprompt.sentences)
{
top_queue.Enqueue(sentence);
}
foreach (string sentence in botprompt.sentences)
{
bot_queue.Enqueue(sentence);
}
foreach (string sentence in wrong.sentences)
{
wrong_queue.Enqueue(sentence);
}
DisplayNext();
}
IEnumerator ToggleFalse(GameObject thing)
{
yield return new WaitForSeconds(1.5f);
thing.SetActive(false);
}
IEnumerator ToggleTrue(GameObject thing)
{
yield return new WaitForSeconds(1.5f);
thing.SetActive(true);
}
public void DisplayNext()
{
Debug.Log("IN DISPLAY " + sen_queue.Count);
if (sen_queue.Count == 0)
{
EndDialogue();
return;
}
if (top_queue.Count == 2)
{
platewater.SetActive(true);
water.SetActive(false);
StartCoroutine(ToggleFalse(salt));
} else if (top_queue.Count == 1)
{
filtersand.SetActive(true);
sand.SetActive(false);
platewater.SetActive(false);
StartCoroutine(ToggleTrue(finalsaltwater));
} else if (top_queue.Count == 0)
{
platewater.SetActive(true);
StartCoroutine(ToggleTrue(salt));
StartCoroutine(ToggleFalse(platewater));
finalsaltwater.SetActive(false);
}
string sentence = sen_queue.Dequeue();
if (top_queue.Count != 0)
{
string topbutton = top_queue.Dequeue();
topText.text = topbutton;
}
if (bot_queue.Count != 0)
{
string botbutton = bot_queue.Dequeue();
botText.text = botbutton;
}
prev_wrong = false;
dialogueText.text = sentence;
}
public void IncorrectDisplay()
{
if (wrong_queue.Count == 0)
{
return;
}
if (prev_wrong == false)
{
string wrong_sen = wrong_queue.Dequeue();
dialogueText.text = wrong_sen;
}
prev_wrong = true;
}
public void EndDialogue()
{
dialogueText.text = "Good job! Refresh the page if you want to restart.";
return;
}
}
I'm somewhat late, but I had the same issue. And even if you've already solved the problem, maybe I can help some other people in the future!
It has something to do with the calling order. In my code I had 2 Start() methods in 2 different classes.
In the class DialogueTrigger:
public Dialogue dialogue;
public void Start()
{
triggerDialogue();
}
public void triggerDialogue()
{
FindObjectOfType<DialogueManager>().startDialogue(dialogue);
}
And in the class DialogueManager:
public Queue<string> sentences;
private bool dialogueStarted;
// Start is called before the first frame update
void Start()
{
sentences = new Queue<string>();
}
private void Update()
{
if(dialogueStarted && Input.GetKeyDown(GameObject.Find("Player").GetComponent<Controls>().confirm))
{
displayNextSentence();
}
}
public void startDialogue(Dialogue dialogue)
{
print("start:" + dialogue.name);
sentences.Clear();
foreach (string s in dialogue.sentences)
{
sentences.Enqueue(s);
}
displayNextSentence();
dialogueStarted = true;
}
public void displayNextSentence()
{
if (sentences.Count == 0)
{
endDialogue();
return;
}
string sentence = sentences.Dequeue();
Debug.Log(sentence);
}
private void endDialogue()
{
Debug.Log("End of dialogue");
dialogueStarted = false;
}
Instead of clicking a button I let the next string come in when pressing a key (spacebar), but it should work the same.
The problem was that the Start() of DialogueManager got called after the startDialogue()-method (which gets called in the Start() of DialogueTrigger), gets called second. This resets the whole queue, makes it empty and thus sets the length to 0. This means the press of the key doesn't reset the queue, but it happens automatically!
In your code for some reason the Start() method gets called after the button press.
The solution to is to put the following code at the top of your StartDialogue()-method:
if (sentences == null)
{
sentences = new Queue<string>();
}
You could probably also leave the if-statement out and then use this code instead of the Clear()-methods. I haven't tested this, but the result should be the same. If you want to use Clear(), it would be better to use the if-statement. If you still leave it in you would reset the queue twice, which would be unnecessary.
This question already has answers here:
how to call non static method in window console application
(5 answers)
Closed 4 years ago.
I just started c#, thank you all for your patience. I am following a course on udemy and i dont understand why my method is not launching.
Here is my code:
public class Program
{
public void Exercise1()
{
Console.Write("Enter a number between 1 to 10: ");
var input = Console.ReadLine();
var number = Convert.ToInt32(input);
if (number >= 1 && number <= 10)
Console.WriteLine("Valid");
else
Console.WriteLine("Invalid");
}
static void Main(string[] args)
{
Exercise1(); // my method is not appearing in intelisense, what am i doing wrong?
}
}
Just mark the method as static:
public class Program
{
public static void Exercise1()
{
Console.Write("Enter a number between 1 to 10: ");
var input = Console.ReadLine();
var number = Convert.ToInt32(input);
if (number >= 1 && number <= 10)
Console.WriteLine("Valid");
else
Console.WriteLine("Invalid");
}
static void Main(string[] args)
{
Exercise1();
}
}
The problem is that Main is static, meaning it doesn't need an instance of Program to run. If you want Main to call other methods in Program, those methods also need to be static.
The only other way to do it would be this:
public class Program
{
public void Exercise1()
{
Console.Write("Enter a number between 1 to 10: ");
var input = Console.ReadLine();
var number = Convert.ToInt32(input);
if (number >= 1 && number <= 10)
Console.WriteLine("Valid");
else
Console.WriteLine("Invalid");
}
static void Main(string[] args)
{
var prog = new Program();
prog.Exercise1();
}
}
I am trying to 'share' variables between methods in C#. I am quite new to C#, I know there's no such thing as a 'global variable' and I'm not quite sure how to correctly use static variables.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectOne
{
static bool tooHigh;
static internal waistMeasurment;
class Main
{
static void Main(string[] args)
{
GetVariables();
}
public static void GetVariables() //This method gets the users height & waist measurments
//and calls the 'ValidateWaist' and 'ValidateHeight' methods for validation
{
Console.Write("What is your waist measurment? "); //This prints a string prompting the user to input their waist measurment
waistMeasurment = Console.ReadLine(); //This writes the users input under the string 'waistMeasurment'
ValidateWaist();
if tooHigh ==true
{
waistMeasurment = Console.ReadLine();
ValidateWaist();
}
}
public static void ValidateWaist() //This method validates the user input so that it fits within the minimum bound
{
if (waistMeasurment < 60) //Checks the lower bound of the waist limit
{
Console.Write("Your waist measurment must be above 59cm? "); //Output error feedback
tooHigh = true;
}
else
{
tooHigh = false;
}
}
}
}
Im having issues with the tooHigh and waistMeasurment
C# is an Object-Oriented Programming Language, which means it consists of namespaces, that hold classesand structs, which hold fields and properties (so, variables) and methods.
You're absolutely right, there are no global variables in C#. Although, you could hack together a class with a static variable and use it as a global, it's best to keep all the variables local and under control.
What you want to achieve, is to place the two variables (tooHigh and waistMeasurment) within the static Main class as static variables.
You also don't use if statements in the style of Python and internal was invented for methods, not variables. According to your code, you are looking for the type of integer, since later on, you are checking whether the variable waistMeasurment is less than 60. In order to do this, you first have to cast the variable to an integer. The proper way to this, is with the int.TryParse method.
namespace ProjectOne
{
class Main
{
static bool tooHigh;
static int waistMeasurment;
static void Main(string[] args)
{
GetVariables();
}
public static void GetVariables() //This method gets the users height & waist measurments
//and calls the 'ValidateWaist' and 'ValidateHeight' methods for validation
{
Console.Write("What is your waist measurment? "); //This prints a string prompting the user to input their waist measurment
int.TryParse(Console.ReadLine(), out waistMeasurment); //This writes the users input under the string 'waistMeasurment'
ValidateWaist();
if (tooHigh)
{
int.TryParse(Console.ReadLine(), out waistMeasurment);
ValidateWaist();
}
}
public static void ValidateWaist() //This method validates the user input so that it fits within the minimum bound
{
if ((int)waistMeasurment < 60) //Checks the lower bound of the waist limit
{
Console.Write("Your waist measurment must be above 59cm? "); //Output error feedback
tooHigh = true;
}
else
{
tooHigh = false;
}
}
}
}
Static can be used to share variable but need to be declared inside Class, there were some more errors in your program, I have modified your program you can use it and debug it for learning
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static bool tooHigh;
static int waistMeasurment;
static void Main(string[] args)
{
GetVariables();
}
public static void GetVariables() //This method gets the users height & waist measurments
//and calls the 'ValidateWaist' and 'ValidateHeight' methods for validation
{
Console.Write("What is your waist measurment? "); //This prints a string prompting the user to input their waist measurment
int.TryParse(Console.ReadLine(), out waistMeasurment); //This writes the users input under the string 'waistMeasurment'
ValidateWaist();
if (tooHigh == true)
{
int.TryParse(Console.ReadLine(), out waistMeasurment); ;
ValidateWaist();
}
}
public static void ValidateWaist() //This method validates the user input so that it fits within the minimum bound
{
if (waistMeasurment < 60) //Checks the lower bound of the waist limit
{
Console.Write("Your waist measurment must be above 59cm? "); //Output error feedback
tooHigh = true;
}
else
{
tooHigh = false;
}
}
}
}
As stated in the comments you have to change your code in order to place the variables inside a Type:
What you've got:
namespace ProjectOne
{
static bool tooHigh;
static internal waistMeasurment;
class Main
{
//your code
}
}
What you have to write:
namespace ProjectOne
{
class Main
{
static bool tooHigh;
static internal waistMeasurment;
//your code again
}
}
I am writing a simple program in c# which asks the user to enter a number, then tells the user if the number is odd or even. my program works however wheni first enter the number nothing happens, i have to enter the number twice and then it tells me if the number is odd or even, im not very good at using the mvvc technique, so if anyone knows why this is happening and could help me that would be great.my code is below...
class CheckNumber
{
protected String number;
public void SetNumber(String newNumber)
{
number = newNumber;
}
public int Number()
{
int number = Convert.ToInt32(Console.ReadLine());
if (number % 2 == 1) //(number % 2 == 0) would test for even numbers(0 remainder)
{
Console.WriteLine("Odd number");
}
else
{
Console.WriteLine("Even number");
}
return number;
}
}
class CheckNumberController
{
IView view;
CheckNumber checkNumber;
public CheckNumberController(IView theView, CheckNumber theCheckMark)
{
view = theView;
checkNumber = theCheckMark;
}
public void Go()
{
view.Start();
checkNumber.SetNumber(view.GetString("Please enter a number"));
view.Show(checkNumber.Number());
view.Stop();
}
}
class ConsoleView : IView
{
public void Start()
{
Console.Clear();
}
public void Stop()
{
Console.WriteLine("Press any key to finish");
Console.ReadKey();
}
public String GetString(String prompt = "")
{
Console.WriteLine(prompt);
return Console.ReadLine();
}
public Int32 GetInt(String prompt = "")
{
Console.WriteLine(prompt);
return Int32.Parse(Console.ReadLine());
}
public void Show<T>(T message)
{
Console.WriteLine(message);
}
}
interface IView
{
void Start();
void Stop();
String GetString(String prompt);
Int32 GetInt(String prompt);
void Show<T>(T message);
}
class Program
{
static void Main(string[] args)
{
new CheckNumberController(new ConsoleView(), new CheckNumber()).Go();
}
}
You're reading input twice. Firstly in the CheckNumberController.Go()
checkNumber.SetNumber(view.GetString("Please enter a number"));
And secondly in CheckNumber.Number()
int number = Convert.ToInt32(Console.ReadLine());
The latter should be:
int number = Convert.ToInt32(this.number);
As you want to work on the value you've already read and set, not an additional one
public String GetString(String prompt = "")
{
Console.WriteLine(prompt);
//return Console.ReadLine();
return "error is here";
}
When calling GetString() method your again trying to get an input. Just comment and return string if you want.
The key is in this method:
public void Go()
{
view.Start();
checkNumber.SetNumber(view.GetString("Please enter a number"));
view.Show(checkNumber.Number());
view.Stop();
}
SetNumber(string) sets the protected field number in the CheckNumber class. However, when you call view.Show<T>(T), you are calling the Number() method on the CheckNumber class, which ignores the stored variable and reads from the console again.
I'm learning C# and i'm having problems with variable scope in my simple console program.
The program runs perfectly so far except I know I will encounter issues when trying to reference variables previously instantiated.
I have tried to change methods from static to non static and also applied public/private access but to no avail.
I just need a nudge in the right direction, hope someone can help!
The error message i'm getting is :
Error 1 An object reference is required for the non-static field, method, or property 'ConsoleApplication2.Program.game()'
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
public class Program
{
int numberToGuess;
int numberGuessed;
int triesRemaining;
public void game()
{
Console.WriteLine(" ==Welcome to Guess My Number== \n");
Console.WriteLine("Player 1: Please enter your number to guess between 1 and 20: \n");
numberToGuess = int.Parse(Console.ReadLine());
Console.WriteLine("Player 2, please enter your first guess, you have 7 tries: \n");
numberGuessed = int.Parse(Console.ReadLine());
if (numberGuessed == numberToGuess)
{
correct();
}
else
{
incorrect();
}
}
public void correct()
{
Console.WriteLine("Congratulations, the number was in fact " + numberToGuess);
}
public void incorrect()
{
}
static void Main(string[] args)
{
game();
}
}
}
instance members (those not marked with the static keyword) exist once per object instance. Every instance of an object gets its own copies of them.
static members, on the other hand, exist once for the entire class and are shared by all object instances.
So, If you've got a class:
class Foo
{
public static int Alpha { get ; set ; }
public int Bravo { get ; set ; }
}
No matter how many instances of your Foo class are created, there is only one instance of Alpha. Any instance method or property can access a static member directly.
Instance members, since they exist on a per-instance basic, require an object instance to reference them. If you add some methods to the Foo class:
public static int DoSomething()
{
return Alpha * 3 ;
}
is perfectly valid — the method is static and the member is static. Ditto for an instance method:
public int DoSomethingElse()
{
return Alpha * 3 ;
}
Something like this will fail:
public static int AndNowForSomethingCompletelyDifferent()
{
return Alpha * 3 + Bravo ;
}
Bravo can't be referenced here without a reference to an instance of Foo. This will work however:
public static int AndNowForSomethingCompletelyDifferent( Foo instance )
{
return Alpha * 3 + instance.Bravo ;
}
As will this:
public int AndNowForSomethingCompletelyDifferent()
{
return Alpha * 3 + Bravo ;
}
Since the method is non-static (an instance method), it has an implicit reference (this) to its instance of Foo. The above is exactly equivalent to
public int AndNowForSomethingCompletelyDifferent()
{
return Alpha * 3 + this.Bravo ;
}
In your case, you could instantiate the class Program in your Main() method:
public static void Main( string[] args )
{
Program p = new Program() ;
p.game() ;
return ;
}
Or you could mark your methods game(), correct() and incorrect() as static, just as the Main() method is marked.
Hope this helps!
static methods/fields belong to the user-defined type, not the instance.
For example, if you look at this piece of code:
public class MyClass
{
public static void Foo()
{
}
}
the Foo() method, is not accessed from an instance of MyClass. Since it is static, you access it from the user-defined type itself. Ex:
public class Program
{
static void Main(String[] args)
{
MyClass.Foo();
}
}
Since Main() is static, you can only reference static methods or variables inside it (this excludes methods referenced from local instance variables).
In your code, the method game() and the fields/methods being called/invoked by game are not static, therefore you would only be able to access it via an object instance. Of course, making game() and all the other fields/methods static would result in a working piece of code.
For more information on static types, look here: http://msdn.microsoft.com/en-us/library/98f28cdx.aspx
I have gone on to complete the methods and it seems to be working great!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
public class Program
{
int numberToGuess;
int numberGuessed;
int triesRemaining = 7;
string playAgain;
string player1, player2;
public void game() //Initiates the game instance
{
Console.WriteLine(" ==Welcome to Guess My Number== \n");
Console.WriteLine(" Player 1, Please enter your name: \n");
player1 = Console.ReadLine();
Console.Clear();
Console.WriteLine(" ==Guess My Number== \n");
Console.WriteLine("Hello " + player1 + " : Please enter your number to guess between 1 and 20: \n");
numberToGuess = int.Parse(Console.ReadLine());
Console.Clear();
Console.WriteLine(" ==Guess My Number== \n");
Console.WriteLine(" Player 2, Please enter your name: \n");
player2 = Console.ReadLine();
Console.Clear();
Console.WriteLine("Hello " + player2 + " please enter your first guess, you have 7 tries: \n");
numberGuessed = int.Parse(Console.ReadLine());
if (numberGuessed == numberToGuess)
{
Console.WriteLine("Congratulations, the number was in fact " + numberToGuess);
newGame();
}
else
{
incorrect();
}
}
public void incorrect() //Method for dealing with incorrect answers
{
for (int x = 0; x < 6; x++)
{
triesRemaining--;
Console.WriteLine("Incorrect, you have " + triesRemaining + " tries remaining \n");
Console.WriteLine(player2 + ", please enter your next guess: \n");
numberGuessed = int.Parse(Console.ReadLine());
if (numberGuessed == numberToGuess)
{
Console.WriteLine("Congratulations, the number was in fact " + numberToGuess);
newGame();
}
else {
//Do nothing
}
}
Console.WriteLine("You have used up all your tries! You have failed. The number was: " +numberToGuess + "\n");
newGame();
} //Method for dealing with incorrect answers
public void newGame() //Method that gives the user the option to start a new game instance
{
Console.WriteLine("Would you like to play again? Type yes or no: \n");
playAgain = Console.ReadLine();
playAgain = playAgain.ToLower();
if (playAgain == "yes")
{
Console.Clear();
game();
}
else if (playAgain == "y")
{
game();
}
else
{
//Do nothing
}
}
static void Main(string[] args)
{
new Program().game();
}
}
}