So in this code block from my console application, when ran, should move the 'X' in Class02 up and down when you hit the respective arrow keys but it doesn't, it just stays in place:
class Program
{
static void Main(string[] args)
{
Class01.Function01();
}
}
class Class01
{
public int num01 = 5;
public int num02 = 5;
public static void Function01()
{
while (true)
{
Class02.Function02();
}
}
}
class Class02
{
public static void Function02()
{
var c1 = new Class01();
Console.SetCursorPosition(c1.num02, c1.num01);
Console.Write("X");
ConsoleKeyInfo keyInfo;
keyInfo = Console.ReadKey(true);
switch (keyInfo.Key)
{
case ConsoleKey.UpArrow:
c1.num01--;
break;
case ConsoleKey.DownArrow:
c1.num01++;
break;
}
}
}
I know what's wrong here, the int in Class01 is not being changed in class02. therefore the Cursor Position is still set as 5 5 writing the 'X' in the same place every key stroke.
So, how does one change the value of int num01 in Class02?
Thanks for any help with this.
You are always creating a new instance of Class01 in the static method Class02.Function02, therefore the value is always it's default value 5. You could make the numbers static too or you could hold a static instance variable of Class01 in Class02, for example:
class Class02
{
private Class01 c1 = New Class01();
public static void Function02()
{
Console.SetCursorPosition(c1.num02, c1.num01);
Console.Write("X");
ConsoleKeyInfo keyInfo;
keyInfo = Console.ReadKey(true);
switch (keyInfo.Key)
{
case ConsoleKey.UpArrow:
c1.num01--;
break;
case ConsoleKey.DownArrow:
c1.num01++;
break;
}
}
}
another option is to pass the instance of Class01 to the method:
public static void Function02(Class01 c1)
{
Console.SetCursorPosition(c1.num02, c1.num01);
Console.Write("X");
ConsoleKeyInfo keyInfo;
keyInfo = Console.ReadKey(true);
switch (keyInfo.Key)
{
case ConsoleKey.UpArrow:
c1.num01--;
break;
case ConsoleKey.DownArrow:
c1.num01++;
break;
}
}
then you call it in this way:
Class01 c1 = new Class01();
while (true)
{
Class02.Function02(c1);
}
If the calling method Function01 would not be static you could pass this.
The error is, that in every single call you create a new instance of class01 with the initial values in it.
Related
I am displaying menu in the console based application using C#. I want that if user press enter key then it should display same menu. Application should not break. I am new to C#
If anyone has idea please share it. It will be helpful to me.
Below is the code.
public static void HospitalMenu()
{
string answer = "";
do
{
Console.Clear();
Console.WriteLine("=============Hospital Management System===================");
Console.WriteLine("1...............Add Patient Information");
Console.WriteLine("2...............Modify Patient Information");
Console.WriteLine("3...............Add Patient Treatment Information");
Console.WriteLine("4...............View Patient History");
Console.WriteLine("5...............Search Patient Info");
Console.WriteLine("6...............Generate Lab Report");
Console.WriteLine("7...............Generate Medical Bills");
Console.WriteLine("8...............Exit");
Console.WriteLine("Select option (between 1 to 8)");
int option = Convert.ToInt32(Console.ReadLine());
switch (option)
{
case 1:
Patient.InsertPatient();
break;
case 2:
Patient.UpdatePatient();
break;
case 3:
PatientTreatment();
break;
case 4:
ViewMenu();
break;
case 5:
SearchMenu();
break;
case 6:
LabMenu();
break;
case 7:
BillMenu();
break;
default:
Environment.Exit(0);
break;
}
Console.WriteLine("Do you want to continue ? (Enter y if yes)");
answer = Console.ReadLine();
} while (answer == "y" || answer == "Y");
}
Thanks in advance.
I'll suggest some changes in your code.
Let's create an Interface that you'll be a contract responsible to show and handle inputs
IMenuHandler.cs
public interface IMenuHandler<TInput>
{
void Show( Action stopApplicationHandler, IMenuHandler<TInput> callerMenu=null);
void HandleInput(TInput input, Action stopApplication, IMenuHandler<TInput> callerMenu);
}
Then let's create your menus.. .
As an example you'll create two, you should modify it for your needs.
MainMenu.cs
public class MainMenu:IMenuHandler<ConsoleKeyInfo>
{
public void Show(Action stopApplicationHandler, IMenuHandler<ConsoleKeyInfo> callerMenu = null)
{
Console.Clear();
Console.WriteLine("=============Hospital Management System===================");
Console.WriteLine("1...............Add Patient Information");
Console.WriteLine("2...............Modify Patient Information");
Console.WriteLine("3...............Add Patient Treatment Information");
Console.WriteLine("4...............View Patient History");
Console.WriteLine("5...............Search Patient Info");
Console.WriteLine("6...............Generate Lab Report");
Console.WriteLine("7...............Generate Medical Bills");
Console.WriteLine("8...............Exit");
Console.WriteLine("Select option (between 1 to 8)");
HandleInput(Console.ReadKey(), stopApplicationHandler, callerMenu ?? this);
}
public void HandleInput(ConsoleKeyInfo input, Action stopApplication, IMenuHandler<ConsoleKeyInfo> callerMenu)
{
switch (input.Key)
{
case ConsoleKey.D1:
new HelpMenu().Show(stopApplication, callerMenu);
break;
case ConsoleKey.D8:
stopApplication.Invoke();
break;
default:
Show(stopApplication, this);
break;
}
}
}
HelpMenu.cs
public class HelpMenu:IMenuHandler<ConsoleKeyInfo>
{
public void Show(Action stopApplicationHandler, IMenuHandler<ConsoleKeyInfo> callerMenu = null)
{
Console.Clear();
Console.WriteLine("Help Menu Example...");
Console.WriteLine("1...............Go back");
Console.WriteLine("2...............Exit");
HandleInput(Console.ReadKey(), stopApplicationHandler, callerMenu );
}
public void HandleInput(ConsoleKeyInfo input, Action stopApplication, IMenuHandler<ConsoleKeyInfo> callerMenu)
{
Console.WriteLine("Help menu handler...");
switch (input.Key)
{
case ConsoleKey.D1:
callerMenu.Show(stopApplication, this);
break;
case ConsoleKey.D2:
stopApplication.Invoke();
break;
default:
Show(stopApplication, callerMenu);
break;
}
}
}
Now we are going to create an wrapper for your application.
Application.cs
public class Application
{
public delegate void OnStopApplicationRequestHandler();
public event OnStopApplicationRequestHandler StopApplicationRequest;
private readonly CancellationTokenSource _cancellationTokenSource;
public Application(CancellationToken? cancellationToken=null, OnStopApplicationRequestHandler? stopApplicationRequestHandler=null)
{
_cancellationTokenSource = cancellationToken != null
? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken.Value)
: new CancellationTokenSource();
StopApplicationRequest += stopApplicationRequestHandler ?? ConfigureDefaultStopApplicationRequestHandler();
}
private OnStopApplicationRequestHandler ConfigureDefaultStopApplicationRequestHandler()
=> () =>
{
Console.WriteLine("Stopping application...");
_cancellationTokenSource.Cancel();
};
public void Run()
{
try
{
while (!_cancellationTokenSource.Token.IsCancellationRequested)
new MainMenu().Show(Stop);
Console.WriteLine("Program has been stopped");
}
//.... You should handle other custom exceptions here
catch (Exception ex)
{
// I'll assume that you will stop your application case it hits this unhandled exception
Console.WriteLine(ex);
Stop();
}
}
private void Stop()
{
StopApplicationRequest?.Invoke();
}
}
Note that this class has an event that will be responsible to handle the application exits.
You should modify it for your needs.
Last but not least
Call your application wrapper in your Program.cs
internal class Program
{
static void Main(string[] args)
{
new Application().Run();
}
}
PS: Don't forget the correct usings....
Hope this helps
i am a C# beginner, so for now most of my code is inside the Main() method. I want to make my Program more object oriented so I want to move code from Main method to another class reliably(so i can do it with other programs as well).
static void Main()
{
int xLentgh = 20;
int yLength = 20;
Map.MapBuilder(xLentgh,yLength);
int oldPositionX = 0;
int oldPositionY = 0;
int newPositionX = 0;
int newPositionY = 0;
if (oldPositionX == 0)
{
Map.WriteAt(".",newPositionX, newPositionY);
}
for (int i = 0; i < 100; i++)
{
ConsoleKeyInfo KeyStroke;
KeyStroke = Console.ReadKey();
switch (KeyStroke.Key)
{
case ConsoleKey.RightArrow:
{
if (newPositionX < xLentgh-1)
{
oldPositionX = newPositionX;
oldPositionY = newPositionY;
newPositionX++;
}
break;
}
case ConsoleKey.LeftArrow:
{
if (newPositionX > 0)
{
oldPositionX = newPositionX;
oldPositionY = newPositionY;
newPositionX--;
}
break;
}
case ConsoleKey.UpArrow:
{
if (newPositionY > 0)
{
oldPositionX = newPositionX;
oldPositionY = newPositionY;
newPositionY--;
}
break;
}
case ConsoleKey.DownArrow:
{
if (newPositionY < yLength-1)
{
oldPositionX = newPositionX;
oldPositionY = newPositionY;
newPositionY++;
}
break;
}
default: break;
}
Map.WriteAt(".",newPositionX, newPositionY);
Map.WriteAt(" ",oldPositionX, oldPositionY);
}
}
In this code I create a "map" and using the switch statement in the for loop to "track" the position of the cursor. How do I write this code in a new class? I dont know where to start
You can try to create a class named as you want (we will call it RandomNameClass) by declaring it outside of the bloc class Program {}.
You should have something like this :
namespace NameYouGaveToProject
{
class RandomNameClass
{
}
class Program
{
static void Main(string[] args)
{
// Your actual code here
}
}
}
Above or under is fine but prefer having the class Program at the bottom if you write all your code in one file.
There you have your first custom class! Now try to add some functions in it. If you haven't learn about instantiating a class yet, just don't forget to add public static before the returning type of your function.
Example of what you could have :
namespace NameYouGaveToProject
{
class RandomNameClass
{
// Function that doesn't return anything, returns "void"
public static void SayHi()
{
Console.WriteLine("Hi!");
}
// Function that returns a string
public static string ReturnHi()
{
return "Hi!";
}
}
class Program
{
static void Main(string[] args)
{
// Your actual code here
}
}
}
And then you can call them by typing the name of the class, followed by a point and then the name of the function and "()" if there are no parameters to this function (there aren't in my example).
The syntax would be :
// Call the void function
RandomNameClass.SayHi();
// Call the function returning a string
string testVariable = RandomNameClass.ReturnHi();
Note that you can call as often as you want every function
And voilĂ ! You know the basics of creating a class and call functions from this class! Next thing you should learn is how to make functions properly, and then instantiating a class and manage it's content
I'm writing a simple text adventure, and would like to have a main menu, which can be accessed at any time, while any other method is running just by typing "menu" in the console
Here's some code that I wrote (sorry, if it's not very good, I'm only starting to learn), but in this example the menu can be accessed only once at the beginning, while I'd like it to run anytime i type "menu", no matter which part of the program is currently running
So, is there any simple and efficient way to check for certain input ("menu" in this case) without copy pasting menu call method everywhere?
Any help would be appreciated, thank you in advance
(This is my previous attempt, which doesn't work, my new approach is in UPDATE1)
class Program
{
static int menuSwitch = 0;
static void Main(string[] args)
{
Console.WriteLine("Welcome to the test program");
string menu = "menu";
string trymenu = Console.ReadLine();
do
{
Console.WriteLine("Main menu");
Console.WriteLine("1.Entry1 \n2.Entry2");
Int32.TryParse(Console.ReadLine(), out menuSwitch);
switch (menuSwitch)
{
case 1:
Console.WriteLine("Entry1");
break;
case 2:
Console.WriteLine("Entry2");
break;
default:
Console.WriteLine("Exiting menu");
break;
}
break;
} while (trymenu == menu);
{
Start();
Continue();
End();
}
}
}
UPDATE1
So, I've done some tinkering and managed to get it working as intended, keeping in mind Alejandro's advice, however as I expected, now I have to call the Menu method after every step (console messages in this case) of another (Start) method
I've been wondering if there is any workaround for this, or any other efficient method to check if there is a "menu" input, as it seems kind of excessive and tedious to work with the way it is now
class Program
{
static void Main(string[] args)
{
Start();
}
static void Menu()
{
int menuSwitch = 0;
string menu = "menu";
string trymenu = Console.ReadLine();
if (trymenu == menu)
{
Console.WriteLine("Main menu");
Console.WriteLine("1.Entry1 \n2.Entry2");
Int32.TryParse(Console.ReadLine(), out menuSwitch);
switch (menuSwitch)
{
case 1:
Console.WriteLine("Entry1");
break;
case 2:
Console.WriteLine("Entry2");
break;
default:
Console.WriteLine("Exiting menu");
break;
}
}
}
static void Start()
{
Console.WriteLine("Welcome to the test program");
Menu();
Console.WriteLine("Type 'menu' to access the main menu");
Menu();
Console.WriteLine("Message1");
Menu();
Console.WriteLine("Message2");
Menu();
Console.WriteLine("Message3");
Menu();
}
}
The simplest way would probably be to move the common code to a method. You might however want to model your game as a state machine.
This allows you to separate most of the content from the game logic. This is very useful since it allows you to store the content in some file that can be loaded by the game engine. A very simple state could look something like this:
public interface IState
{
string Description { get; }
IEnumerable<ITransition> Transitions { get; }
void OnActivated(IState from);
}
public interface ITransition
{
string Command { get; }
IState TargetState { get; }
}
In this model commands are modeled as transitions between states. There are several ways to have transitions that are global:
Make a base class that contains global transitions that all states should have
Add the global states explicitly when creating each state (probably with some helper method)
Built the global transitions directly into the main game loop
An example of the last alternative could be something like this:
public class Game
{
private readonly IState initialState;
private readonly IEnumerable<ITransition> globalCommands;
private readonly IState exitState;
public Game(IState initialState, IEnumerable<ITransition> globalCommands, IState exitState)
{
this.initialState = initialState;
this.globalCommands = globalCommands;
this.exitState = exitState;
}
private IEnumerable<ITransition> GetTransitions(IState state) => state.Transitions.Concat(globalCommands);
public void Loop()
{
var currentState = initialState;
while (currentState != exitState)
{
Console.WriteLine(currentState.Description);
var transitions = GetTransitions(currentState).ToList();
foreach (var transition in transitions)
{
Console.WriteLine(transition.Command);
}
ITransition nextTransition;
do
{
var command = Console.ReadLine();
nextTransition = transitions.FirstOrDefault(t => t.Command.Equals(command));
} while (nextTransition == null);
nextTransition.TargetState.OnActivated(currentState);
currentState = nextTransition.TargetState;
}
}
}
One complexity with this is that you probably want to return to whatever state you left when you exit the menu. One way to do this could be to save the state you entered the menu from in a "exit" transition:
public class MenuState : IState
{
public string Description { get; }
IEnumerable<ITransition> IState.Transitions => Transitions.Concat(new[] {exit});
public List<ITransition> Transitions { get; } = new List<ITransition>();
private Transition exit;
public virtual void OnActivated(IState from) => exit = new Transition("exit", from);
public MenuState(string description) => Description = description;
}
I would like to access list (in my program named "section") inside a method(menu choose). I tried 3 ways:
public static void dataBase()
{
List<float> section = new List<float>();
}
// 1st try
// List<float> section = new List<float>();
//
public static void mainMenu()
{
Console.Clear();
Console.WriteLine("Trans->Connector->\n");
Console.WriteLine("Add: \n1. Section \n2. Wled \n3. Regenerator");
menuChoose();
}
public static void menuChoose()
{
var key = Console.ReadKey();
switch (key.Key)
{
case ConsoleKey.D1:
case ConsoleKey.NumPad1:
Console.Clear();
Console.WriteLine("Give lenght:");
float result;
float.TryParse(Console.ReadLine(), out result);
dataBase.section.Add();
section.Add(result);
break;
case ConsoleKey.D2:
Console.WriteLine("2");
break;
case ConsoleKey.D3:
Console.WriteLine("3");
break;
default:
Console.WriteLine("default");
break;
}
}
static void Main(string[] args)
{
int WeldCount;
int ConnectroCount;
//3rd try
// List<float> section = new List<float>();
//
mainMenu();
}
Thank you for your time!
You can't access a member in the local scope of your function outside it. You might want to think about making it a private instance variable inside your class that you will then be able to access from any method declared that belongs to this class, something along these lines:
public class MyClass
{
// this field is accessible from any method declared within this class
private List<Float> section;
public MyClass()
{
section = new List<Float>();
}
private void someMethod()
{
section.Add(2.2);
Console.WriteLine(section[0]); // example
}
}
Well you can make it class level variable (like in your 1st try) and make it static.
However you should use return value from your menuChoose() method. Having all code depend on single static list instance is not ideal.
public static List<float> menuChoose()
{
List<float> selection = new List<float>();
var key = Console.ReadKey();
switch (key.Key)
{
case ConsoleKey.D1:
case ConsoleKey.NumPad1:
Console.Clear();
Console.WriteLine("Give lenght:");
float result;
float.TryParse(Console.ReadLine(), out result);
selection.Add(result);
break;
case ConsoleKey.D2:
Console.WriteLine("2");
break;
case ConsoleKey.D3:
Console.WriteLine("3");
break;
default:
Console.WriteLine("default");
break;
}
return selection;
}
You can to it, if you would implement something like this:
public static class DataBase
{
public static List<float> Section { get; set; }
static DataBase()
{
Section = new List<float>();
}
}
here how to use e.g. in your switch statement:
case ConsoleKey.NumPad1:
Console.Clear();
Console.WriteLine("Give lenght:");
float result;
float.TryParse(Console.ReadLine(), out result);
DataBase.Section.Add(result);
break;
I didn't get what you try to achieve by dataBase.section.Add(); so I removed it in my example.
I could not use any of your answers so I did this in my way(much worse than yours, for sure)
public class Program
{
public int WeldCount;
public int ConnectroCount;
public List<float> section = new List<float>();
//public List<> TrackElements = new List<>();
public Program()
{
section.Add(0);
}
public void showResults()
{
float allSections = 0;
foreach (float item in section)
{
allSections += item;
}
Console.Clear();
Console.WriteLine("c1 {0}, c2 {1}, c3{2}", WeldCount,ConnectroCount,allSections);
Console.ReadKey();
}
public void finalConstruction()
{
}
public static void mainMenu()
{
Console.Clear();
Console.WriteLine("\n");
Console.WriteLine("Add: \n1. Section \n2. Weld \n3. Regenerator\n4. Show results");
}
public void menuChoose()
{
var key = Console.ReadKey();
switch (key.Key)
{
case ConsoleKey.D1:
case ConsoleKey.NumPad1:
Console.Clear();
Console.WriteLine("Give lenght:");
float result;
float.TryParse(Console.ReadLine(), out result);
section.Add(result);
mainMenu();
menuChoose();
break;
case ConsoleKey.D2:
WeldCount++;
mainMenu();
menuChoose();
break;
case ConsoleKey.D3:
ConnectroCount++;
mainMenu();
menuChoose();
break;
case ConsoleKey.D4:
showResults();
mainMenu();
menuChoose();
break;
default:
Console.WriteLine("wtf did just happend");
break;
}
}
static void Main(string[] args)
{
Program program = new Program();
mainMenu();
program.menuChoose();
}
}
}
I want choice == 1 to only be able to be selected five times, so I initialized a variable firstClass = 0, then set up a do-while for firstClass < 5. I included firstClass++ in my do-while to act as a counter. However, I think firstClass is re-initializing every time I call the method CheckIn(). How can I prevent this from happening? Thanks in advance.
using System;
namespace Assignment7
{
class Plane
{
public static void Main(string[] args)
{
Console.WriteLine("Welcome to the Airline Reservation System.");
Console.WriteLine("Where would you like to sit?\n");
Console.WriteLine("Enter 1 for First Class.");
Console.WriteLine("Enter 2 for Economy.");
CheckIn();
}
public static void CheckIn()
{
int choice = Convert.ToInt32(Console.ReadLine());
int firstClass = 0;
int economy = 0;
if (choice == 1)
{
do
{
Console.WriteLine("You have chosen a First Class seat.");
firstClass++;
CheckIn();
} while (firstClass < 5);
}
else if (choice == 2)
{
do
{
Console.WriteLine("You have chosen an Economy seat.");
economy++;
CheckIn();
} while (economy < 5);
}
else
{
Console.WriteLine("That does not compute.");
CheckIn();
}
}
}
}
That is entirely normal. If you want the variable to exist outside the method, you must declare it outside a method, as a "field". Simply move the:
int firstClass = 0;
outside the method, adding the static modifier (in this case):
static int firstClass = 0;
Note also that this by itself is not thread-safe; if threading is an issue (for example, ASP.NET) then use int newValue = Interlocked.Increment(ref firstClass);. I only mention this because in the general case static data should consider threading, but I suspect it isn't an issue in your case (a console exe).
The firstClass variable is method scoped. Every time the method is called the variable is reinitialized. To have firstClass become an ongoing counter it needs to be outside the method, within the class.
You need to take any exit condition out of your method and put it outside, either by making a new method or putting it in the one that's calling it already.
For example you could do something like:
using System;
namespace Assignment7
{
class Plane
{
public static void Main(string[] args)
{
Console.WriteLine("Welcome to the Airline Reservation System.");
Console.WriteLine("Where would you like to sit?\n");
Console.WriteLine("Enter 1 for First Class.");
Console.WriteLine("Enter 2 for Economy.");
CheckIn(0, 0);
}
public static void CheckIn(int firstClassSeatsTaken, int economySeatsTaken)
{
int choice = Convert.ToInt32(Console.ReadLine());
if (choice == 1)
{
do
{
Console.WriteLine("You have chosen a First Class seat.");
firstClass++;
CheckIn(firstClassSeatsTaken, economySeatsTaken);
} while (firstClass < 5);
}
else if (choice == 2)
{
do
{
Console.WriteLine("You have chosen an Economy seat.");
economy++;
CheckIn(firstClassSeatsTaken, economySeatsTaken);
} while (economy < 5);
}
else
{
Console.WriteLine("That does not compute.");
CheckIn(firstClassSeatsTaken, economySeatsTaken);
}
}
}
}