I am having trouble display the object's properties and transferring them between classes. I am also having trouble getting the error message from the set methods. It seems I can enter anything without getting an error. I know the problem might have something in the object because I am just getting blank variable names when I try to display it.
namespace Project
{
class Program
{
static void Main(string[] args)
{
string name;
double strength = 0;
double dexterity = 0;
double hitPoints = 0;
double armor = 0;
Console.WriteLine("--WELCOME TO THE BATTLE--\n");
Console.WriteLine("Please enter the statistics for warrior one.");
Console.WriteLine("Name: ");
name = Console.ReadLine();
Console.WriteLine("Strength: ");
strength = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Dexterity: ");
dexterity = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Hit Points: ");
hitPoints = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Armor: ");
armor = Convert.ToDouble(Console.ReadLine());
Warrior warriorOne = new Warrior(name, strength, dexterity, hitPoints, armor);
Console.WriteLine("\nPlease enter the statistics for warrior two.");
Console.WriteLine("Name: ");
name = Console.ReadLine();
Console.WriteLine("Strength: ");
strength = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Dexterity: ");
dexterity = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Hit Points: ");
hitPoints = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Armor: ");
armor = Convert.ToDouble(Console.ReadLine());
Warrior warriorTwo = new Warrior(name, strength, dexterity, hitPoints, armor);
Console.WriteLine("\nWarriors:\n" + warriorOne.Name + "--" + "Strength " + warriorOne.Strength + ", Dexterity " + warriorOne.Dexterity + ", HitPoints " + warriorOne.HitPoints + ", Armor " + warriorOne.Armor);
Console.WriteLine("\nWarriors:\n" + warriorTwo.Name + "--" + "Strength " + warriorTwo.Strength + ", Dexterity " + warriorTwo.Dexterity + ", HitPoints " + warriorTwo.HitPoints + ", Armor " + warriorTwo.Armor);
Battlefield.Battle(warriorOne, warriorTwo);
}
}
class Warrior
{
private double strength;
private double dexterity;
private double hitPoints;
private double armor;
public Warrior(string name, double strength, double dexterity, double hitPoints, double armor)
{
name = Name;
this.strength = Strength;
this.dexterity = Dexterity;
this.hitPoints = HitPoints;
this.armor = Armor;
}
public string Name { get; set; }
public double Strength
{
get
{
return strength;
}
set
{
while (value < 10 & value > 20)
{
Console.WriteLine("Strength has a range of 10-20. Please re-enter: ");
value = Convert.ToDouble(Console.ReadLine());
}
strength = value;
}
}
public double Dexterity
{
get
{
return dexterity;
}
set
{
while (value < 10 & value > 20)
{
Console.WriteLine("Dexterity has a range of 10-20. Please re-enter: ");
value = Convert.ToDouble(Console.ReadLine());
}
dexterity = value;
}
}
public double HitPoints
{
get
{
return hitPoints;
}
set
{
while (value < 10 & value > 20)
{
Console.WriteLine("Hit points have a range of 10-20. Please re-enter: ");
value = Convert.ToDouble(Console.ReadLine());
}
hitPoints = value;
}
}
public double Armor
{
get
{
return armor;
}
set
{
while (value < 0 & value > 5)
{
Console.WriteLine("Armor has a range of 0-5. Please re-enter: ");
value = Convert.ToDouble(Console.ReadLine());
}
armor = value;
}
}
}
class Battlefield
{
public static void Battle(Warrior warriorOne, Warrior warriorTwo)
{ Console.WriteLine(warriorOne.Name); }
}
One problem is with your Warrior class, in the constructor where you try to set the Name property. You have this (I've only included the relevant bits):
public Warrior(string name)
{
name = Name;
}
public string Name { get; set; }
Notice that you're NOT setting the Name property here. You are setting the argument name to whatever the Name property is (which is probably null).
To fix this, just switch the order around the assignment:
public Warrior(string name)
{
Name = name;
}
You might want to check all your other properties as well (it looks like this was a common mistake, where you have the property you're trying to set on the right side of the = instead of the left).
Remember you should almost always assign to the public accessor (the capitalized one), so your set code runs. Try not to modify the private backing field except from the property set method.
Related
I am trying to print product details by creating a class Product and a method Display() in Product class to display product details.
I created an array of Product and trying to save products in array and trying to display the products from array by using Display Method.
User should provide choice whether he wants to ADD PRODUCT , DISPLAY PRODUCT or EXIT
based on choice need to perform action.
class Product
{
private static int m_intProductCounter = 0; // Initially Making Product Count = 0
public Product() // Constructor for class Product
{
m_intProductCounter++; // Whenever new object is created or Constructor is called Count Increases
}
public int ProductCount // Properity for Product Count
{
get { return m_intProductCounter; }
}
private int m_intProductid; // Product Id Variable
public int ProductId // properity for Product Id
{
get { return m_intProductid; }
set
{
if (value > 0)
m_intProductid = value;
else
throw new Exception("Invalid Product Id! Please Check Product Id.");
}
}
private string m_strProductName; // Product Name Variable
public string ProductName // Properity for Product Name
{
get { return m_strProductName; }
set
{
if (value.Length > 3)
m_strProductName = value;
else
throw new Exception("Invalid Product Name! Please Check Product Name.");
}
}
private DateTime m_dateManufacturedDate = DateTime.UtcNow; // Product Manufactured date variable
//private DateTime m_dateExpiryDate;
public DateTime ExpiryDate // Product Expiry Date Calculation
{
get { return m_dateManufacturedDate.AddYears(2); }
}
private int m_intProductQuantity; // Product Quantity variable
public int ProductQnty
{
get { return m_intProductQuantity; } // Properity for Product Quantity
set
{
if (value > 0 && value <= 500)
m_intProductQuantity = value;
else if (value < 0)
throw new Exception("Invalid Quantity! Product Quantity cannot be Less Than 0");
else
throw new Exception("Invalid Quantity! Product Quantity Cannot be more than 500.");
}
}
private decimal m_decProductPrice; // Product Price variable
public decimal ProductPrice // Properity for Product Price
{
get { return m_decProductPrice; }
set
{
if (value > 0)
m_decProductPrice = value;
else
throw new Exception("Invalid Producr Price! Product price Cannot Be less than 0");
}
}
private decimal m_decDiscountPrice; // Product Discount variable
public decimal Discount // Properity for Product Discount
{
get { return m_decDiscountPrice; }
set
{
if (value <= 45 && value > 0)
m_decDiscountPrice = value;
else if (value < 0)
throw new Exception("Product Discount can be either 0 or morethan that, but can't be zero.");
else
throw new Exception("Product discount can't be more than 45");
}
}
public string Display() // Displaying Product Details.
{
StringBuilder display = new StringBuilder();
display.Append("Product ID = " + ProductId + "\n");
display.Append("Product Name = " + ProductName + "\n");
//disp.Append("Product Manufactured Date = " + );
display.Append("Product Expiry Date = " + ExpiryDate + "\n");
display.Append("Product Price Per 1 Quantity = " + ProductPrice + "\n");
display.Append("Product Quantity = " + ProductQnty + "\n");
display.Append("Product Discount per 1 Quantity= " + Discount + "\n");
return display.ToString();
}
}
class Program
{
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("Enter 1 to ADD product.\n Enter 2 to Display Product. \n Enter 3 to Exit.");
string Instruction = Console.ReadLine();
Product[] products = new Product[3];
switch (Instruction)
{
case "1":
{
Product p1 = new Product();
Console.Write("Enter Producr Id : ");
p1.ProductId = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter Product Name : ");
p1.ProductName = Console.ReadLine();
Console.Write("Enter Product Quantity : ");
p1.ProductQnty = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter Product Price : ");
p1.ProductPrice = Convert.ToDecimal(Console.ReadLine());
Console.Write("Enter Product Discount in number without % symbol : ");
p1.Discount = Convert.ToDecimal(Console.ReadLine());
products.Append(p1);
Console.WriteLine("\n \n \n" + "Product Added Succesfully \n " + "ThankYou.");
Console.WriteLine("Total Products Entered = " + p1.ProductCount);
}
break;
case "2":
{
Console.WriteLine(products[0].Display());
break;
}
}
if (Instruction == "3")
break;
}
}
}
why you are using array for products collection? And inside while you are always creating new array for products (inside while: Product[] products = new Product[3];)!
Use List or any dynamic collection in this case, change your main method to this:
static void Main(string[] args)
{
var products = new List<Product>();
while (true)
{
Console.WriteLine("Enter 1 to ADD product.\n Enter 2 to Display Product. \n Enter 3 to Exit.");
string Instruction = Console.ReadLine();
switch (Instruction)
{
case "1":
{
var p1 = new Product();
Console.Write("Enter Producr Id : ");
p1.ProductId = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter Product Name : ");
p1.ProductName = Console.ReadLine();
Console.Write("Enter Product Quantity : ");
p1.ProductQnty = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter Product Price : ");
p1.ProductPrice = Convert.ToDecimal(Console.ReadLine());
Console.Write("Enter Product Discount in number without % symbol : ");
p1.Discount = Convert.ToDecimal(Console.ReadLine());
products.Add(p1);
Console.WriteLine("\n \n \n" + "Product Added Succesfully \n " + "ThankYou.");
Console.WriteLine("Total Products Entered = " + p1.ProductCount);
}
break;
case "2":
{
foreach (var item in products)
Console.WriteLine(item.Display());
break;
}
}
if (Instruction == "3")
break;
}
}
I'm trying to return out of a method in C#, but every time I run the program I get a message that I'm creating a variable but never using it, then I get errors that the current variable does not exist in current context.
I am relatively new to C#, and I might be really dumb but if anyone can help me that will be great!
The code:
using System;
class MainClass
{
public static void Main()
{
int health = 3;
int powerCrystals = 0;
int healthCrystals = 0;
int basicEnemyDamage = 1;
int basicEnemyScore = 10;
string basicEnemyDrops = "1 powerCrystal";
int score = 0;
// Basic Enemies Drop 1 powerCrystal.
// Moderate Enemies Drop 1 powerCrystal and 1 healthCrystal.
// Advanced Enemies Drop 2 powerCrystals and 1 healthCrystal.
// Bosses Drop 3 powerCrystals and 3 healthCrystals.
Console.WriteLine("Input your username:");
string userName = Console.ReadLine();
Console.WriteLine("Welcome, " + userName);
Console.WriteLine("To check your stats, write: stats");
TrollFight();
}
static void TrollFight()
{
Console.WriteLine(userName + "! There is a pack of trolls aproaching! Guess the right number to kill them!");
Console.WriteLine("Your current health is = " + health);
Console.WriteLine("Guess the correct number and then you can defeat the trolls! It is between 1-9!");
int guessedNumber = Convert.ToInt32(Console.ReadLine());
if (guessedNumber == 4)
{
Console.WriteLine("You killed the trolls! You gained: " + basicEnemyDrops);
score = score + basicEnemyDamage;
Console.WriteLine("Your score is = " + score);
return;
}
else
{
Console.WriteLine("WRONG! You took damage! Come on, guess again!");
health = health - basicEnemyDamage;
}
int guessedNumber2 = Convert.ToInt32(Console.ReadLine());
if (guessedNumber2 == 4)
{
Console.WriteLine("You killed the trolls! You gained: " + basicEnemyDrops);
score = score + basicEnemyScore;
Console.WriteLine("Your score is = " + score);
return;
}
else
{
Console.WriteLine("WRONG! You took damage! Come on, guess again! Your health is = 2");
health = health - basicEnemyScore;
}
int guessedNumber3 = Convert.ToInt32(Console.ReadLine());
if (guessedNumber3 == 4)
{
Console.WriteLine("You killed the trolls! You gained: " + basicEnemyDrops);
score = score + basicEnemyDamage;
Console.WriteLine("Your score is = " + score);
return;
}
else
{
Console.WriteLine("WRONG! You took damage! Come on, guess again! Your health is = 1");
Console.WriteLine("You are almost dead! You do not have any Health Crystals so you can't heal!");
health = health - basicEnemyScore;
}
int guessedNumber4 = Convert.ToInt32(Console.ReadLine());
if (guessedNumber4 == 4)
{
Console.WriteLine("You killed the trolls! You gained: " + basicEnemyDrops);
score = score + basicEnemyScore;
Console.WriteLine("Your score is = " + score);
return;
}
else
{
Console.WriteLine("WRONG! You died! Your final score = " + score);
health = health - basicEnemyDamage;
}
Console.WriteLine("To check your stats, write: stats");
}
}
I'm trying to return out of a method but it gives me a CS0219 warning
Ok a few things. The difference between a Void/Subroutine and a Function is that a Function returns something. Both your methods are voids, they don't return anything:
public static void Main()
static void TrollFight()
The problem with the variables is that they are out of scope.
Local - visible within the method
Private - visible to the class
Public - visible outside the assembly
One solution is to make the variables Private member variables:
class MainClass {
private int health = 3;
private int powerCrystals = 0;
private int healthCrystals = 0;
private int basicEnemyDamage = 1;
private int basicEnemyScore = 10;
private string basicEnemyDrops = "1 powerCrystal";
private int score = 0;
public static void Main() {
Run the project, this should fix it. The problem with using Private variable scope is it can get messy when multiple methods can change variables (without the other knowing). In this case we can use parameters to pass variables to voids or functions:
TrollFight(basicEnemyDamage);
...
static void TrollFight(string basicEnemyDamage) {
A good design will use all three with local variables:
class MainClass {
private int health = 3;
private string basicEnemyDrops = "1 powerCrystal";
private int score = 0;
public static void Main() {
...
}
static void TrollFight(string basicEnemyDamage) {
int powerCrystals = 0;
int healthCrystals = 0;
int basicEnemyDamage = 1;
int basicEnemyScore = 10;
I'd even change the void to return the Score:
static int TrollFight(string basicEnemyDamage, int score)
{
return score;
}
The Code:
using System;
public class MainClass {
private int health = 3;
private int score = 0;
private int powerCrystals = 0;
private int healthCrystals = 0;
private int basicEnemyDamage = 1;
private int basicEnemyScore = 10;
private string basicEnemyDrops = "1 powerCrystal";
public static void Main() {
//Basic Enemies Drop 1 powerCrystal.
//Moderate Enemies Drop 1 powerCrystal and 1 healthCrystal.
//Advanced Enemies Drop 2 powerCrystals and 1 healthCrystal.
//Bosses Drop 3 powerCrystals and 3 healthCrystals.
Console.WriteLine("Input your username:");
string userName = Console.ReadLine();
Console.WriteLine("Welcome, " + userName);
Console.WriteLine("To check your stats, write: stats");
TrollFight(userName);
}
static void TrollFight(string userName) {
Console.WriteLine(userName + "! There is a pack of trolls approaching! Guess the right number to kill them!");
Console.WriteLine("Your current health is = " + health.ToString());
Console.WriteLine("Guess the correct number and then you can defeat the trolls! It is between 1-9!");
int guessedNumber = Convert.ToInt32(Console.ReadLine());
if (guessedNumber == 4)
{
Console.WriteLine("You killed the trolls! You gained: " + basicEnemyDrops);
score = score + basicEnemyDamage;
Console.WriteLine("Your score is = " + score.ToString());
return;
}
else
{
Console.WriteLine("WRONG! You took damage! Come on, guess again!");
health = health - basicEnemyDamage;
}
int guessedNumber2 = Convert.ToInt32(Console.ReadLine());
if (guessedNumber2 == 4)
{
Console.WriteLine("You killed the trolls! You gained: " + basicEnemyDrops);
score = score + basicEnemyScore;
Console.WriteLine("Your score is = " + score.ToString());
return;
}
else
{
Console.WriteLine("WRONG! You took damage! Come on, guess again! Your health is = 2");
health = health - basicEnemyScore;
}
int guessedNumber3 = Convert.ToInt32(Console.ReadLine());
if (guessedNumber3 == 4)
{
Console.WriteLine("You killed the trolls! You gained: " + basicEnemyDrops);
score = score + basicEnemyDamage;
Console.WriteLine("Your score is = " + score.ToString());
return;
}
else
{
Console.WriteLine("WRONG! You took damage! Come on, guess again! Your health is = 1");
Console.WriteLine("You are almost dead! You do not have any Health Crystals so you can't heal!");
health = health - basicEnemyScore;
}
int guessedNumber4 = Convert.ToInt32(Console.ReadLine());
if (guessedNumber4 == 4)
{
Console.WriteLine("You killed the trolls! You gained: " + basicEnemyDrops);
score = score + basicEnemyScore;
Console.WriteLine("Your score is = " + score.ToString());
return;
}
else
{
Console.WriteLine("WRONG! You died! Your final score = " + score.ToString());
health = health - basicEnemyDamage;
}
Console.WriteLine("To check your stats, write: stats");
}
}
I made a game where you first say how many players there are and then every player throws 3 darts and it loops until one player gets 301 points and now I want to get the player who got more than 301 points from the list of players and I want to get their score so I can print out their score and say that they won at the end of the game but I can't figure out how to do that. Thanks
class Program
{
public static void Main(string[] args)
{
Game My_game = new Game();
My_game.PlayGame();
}
}
public class Game
{
private List<Player> player_list = new List<Player>();
private List<int> total_list = new List<int>();
public void PlayGame()
{
Random random_number = new Random();
int throw1;
int throw2;
int throw3;
string more_players = "yes";
while (more_players == "yes")
{
Console.WriteLine("What is the players name?: ");
player_list.Add(new Player(Console.ReadLine()));
Console.WriteLine("Are there more players?");
more_players = Console.ReadLine();
}
Console.WriteLine("\n\n Welcome to the dartgame! \n" +
"\n Game Rules: Each player throws 3 darts at a time." +
"\n Every throw can be worth 0-20 points." +
"\n Whoever gets 301 points first is the winner!");
Console.WriteLine("\nPlayers:");
foreach (var players in player_list)
{
Console.WriteLine(players);
}
int total_points = 0;
while (!player_list.Any(x => x.calculate_points() >= 301))
{
foreach (var players in player_list)
{
Console.WriteLine("\n\n\n\n");
Console.WriteLine("\n first throw for{0}!", players);
Console.WriteLine("Press space to throw a dart!");
Console.ReadKey();
throw1 = random_number.Next(1, 20);
Console.WriteLine("You got " + throw1 + " points!");
Console.WriteLine("\n second throw for{0}!", players);
Console.WriteLine("Press space to throw a dart!");
Console.ReadKey();
throw2 = random_number.Next(1, 20);
Console.WriteLine("You got " + throw2 + " points!");
Console.WriteLine("\n third throw for{0}!", players);
Console.WriteLine("Press space to throw a dart!");
Console.ReadKey();
throw3 = random_number.Next(1, 20);
Console.WriteLine("You got " + throw3 + " points!");
total_points = throw1 + throw2 + throw3;
Console.WriteLine("\nPoints for this round: " + total_points);
total_list.Add(total_points);
total_points = total_list.Sum(x => Convert.ToInt32(x));
players.Add_turn(throw1, throw2, throw3);
}
foreach (var players in player_list)
{
players.print_turns();
}
}
}
}
class Player
{
private string name;
private List<Turns> turn_list = new List<Turns>();
public Player(string _name)
{
name = _name;
}
public void Add_turn(int turn1, int turn2, int turn3)
{
turn_list.Add(new Turns(turn1, turn2, turn3));
}
public int calculate_points()
{
int total = 0;
foreach (var turns in turn_list)
{
total = total + turns.Get_Score();
}
return total;
}
public void print_turns()
{
Console.WriteLine("\n\n\n\n----------------------------------------");
Console.WriteLine("Points for {0}", name);
foreach (var turns in turn_list)
{
Console.WriteLine(turns);
}
Console.WriteLine("\n Total points: {0}", calculate_points());
}
public override string ToString()
{
return string.Format(" {0} ", name);
}
}
class Turns
{
private int turn1;
private int turn2;
private int turn3;
public Turns(int _turn1, int _turn2, int _turn3)
{
turn1 = _turn1;
turn2 = _turn2;
turn3 = _turn3;
}
public int Get_Score()
{
int totalt;
totalt = turn1 + turn2 + turn3;
return totalt;
}
public override string ToString()
{
return string.Format("\n throw 1: {0} \n throw 2: {1} \n throw 3: {2}", turn1, turn2, turn3);
}
}
Well, this is how you already check if any players match the criteria:
player_list.Any(x => x.calculate_points() >= 301)
So as soon as one does match the criteria, you can get that single player:
player_list.Single(x => x.calculate_points() >= 301)
Or all matching players, if there's more than one:
player_list.Where(x => x.calculate_points() >= 301)
Or just the first matching player, if there's more than one but you only want one:
player_list.First(x => x.calculate_points() >= 301)
Or perhaps the player with the highest score (not accounting for a tie score):
player_list.OrderByDescending(x => x.calculate_points()).First();
My code is as follows:
namespace Calculation
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("This is a system to calculate speed, distance or time.");
Console.WriteLine("1 = Speed - 2 = Distance - 3 = time");
Console.WriteLine("Please enter which calculation you would like to perform. 1, 2 or 3");
string userCalculation = Console.ReadLine();
int Calculation = int.Parse(userCalculation);
if(Calculation < 1)
{
Console.WriteLine("Please enter a number greater than or equal to 1 but less than 3.");
}
if (Calculation > 3)
{
Console.WriteLine("Please enter a number less than 3 but greater than or equal to 1.");
}
else
{
switch (Calculation)
{
//This statement calculates speed.
case 1:
Console.WriteLine("You have chose to calculate speed. S = D/T");
Console.WriteLine("To work this out you need to firstly enter your distance in metres");
string userDistance = Console.ReadLine();
int Distance = int.Parse(userDistance);
Console.WriteLine("Now enter your time in seconds.");
string userTime = Console.ReadLine();
int Time = int.Parse(userTime);
Console.WriteLine("Your speed is " + Distance / Time + " m/s");
Console.WriteLine("In MPH this is " + Distance / Time * 2.23 + "MPH");
break;
//This statement calculates distance.
case 2:
Console.WriteLine("You have chose to calculate distance. D = SxT");
Console.WriteLine("To work this out you need to firstly enter your speed");
string userSpeed = Console.ReadLine();
int Speed = int.Parse(userSpeed);
Console.WriteLine("Now enter your time in hours.");
string userTime1 = Console.ReadLine();
double Time1 = double.Parse(userTime1);
Console.WriteLine("Your Distance is " + Speed * Time1 + " miles");
break;
//This statement calculates time.
case 3:
Console.WriteLine("You have chose to calculate Time. T = D/S");
Console.WriteLine("To work this out you need to firstly enter your distance in miles.");
string userMiles = Console.ReadLine();
int Miles = int.Parse(userMiles);
Console.WriteLine("Now enter your Speed in MPH.");
string userSpeed2 = Console.ReadLine();
double Speed2 = double.Parse(userSpeed2);
Console.WriteLine("Your Time is " + Miles / Speed2 + "hours.");
Console.WriteLine("This would be " + Miles / Speed2 * 60 + " minutes");
break;
}
}
}
}
}
You can remove one if statement it is not very diffrent from die other if statement. replace it by this one:
if (Calculation < 1 || Calculation > 3)
{
Console.WriteLine("Please enter a number greater than or equal to 1 but less than 3.");
}
Create Two funtions to return user input one for int and the second for the double return type.
private int GetIntUserInput()
{
string userInput = Console.ReadLine();
int convertedUserInput = int.Parse(userInput);
return convertedUserInput;
}
private double GetDoubleUserInput()
{
string userInput = Console.ReadLine();
double convertedUserInput = double.Parse(userInput);
return convertedUserInput;
}
And I should move the calculations to a funtion as well
You also can use an enum for better readability.
enum Options
{
Speed,
Time,
Distance
}
//example
Options calculation = (Options)Calculation; //cast user input number
// to Option enum
switch (calculation)
{
case options.Distance:
// some code
break;
case options.Speed:
// some code
break;
}
First of all, for a better maintainablity index, you better make those 3 algorithms into seperate functions and call them, or at least the calculations.
About the if/switch, you can use a default: case at the end of your switch,
default:
Console.WriteLine("Please enter a number greater than or equal to 1 but less than 3.");
break;
Hope it helped.
As a start, perhaps something like this (air code):
case 1:
Console.WriteLine("You have chose to calculate speed. S = D/T");
int Distance = GetNumericInput("To work this out you need to firstly enter your distance in metres");
int Time = GetNumericInput("Now enter your time in seconds.");
Console.WriteLine("Your speed is " + Distance / Time + " m/s");
Console.WriteLine("In MPH this is " + Distance / Time * 2.23 + "MPH");
break;
Which uses this function (air code, needs error handling):
string GetNumericInput(string prompt)
{
Console.WriteLine(prompt;
string input = Console.ReadLine();
int inputNumeric = int.Parse(input);
return input;
}
My usual approach for organising code like this is to make each case into a class, and add those classes into a dictionary against their case value, e.g.:
public interface ICalculation
{
void Run();
}
public class SpeedCalculation
: ICalculation
{
public void Run()
{
Console.WriteLine("You have chose to calculate speed. S = D/T");
Console.WriteLine("To work this out you need to firstly enter your distance in metres");
string userDistance = Console.ReadLine();
int Distance = int.Parse(userDistance);
Console.WriteLine("Now enter your time in seconds.");
string userTime = Console.ReadLine();
int Time = int.Parse(userTime);
Console.WriteLine("Your speed is " + Distance / Time + " m/s");
Console.WriteLine("In MPH this is " + Distance / Time * 2.23 + "MPH");
}
}
...more ICalculation types...
class Program
{
static void Main(string[] args)
{
var caseDictionary = new Dictionary<int, ICalculation>
{
{1, new SpeedCalculation()},
{2, new DistanceCalculation()},
{3, new TimeCalculation()}
};
Console.WriteLine("This is a system to calculate speed, distance or time.");
Console.WriteLine("1 = Speed - 2 = Distance - 3 = time");
Console.WriteLine("Please enter which calculation you would like to perform. 1, 2 or 3");
string userCalculation = Console.ReadLine();
int Calculation = int.Parse(userCalculation);
if(!caseDictionary.ContainsKey(Calculation))
{
Console.WriteLine("Please enter a number between 1 and 3 (inclusive).");
}
else
{
caseDictionary[Calculation].Run();
}
}
}
This gives you options for organising the code as you like with inheritance or abstractions, makes it easy to add new cases (even programmatically), and you could make the main method more flexible (e.g. the line "1 = Speed - 2 = Distance - 3 = time" could be generated from the contents of the dictionary).
I'd do the following:
class Program
{
private class MenuOption
{
public string Description { get; }
public Action Run { get; }
public MenuOption(string description, Action run)
{
Description = description;
Run = run;
}
}
static void Main(string[] args)
{
int option;
var menuOptions = buildMenuOptions();
do
{
Console.WriteLine($"This is a system to calculate: {string.Join(", ", menuOptions.Values.Take(menuOptions.Count-1).Select(o => o.Description))}");
Console.WriteLine(string.Join(" - ", menuOptions.Select(kv => $"{kv.Key} = {kv.Value.Description}")));
Console.WriteLine($"Please enter which calculation you would like to perform. [{string.Join(", ", menuOptions.Keys)}]");
} while (!tryValidateUserOption(menuOptions, out option));
menuOptions[option].Run();
Console.Write("Press key to exit... ");
Console.ReadKey();
}
private static IDictionary<int, MenuOption> buildMenuOptions() =>
new Dictionary<int, MenuOption>() { { 1, new MenuOption("Speed", () => runSpeedOption()) },
{ 2, new MenuOption("Distance", () => runDistanceOption()) },
{ 3, new MenuOption("Time", () => runTimeOption())},
{ 4, new MenuOption("Quit", () => { return; }) } };
private static bool tryValidateUserOption(IDictionary<int, MenuOption> options, out int selectedOption)
{
var input = Console.ReadLine();
if (!int.TryParse(input, out selectedOption) ||
!options.ContainsKey(selectedOption))
{
Console.WriteLine("Invalid option. Please try again.");
return false;
}
return true;
}
private static void runTimeOption()
{
int miles;
double speed;
Console.WriteLine("You have chose to calculate Time. T = D/S.");
getUserInput("To work this out you need to firstly enter your distance in miles.", 0, int.MaxValue, out miles);
getUserInput("Now enter your Speed in MPH.", 0, double.MaxValue, out speed);
Console.WriteLine("Your Time is " + miles / speed + " hours.");
Console.WriteLine("This would be " + miles / speed * 60 + " minutes");
}
private static void runDistanceOption()
{
int speed;
double time;
Console.WriteLine("You have chose to calculate distance. D = SxT.");
getUserInput("To work this out you need to firstly enter your speed.", 0, int.MaxValue, out speed);
getUserInput("Now enter your time in hours.", 0, double.MaxValue, out time);
Console.WriteLine("Now enter your time in hours.");
Console.WriteLine("Your Distance is " + speed * time + " miles");
}
private static void runSpeedOption()
{
int distance, time;
Console.WriteLine("You have chose to calculate speed. S = D/T");
getUserInput("To work this out you need to firstly enter your distance in metres.", 0, int.MaxValue, out distance);
getUserInput("Now enter your time in seconds.", 0, int.MaxValue, out time);
Console.WriteLine("Your speed is " + distance / time + " m/s");
Console.WriteLine("In MPH this is " + distance / time * 2.23 + " MPH");
}
private static void getUserInput(string message, int lowerInclusiveBound, int upperExclusiveBound, out int value)
{
while (true)
{
Console.WriteLine(message);
var input = Console.ReadLine();
if (int.TryParse(input, out value) &&
value >= lowerInclusiveBound &&
value < upperExclusiveBound)
return;
Console.WriteLine("Input is not a valid value. Please try again.");
}
}
private static void getUserInput(string message, double lowerInclusiveBound, double upperExclusiveBound, out double value)
{
while (true)
{
Console.WriteLine(message);
var input = Console.ReadLine();
if (double.TryParse(input, out value) &&
value >= lowerInclusiveBound &&
value < upperExclusiveBound)
return;
Console.WriteLine("Input is not a valid value. Please try again.");
}
}
}
Things to note:
Don't hard code the menu. Make it flexible, that way adding options is easy; look how much it took to add a fourth option.
If the menu is not set, you can't hard code options with ifs and switches. Use a dictionary with the option number as a key. Store as value a delegate to the action you want to perform.
Try to not repeate code. Extract all common functionality to helper methods that can be reused; consider changing all inputs to double to reduce pesky code duplication validating ints and doubles.
I wrote some code to take in five Social Security Numbers, five gross income entries, and calculate tax for each one. The program will use default values for dollar limit, low rate, and high rate to calculate tax owed. But it will also let user to choose if he/she wants to use their own dollar limit, low rate, and high rate to calculate tax owed for a chosen taxpayer.
Problem:
Whenever I enter my own dollar limit, low rate, and high rate to calculate tax owed it still uses default values (limit = 30000, low rate = .15 and high rate = .28). And that's how a get the wrong calculated tax owed values.
Question.
Could it be because my "public static void GetRates(int income)" doesn't have a return type (it is void)? Should I be returning a value back to main after I call "Taxpayer.GetRates(taxPayer[x].grossIncome);" method?
Part of the code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace assignment
{
public class Rates
{
public int incomeLimit; // income limit
public double lowTaxRate; // low tax rate
public double highTaxRate; // high tax rate
public int IncomeLimit // read only property
{
get
{
return incomeLimit;
}
}
public double LowTaxRate // read only property
{
get
{
return lowTaxRate;
}
}
public double HighTaxRate // read only property
{
get
{
return highTaxRate;
}
}
public Rates()
{
DoRates();
}
public void DoRates() // class constructor that assigns default values
{
// set default values for limit, lowRate, and highRate
incomeLimit = 30000;
lowTaxRate = .15;
highTaxRate = .28;
}
public void DoRates(int limit, double lowRate, double highRate) // class constructor that takes three parameters
{
incomeLimit = limit;
lowTaxRate = lowRate;
highTaxRate = highRate;
}
// CalculateTax method that takes an income parameter and computes the tax
public int CalculateTax(int income)
{
int taxOwed = 0;
if (income < incomeLimit)
{
taxOwed = Convert.ToInt32(income * lowTaxRate);
}
if (income >= incomeLimit)
{
taxOwed = Convert.ToInt32(income * highTaxRate);
}
return taxOwed;
}
}
public class Taxpayer : IComparable
{
string socialSecurityNum;
int grossIncome;
int taxOwed;
// Use get and set accessors.
public string SocialSecurityNum
{
get
{
return socialSecurityNum;
}
set
{
socialSecurityNum = value;
}
}
// Use get and set accessors.
public int GrossIncome
{
get
{
return grossIncome;
}
set
{
grossIncome = value;
}
}
// Use read-only accessor
public int TaxOwed
{
get
{
return taxOwed;
}
}
// objects are comparable to each other based on tax owed.
int IComparable.CompareTo(Object o)
{
int returnVal;
Taxpayer temp = (Taxpayer)o;
if (this.taxOwed > temp.TaxOwed)
returnVal = 1;
else
if (this.taxOwed < temp.TaxOwed)
returnVal = -1;
else
returnVal = 0;
return returnVal;
}
public static void GetRates(int income)
{
int incomeLimit;
double lowRate;
double highRate;
char input;
Rates rates = new Rates();
Console.Write("Do you want default values (enter D) or enter your own (enter O)? ");
input = Convert.ToChar(Console.ReadLine());
switch (char.ToUpper(input)) // start switch
{
case 'D': // if the input latter is d or a D
rates.DoRates();
break;
case 'O': // if the input latter is o or an O
Console.Write("Enter the dollar limit ");
incomeLimit = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the low rate ");
lowRate = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter the high rate ");
highRate = Convert.ToDouble(Console.ReadLine());
rates.DoRates(incomeLimit, lowRate, highRate);
rates.CalculateTax(income);
break;
default: Console.WriteLine("You entered and incorrect option"); // display this messages if the input was something other than D or O
break;
}
}
public static void Main()
{
// instantiate an array of five (5) Taxpayer objects.
Taxpayer[] taxPayer = new Taxpayer[5];
Rates taxRates = new Rates();
// Implement a for-loop that will prompt the user
// to enter the Social Security Number and gross income.
for (int x = 0; x < taxPayer.Length; ++x)
{
taxPayer[x] = new Taxpayer();
Console.Write("Enter Social Security Number for taxpayer {0} ", x + 1);
taxPayer[x].socialSecurityNum = Convert.ToString(Console.ReadLine());
Console.Write("Enter gross income for taxpayer {0} ", x + 1);
taxPayer[x].grossIncome = Convert.ToInt32(Console.ReadLine());
Taxpayer.GetRates(taxPayer[x].grossIncome);
taxPayer[x].taxOwed = taxRates.CalculateTax(taxPayer[x].grossIncome);
}
Thank you for the help everyone. I think I did get carried away a little while writing this code. After isolating the code with my issue I finally figured it out. Here is what I did in case anyone wants to see.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace assignment
{
public class Rates
{
public int incomeLimit; // income limit
public double lowTaxRate; // low tax rate
public double highTaxRate; // high tax rate
public int IncomeLimit { get { return incomeLimit; } }// read only property
public double LowTaxRate { get { return lowTaxRate; } } // read only property
public double HighTaxRate { get { return highTaxRate; } }// read only property
public Rates()
{
incomeLimit = 30000;
lowTaxRate = .15;
highTaxRate = .28;
}
public Rates(int incomeLim, double lowRate, double highRate)
{
incomeLimit = incomeLim;
lowTaxRate = lowRate;
highTaxRate = highRate;
}
// CalculateTax method that takes an income parameter and computes the tax
public int CalculateTax(int income)
{
int taxOwed = 0;
if (income < incomeLimit)
{
taxOwed = Convert.ToInt32(income * lowTaxRate);
}
if (income >= incomeLimit)
{
taxOwed = Convert.ToInt32(income * highTaxRate);
}
return taxOwed;
}
}
public class Taxpayer
{
string socialSecurityNum = null;
int grossIncome = 0;
int taxOwed = 0;
// Use get and set accessors.
public string SocialSecurityNum { get {return socialSecurityNum;} set {socialSecurityNum = value;} }
// Use get and set accessors.
public int GrossIncome { get { return grossIncome; } set { grossIncome = value; } }
// Use read-only accessor
public int TaxOwed { get { return taxOwed; } }
public void GetRates(int income)
{
int incomeLimit = 0;
double lowRate = 0;
double highRate = 0;
char input;
Console.Write("Do you want default values (enter D) or enter your own (enter O)? ");
input = Convert.ToChar(Console.ReadLine());
switch (char.ToUpper(input)) // start switch
{
case 'D': // if the input latter is d or a D
Rates rates = new Rates();
taxOwed = rates.CalculateTax(income);
break;
case 'O': // if the input latter is o or an O
Console.Write("Enter the dollar limit ");
incomeLimit = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the low rate ");
lowRate = Convert.ToDouble(Console.ReadLine());
Console.Write("Enter the high rate ");
highRate = Convert.ToDouble(Console.ReadLine());
Rates myrates = new Rates(incomeLimit, lowRate, highRate);
taxOwed = myrates.CalculateTax(income);
break;
default: Console.WriteLine("You entered and incorrect option"); // display this messages if the input was something other than D or O
break;
}
}
public static void Main()
{
Taxpayer[] taxPayer = new Taxpayer[5];
Rates taxRates = new Rates();
Taxpayer myTaxpayer = new Taxpayer();
// Implement a for-loop that will prompt the user
// to enter the Social Security Number and gross income.
for (int x = 0; x < taxPayer.Length; ++x)
{
taxPayer[x] = new Taxpayer();
Console.Write("Enter Social Security Number for taxpayer {0} ", x + 1);
taxPayer[x].socialSecurityNum = Convert.ToString(Console.ReadLine());
Console.Write("Enter gross income for taxpayer {0} ", x + 1);
taxPayer[x].grossIncome = Convert.ToInt32(Console.ReadLine());
myTaxpayer.GetRates(taxPayer[x].grossIncome);
taxPayer[x].taxOwed = myTaxpayer.taxOwed;
}
// Implement a for-loop that will display each object
// as formatted taxpayer SSN, income and calculated tax.
for (int y = 0; y < taxPayer.Length; ++y)
{
Console.WriteLine("Taxpayer # {0} SSN: {1} income {2:C} Tax is {3:C}", y + 1, taxPayer[y].socialSecurityNum,
taxPayer[y].grossIncome, taxPayer[y].taxOwed);
}
}
}
}
I'll recommend to you to change your code, a more clean code and using betters OOP techniques.
You should check the class Taxpayer, specifically the method called GetRates().
in that method you create a object of type Rates, now, if you check the constructor of the class Rates
public Rates()
{
DoRates();
}
it calls the method Dorates() but without parameters, so, it will always call these DoRates method
public void DoRates() // class constructor that assigns default values
{
// set default values for limit, lowRate, and highRate
incomeLimit = 30000;
lowTaxRate = .15;
highTaxRate = .28;
}
I'm surprised your compiler didn't complain. In Taxpayer.GetRates(int) you make a call to Rates.CalculateTax(int), which returns an int value. It doesn't get stored or returned anywhere, so I'm not sure what the purpose of the call is there. Also, since the object rates is attached to the static method GetRates(int), you're not changing any values in the object taxratesthat you use to calculate the tax. Finally, as has been suggested, your constructor sets default values. You could potentially add another constructor to take parameters. From there, you might want to make sure you change the values in the object you're using to calculate tax.
Occam's razor: keep it simple stupid. I think you're getting carried away with OOP. Simplify some things to make it work.