Variable as function parameter? - c#

I am doing a sort of little rpg(role playing game), in the conversations there are decisions that influence certain variables of the player. I was wondering if you knew a more effective way than mine:
public string Name, Nickname;
public int Age;
public void Decision(string Var, string Input)
{
if (Var == "Name")
Name = Input;
else if (Var == "Nickname")
Nickname = Input;
else if (Var == "Age")
Age = Convert.ToInt32(Input);
}
As you can see, it is pretty long for only 3 variables, but there are more... Is there a way to do it faster? Something like this:
public void Decision(Variable Var, string Input)
{
Player.Var = input;
}
Edit: I will use a mix of the two answers:
public string Nom, Prenom;
public int Age;
public void Decision(InfoType type, string Input)
{
switch (type)
{
case InfoType.Name:
Nom = Input;
break;
case InfoType.Prenom:
Prenom = Input;
break;
}
}
public void Decision(InfoType type, int Input)
{
switch (type)
{
case InfoType.Age:
Age = Convert.ToInt32(Input);
break;
}
}

How about method overloading?
public void Decision(string Var, string Input)
{
if (Var == "Name")
Name = Input;
else if (Var == "Nickname")
Nickname = Input;
}
public void Decision(int Input)
{
Age = input
}

You could possibly use reflection. The downside to this is you will have to do additional checks for complex types, but for simple objects it can work like this.
public class MyObject {
public string Name { get; set; }
public string Nickname { get; set; }
public int Age { get; set; }
}
public class TestReflection {
public void Test() {
var obj = new MyObject();
UpdateObject(obj, "Name", "THis is a name");
UpdateObject(obj, "Age", 99);
UpdateObject(obj, "Nickname", "This is a nickname");
Console.WriteLine("{0} {1} {2}", obj.Name, obj.Age, obj.Nickname);
Console.ReadLine();
}
private void UpdateObject(MyObject obj, string varName, object varValue) {
//Get Properties of the object
var properties = obj.GetType().GetProperties();
//Search for the property via the name passed over to the method.
var prop = properties.FirstOrDefault(_ => _.Name.Equals(varName, StringComparison.InvariantCultureIgnoreCase));
//Check prop exists and set to the object.
if(prop != null) {
prop.SetValue(obj, varValue);
}
}
}

You could make things a little bit more concise with a switch statement and also use an enum for type safety. e.g.
public enum InfoType {
Name,
Nickname,
Age
}
public void Decision(InfoType type, string input)
{
switch (type)
{
case InfoType.Name:
Name = input;
break;
case InfoType.NickName:
NickName = input;
break;
}
}
And so on.

Related

How to write commands for File/Json

Below is the code I made but I don't know where to start.
I will be grateful for the hint.
I have no idea what i should do next..
I want to make a program that will have a few commands.
Adding a new planet
Planet Removal
Show the List
Save to JSON
displays planet data
public class MyDate
{
public int masa { get; set; }
public int sredni { get; set; }
}
public class Lad
{
public string PlanetName { get; set; }
public MyDate Szczegoly { get; set; }
}
class Program
{
static void Main()
{
string choice = Console.ReadLine();
//string choiceup = choice.ToUpper();
switch (choice)
{
case "Add":
Add();
return;
case "Save":
break;
case "List":
LoadList();
break;
case "Exit":
return;
}
}
public static void Add()
{
Console.WriteLine("Podaj nazwe planety");
string name = Console.ReadLine();
Console.WriteLine("Podaj mase");
int masa = Convert.ToInt16(Console.ReadLine());
Console.WriteLine("Podaj srednice");
int sred = Convert.ToInt16(Console.ReadLine());
List<Lad> _data = new List<Lad>();
_data.Add(new Lad()
{
PlanetName = name,
Szczegoly = new MyDate
{
masa = masa,
sredni = sred
}
});
var json = System.Text.Json.JsonSerializer.Serialize(_data);
Console.WriteLine(json);
string json2 = JsonConvert.SerializeObject(_data, Formatting.Indented);
File.AppendAllText(#"tescikkk.json", json2);
}
static List<Lad> LoadList()
{
string text = File.ReadAllText(#"tescikkk.json");
if (string.IsNullOrEmpty(text))
return new List<Lad>() { };
return JsonConvert.DeserializeObject<Lad[]>(text).ToList();
}
}

Trying to figure out how to access list in a different method

This is my Code inside my Class. I'm trying to figure out how to access Questions list in DisplayQuestion. I have a program.cs that display a menu for a quiz and I can't have anything static.
public string Question { get; set; }
public List<string> Choices { get; set; }
public char[] CorrectChoice = { 'A', 'B', 'C', 'D' };
public List<string> Questions { get; set; }
These are my methods inside my class. I will need to access this list multiple times inside this class.
public void NewQuestion()
{
Questions = new List<string>();
Choices = new List<string>();
Console.WriteLine("Enter the question: ");
Questions.Add(Console.ReadLine());
Console.WriteLine("Enter Choice 1 for the question:");
Choices.Add(Console.ReadLine());
Console.WriteLine("Enter Choice 2 for the question: ");
Choices.Add(Console.ReadLine());
Console.WriteLine("Enter Choice 3 for the question: ");
Choices.Add(Console.ReadLine());
Console.WriteLine("Enter Choice 4 for the question:");
Choices.Add(Console.ReadLine());
// Console.WriteLine("Enter the correct choice(A,B,C,D)");
foreach (string choice in Choices)
{
Console.WriteLine();
Console.WriteLine(choice);
}
}
public void DisplayQuestions()
{
foreach(string question in Questions)
{
Console.WriteLine();
Console.WriteLine(question);
}
}
try declaring and initializing it to null in the global section or create a class with proper getter setter methods for it.
Don't feel constrained to do everything in one class. Even a rough, verbose attempt at separating concerns into separate classes helps with readability, maintainability, and sanity. Then, you're just a thoughtful refactor away from good code.
You are using C#, an OBJECT-oriented language. So go with the grain and embrace using objects.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Quiz_StackOverflow
{
class Program
{
static void Main(string[] args)
{
var quizGenerator = new QuizGenerator();
var quiz = quizGenerator.GenerateQuiz();
var quizProctor = new QuizProctor();
var grade = quizProctor.ProctorQuiz(quiz);
Console.WriteLine(grade.ToString());
Console.WriteLine("Done. Press any key to exit.");
Console.ReadKey();
}
}
public class QuizGenerator
{
public Quiz GenerateQuiz()
{
var problems = GenerateProblems();
var quiz = new Quiz()
{
Problems = problems
};
return quiz;
}
private List<Problem> GenerateProblems()
{
List<Problem> problems = new List<Problem>();
int numChoices = InputValidator.GetPositiveNumber("Enter number of problems: ");
for (int i = 0; i < numChoices; i++)
{
Problem problem = GenerateProblem();
problems.Add(problem);
}
return problems;
}
private Problem GenerateProblem()
{
var question = GenerateQuestion();
var choices = GenerateChoices();
var answer = GenerateAnswer(choices);
var problem = new Problem()
{
Question = question,
Choices = choices,
Answer = answer
};
return problem;
}
private string GenerateQuestion()
{
Console.WriteLine("Enter the question: ");
string question = Console.ReadLine();
return question;
}
private List<string> GenerateChoices()
{
List<string> choices = new List<string>();
int numChoices = InputValidator.GetPositiveNumber("Enter number of choices for the question: ");
for (int i=1; i<=numChoices; i++)
{
string choice = GenerateChoice(i);
choices.Add(choice);
}
return choices;
}
private string GenerateChoice(int index)
{
Console.WriteLine($"Enter Choice {index} for the question: ");
string choice = Console.ReadLine();
return choice;
}
private Answer GenerateAnswer(List<string> choices)
{
Console.WriteLine("Enter the answer: ");
string userChoice = InputValidator.GetUserChoice(new Problem() { Choices=choices });
var answer = new Answer()
{
Value = userChoice
};
return answer;
}
}
public class QuizProctor
{
public Grade ProctorQuiz(Quiz quiz)
{
var answers = new List<Answer>();
foreach(Problem problem in quiz.Problems)
{
Answer answer = ProctorProblem(problem);
answers.Add(answer);
}
Grade grade = quiz.Grade(answers);
return grade;
}
private Answer ProctorProblem(Problem problem)
{
string userChoice = InputValidator.GetUserChoice(problem);
var answer = new Answer()
{
Value = userChoice
};
return answer;
}
}
public class Quiz
{
public List<Problem> Problems { get; set; }
public Grade Grade(List<Answer> answers)
{
List<Answer> answerKey = Problems.Select(x => x.Answer).ToList();
var rawResults = new List<Tuple<Answer, Answer>>();
for(int i=0; i<answers.Count; i++)
{
Answer correct = answerKey[i];
Answer provided = answers[i];
rawResults.Add(new Tuple<Answer, Answer>(correct, provided));
}
return new Grade(rawResults);
}
}
public class Grade
{
private List<Tuple<Answer, Answer>> RawResults { get; set; }
public decimal Percent
{
get { return decimal.Divide(RawResults.Count(x => x.Item1.Equals(x.Item2)), RawResults.Count); }
}
public Grade(List<Tuple<Answer, Answer>> rawResults)
{
RawResults = rawResults;
}
public override string ToString()
{
return string.Format("You scored a {0:P2}.", Percent);
}
}
public class Problem
{
public string Question { get; set; }
public List<string> Choices { get; set; }
public Answer Answer { get; set; }
public string Prompt()
{
Func<int, char> numberToLetter = (int n) =>
{
return (char)('A' - 1 + n);
};
string prompt = Question;
for (int i=0; i<Choices.Count; i++)
{
string choice = Choices[i];
prompt += $"\n{numberToLetter(i+1)}) {choice}";
}
return prompt;
}
}
public class Answer
{
public string Value { get; set; }
public override string ToString()
{
return Value + "";
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return (obj as Answer).Value.Equals(Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
}
public static class InputValidator
{
public static int GetPositiveNumber(string prompt)
{
int number = -1;
while (number < 0)
{
Console.Write(prompt);
string input = Console.ReadLine();
try
{
number = int.Parse(input);
}
catch (Exception)
{
Console.WriteLine("ERROR: Please input a positive number.");
}
}
return number;
}
public static string GetUserChoice(Problem problem)
{
Func<char, int> letterToNumber = (char c) =>
{
if (char.IsLower(c))
{
return (int)(c - 'a' + 1);
}
return (int)(c - 'A' + 1);
};
char userChoiceLetter = '_';
while (!char.IsLetter(userChoiceLetter))
{
Console.WriteLine(problem.Prompt());
Console.Write("Answer: ");
var input = Console.ReadLine();
try
{
userChoiceLetter = char.Parse(input);
}
catch (Exception)
{
Console.WriteLine("ERROR: Please input a letter corresponding to your choice.");
}
}
int answerIndex = letterToNumber(userChoiceLetter) - 1;
return problem.Choices[answerIndex];
}
}
}

Sorting a list of names with first/last name and age C#

I want to sort the names on this list first by age (which I have done so far), but I was wondering how I could then sort these names again by last name before printing to a new file. For example if I have 5 people that are 20 years old with different last names, how could I make sure those 5 people are in ascending alphabetical order?
class Person : IComparable
{
string vorname;
string nachname;
int age;
public Person(string vorname, string nachname, int age)
{
this.age = age;
this.nachname = nachname;
this.vorname = vorname;
}
public int CompareTo(object obj)
{
Person other = (Person)obj;
int a = this.age - other.age;
if (a != 0)
{
return -a;
}
else
{
return age.CompareTo(other.age);
}
}
public override string ToString()
{
return vorname + " " + nachname + "\t" + age;
}
}
class Program
{
static void Main(string[] args)
{
Person[] peeps = new Person[20];
try
{
StreamReader sr = new StreamReader("inputNames.txt");
int count = 0;
while (!sr.EndOfStream)
{
string data = sr.ReadLine();
Console.WriteLine();
string[] info = data.Split(',');
peeps[count] = new Person(info[0], info[1], int.Parse(info[2]));
count++;
}
Array.Sort(peeps);
sr.Close();
}
catch(FileNotFoundException e)
{
Console.WriteLine(e.Message);
}
StreamWriter sw = new StreamWriter("outputNames.txt");
Console.WriteLine();
foreach (Person p in peeps)
{
Console.WriteLine(p);
sw.WriteLine(p);
}
sw.Close();
}
}
Linq is your friend. You can re-write all that code in 1 line:
peeps.OrderBy(x => x.Age).ThenBy(x => x.LastName);
That's all there is to it :). You can get rid of all that IComparable junk, that's old school.
EDIT: for IComparable, you can do:
public int CompareTo(object obj)
{
Person other = (Person)obj;
if (age < other.age)
return -1;
if (String.Compare(vorname, other.vorname) < 0)
return -1;
return 1;
}
Seems to work for my quick testing, but test it more :).
You can use Linq:
people.OrderBy(person => person.age)
.ThenBy(person => person.LastName);
Little bit old-fashioned, but still. You can use Comparers and use them later as you wish for flexibility:
public class AgeComparer: Comparer<Person>
{
public override int Compare(Person x, Person y)
{
return x.Age.CompareTo(y.Age);
}
}
public class LastNameThenAgeComparer: Comparer<Person>
{
public override int Compare(Person x, Person y)
{
if (x.LastName.CompareTo(y.LastName) != 0)
{
return x.LastName.CompareTo(y.LastName);
}
else (x.Age.CompareTo(y.Age) != 0)
{
return x.Age.CompareTo(y.Age);
}
}
}
//// other types of comparers
Usage:
personList.Sort(new LastNameThenAgeComparer());
LINQ + Extension Methods
class Program
{
static void Main(string[] args)
{
try
{
"inputNames.txt".ReadFileAsLines()
.Select(l => l.Split(','))
.Select(l => new Person
{
vorname = l[0],
nachname = l[1],
age = int.Parse(l[2]),
})
.OrderBy(p => p.age).ThenBy(p => p.nachname)
.WriteAsLinesTo("outputNames.txt");
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
}
}
}
public class Person
{
public string vorname { get; set; }
public string nachname { get; set; }
public int age { get; set; }
public override string ToString()
{
return string.Format("{0} {1}\t{2}", this.vorname, this.nachname, this.age);
}
}
public static class ToolsEx
{
public static IEnumerable<string> ReadFileAsLines(this string filename)
{
using (var reader = new StreamReader(filename))
while (!reader.EndOfStream)
yield return reader.ReadLine();
}
public static void WriteAsLinesTo(this IEnumerable lines, string filename)
{
using (var writer = new StreamWriter(filename))
foreach (var line in lines)
writer.WriteLine(line);
}
}
This is how I would implement such a person class with some comments.
//sort a person object by age first, then by last name
class Person : IComparable<Person>, IComparable
{
public string LastName { get; }
public string FirstName { get; }
public int Age { get; }
public Person(string vorname, string nachname, int age)
{
LastName = vorname;
FirstName = nachname;
Age = age;
}
// used by the default comparer
public int CompareTo(Person p)
{
// make sure comparable being consistent with equality; this will use IEquatable<Person> if implemented on Person hence better than static Equals from object
if (EqualityComparer<Person>.Default.Equals(this, p)) return 0;
if (p == null)
throw new ArgumentNullException(nameof(p), "Cannot compare person with null");
if (Age.CompareTo(p.Age) == 0)
{
return LastName.CompareTo(p.LastName);
}
return Age.CompareTo(p.Age);
}
// explicit implementation for backward compatiability
int IComparable.CompareTo(object obj)
{
Person p = obj as Person;
return CompareTo(p);
}
public override string ToString() => $"{LastName} {FirstName} \t {Age}";
}

Checking if A objects property exist

I was wanted to ask a question cause I can't really find what I'm looking for online. I want to see/check if a student IdNum already exist for example.
I don't know the right term that I'm looking for to google it, and the book I have isn't really that useful as to what to do when needing to do this sort of check.
Here is the code what i have been tried so far :
static void Main(string[] args)
{
Class1[] c1 = new Class1[10]
for (int i = 0; i < c1.Length; i++)
{
Console.WriteLine("enter Student ID");
string text = Console.ReadLine();
int value;
while (!Int32.TryParse(text, out value))
{
Console.WriteLine("ID Was not a Valid ID Number. Try Again");
text = Console.ReadLine();
}
// maybe here say if IdNum exist or not
{
// Try a different number
}
}
}
Class Class1
{
public int IdNum { get; set; }
public int SomethingElse { get; set; }
// and so on
}
Thanks
IEnumerable<Class1> c1 = GetStudents();
string text = Console.ReadLine();
int value;
while (!Int32.TryParse(text, out value))
{
Console.WriteLine("ID Was not a Valid ID Number. Try Again");
text = Console.ReadLine();
}
bool exist = c1.Any(s = > s.IdNum == value);
If you don't want to use linq, you can just rewrite the last line with:
bool exist = false;
foreach (var s in c1)
{
if (s.IdNum == value)
{
exist = true;
break;
}
}

find an object's property and get its value - C#

say there is a class like
class phones
{
public int Id {get; set;}
public string Name {get; set;}
public string Color {get; set;}
public decimal Price {get; set;}
}
List<phones> myList = GetData();
//list is filled with objects
Now, I know the Id and the exact name of the object's property and want to get the value from the matching object.
private string GetValue(int pid, string featurename)
{
string val = "";
foreach(phones obj in myList)
{
if(obj.Id == pid)
{
//if featurename is 'Name', it should be
//val = obj.Name;
//if featurename is 'Price', it should return
//val = obj.Price;
break;
}
}
return val;
}
Is this possible. Please advise.
Use this:
Phones phones= new Phones();
string returnValue = phones.GetType().GetProperty(featureName).GetValue(phones, null).ToString();
Also, remember to add validation for input featureName and error handling.
How about this:
foreach(phones obj in myList)
{
if(obj.Id == pid)
{
if (featurename == "Name")
{
return obj.Name;
}
else if (featurename == "Price")
{
return obj.Price.ToString();
}
else
{
return string.Empty;
}
}
}
I think you want Property with given featurename and use it
you could use lambda expression like this
or
Use PropertyInfo like this
foreach (PropertyInfo p in typeof(ClassName).GetProperties())
{
string propertyName = p.Name;
//....
}

Categories