Possible class function in C# - c#
I have a class created:
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
}
As you can see, it's a very simple class at the moment. My question is, is there a way to create another class inside this so when I call my function I can have a math equation returned?
Example:
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = 15;
MessageBox.Show(c.Str.Mod);
The output to the window would be "7"
(Mod is: Math.Floor(Str / 2);)
I have been trying to search both SO and Google for some time and have yet to figure this out. I may be searching for the wrong phrases or this might not even be possible.
Thanks
only way that I can quickly think is Extension Methods
class Program
{
static void Main(string[] args)
{
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = 15;
Console.WriteLine(c.Str.Mod());
Console.Read();
}
}
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
}
public static class Ext
{
public static int Mod(this int value)
{
return (int)Math.Floor(value / 2.0);
}
}
public class Character // C should be uppercase here.
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public double ModMe()
{
return Math.Floor(this.Str / 2); // Math.Floor returns double
}
}
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = 15;
MessageBox.Show(c.ModMe());
or:
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public int StrMod{
get{
return (int)Math.Floor(Str / 2);
}
}
}
used with:
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = 15;
MessageBox.Show(c.StrMod);
Yes, you can create a method called Mod that will do your math for you. It'd look something like this:
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public double Mod(int stat)
{
return Math.Floor(stat/2);
}
}
Create an interface. Use properties. Use descriptive variable names:
public interface ICharacter
{
public string Name { get; }
public int Strength { get; }
}
Then implement it:
public class Character : ICharacter
{
public string Name { get; private set; }
public int Strength { get; private set; }
public Character(string name, int strength)
{
this.Name = name;
this.Strength = strength;
}
}
Now for your question, you should let one class do one thing. So now you can create and initialize a calculator for a character's damage modifier (or whatever "Mod" means):
public class DamageModifierCalculator
{
public int Calculate(ICharacter character)
{
return (int)Math.Floor(character.Strength / 2);
}
}
Now initialize and call it:
var character = new Character("Goofy", 15);
var calculator = new DamageModifierCalculator();
int mod = calculator.Calculate(character);
It's extensible, it's testable and its concerns are separated. You will want to create an interface for the calculator too, as you'll need more of them, preferably one for each kind of calculation.
Or you can just stick it in your Character class, but then it's got nothing to do with OO anymore.
Rather than using Int fields for your stats (at least for your example), make a Stat class, like so:
public class character
{
public string Name, Owner;
public int AC, Speed, maxHP, currHP, AP, SV, Surges;
public Stat Str { get; set; }
public Stat Con { get; set; }
public Stat Dex { get; set; }
public Stat Int { get; set; }
public Stat Wis { get; set; }
public Stat Cha { get; set; }
public class Stat
{
public Stat(int stat)
{
Value = stat;
}
public int Value { get; set; }
public int Mod { get { /*Calcuate Mod from Value.*/; } }
}
}
And call it like this:
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = new Stat(7);
MessageBox.Show(c.Str.Value); //The Value
MessageBox.Show(c.Str.Mod); //The Mod of Strength
For this operation, you can just do :
int x = (int)15 / 2;
Also, you can create nested class, that is to say, a class inside a class.
For example, you would have inside your class something like :
public class MathOperator
{
public int Mod(int x)
{
return (int)x/2;
}
}
And then, just create an instance of this nested class in your class, and use it on c.Str
If Mod is a operation that could apply to any integer, you could define it as an extension method.
static class ExtendInt
{
static public int Mod(this int stat)
{
return stat / 2;
}
}
class UseExtendedInt
{
void UseIt()
{
int a = 1;
int b = a.Mod();
}
}
If you put ExtendInt inside a unique namespace, you can use that namespace only in the files where you want this to work, but otherwise this will be an available function for all integers in that namespace.
If this needs different operations depending on the variable name, you'll have to somehow incorporate reflection or define an enum that identifies the calculation type to pass into Mod.
In most cases, if the calculation types are different, you're better off defining properties like strMod, conMod, etc...
To use that exact syntax, you would need Str to be a different type. One that can be converted from an int and have a property named Mod:
public class character {
// A type that is convertible from int and has a Mod property
public class Modder {
//private variable to hold the integer value
private int _value;
// private constructor that is used by the converter
private Modder(int value){ _value = value; }
// implicit converter to handle the conversion from int
public static implicit operator Modder(int value) {
return new Modder(value);
}
// Property Mod that does the calculation
public int Mod {
get { return _value / 2; }
}
}
public string Name, Owner;
public int Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public Modder Str;
}
I put that class insde the character class, but it doesn't have to be.
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public int MathFunction(int input)
{
return (int)(input/2);
}
}
now you can use
MessageBox.Show(c.MathFunction(c.Str));
Related
Change variables based on time elapsed
I'm trying to create a program within which the user interacts with a virtual pet. This pet has attributes such as hunger, which is just stored as an integer between 1-10. Is there a way to decrease the value of said variable based on how much time has passed (since the pet was last fed, let's say)? Hopefully i can use it to create a function like this: static void hungerDecrease(CPet pet) { bool needsFeeding = false; // some method of checking if say 4 hours has passed and if so set needsFeeding to be true if (needsFeeding == true) { pet.Hunger -= 1; } } The class CPet looks like this: public class CPet { public string Name; public string Gender; // Attributes belonging to pets, with values being defined upon creation. public int Hunger = 5; public int Boredom = 5; public int Happiness = 5; public int Intelligence = 1; public CPet(string name, string gender) { Name = name; Gender = gender; } }
public class CPet { public string Name; public DateTime LastFed; ... } static void hungerDecrease(CPet pet) { if (DateTime.Now > pet.LastFed.AddHours(4)) { pet.Hunger -= 1; pet.LastFed = DateTime.Now; } }
Using implicit operator overloading
I created the following struct to keep track of all my network IDs I use for my game: public struct NetworkId { private static int _availibleId = 1; private int _id; public static implicit operator int(NetworkId i) { if (i._id == 0) { i._id = _availibleId++; } return i._id; } } I initialize the ID at the moment someone tries to access it. But my problem now is, when I use the id like in the following example, the ID gets reassigned every time. public class TestObject { private NetworkId _id; public NetworkId Id { get { return _id; } } public void Create { NetworkManager.SendPacket(new Packets.CreateObject(Id)); } } I can't wrap my head around what is happening here. Thank you for your help!
Does it need to be a struct? With class semantics do this: public class NetworkId { private static int _availibleId = 1; public int Id { get; } = _availibleId++; public static implicit operator int(NetworkId i) { return i.Id; } } void Test() { int A = new NetworkId(); //A=1 int B = new NetworkId(); //B=2 }
Correctly accessing parameters from a " : Base" constructor
Situation I'm making a small text based game using some OOP practices I learnt this academic year, the reason I'm doing this is to mostly improve the OOP that I currently know and hopefully improve some of my practices with assistance from experienced users. So, in layman terms, I currently have an "Ork" class that's extending "Enemy" and "Enemy" is extending "Entity" public class Ork : Enemy public class Enemy : Entity I have the "Enemy" class because I intend to make many unique enemy object types, not just "Ork", with this current setup I could make "Elf" or "Human" the same way. (and it's much easier to add new types in the future) Enemy has it's own constructor. public Enemy(string[] Droplist, int Defaultgold, string Weaknesses, string Resistances, string[] Taunts, string Aggro, string Critchance, string Threshold, string Name, string Type, string Spawnzone, string _Class, int Defaultlevel, int Maxlevel, string trait, int str, int agi, int dex, int hel, int man) { //make a new entity instance. entity = new Entity(); //Set all the local variables to the passed in parameters. setEntity(Name, Type, Spawnzone, _Class, Defaultlevel, Maxlevel, trait, str, agi, dex, hel, man); droplist = Droplist; defaultgold = Defaultgold; weaknesses = Weaknesses; resistances = Resistances; taunts = Taunts; aggro = Aggro; critchance = Critchance; threshold = Threshold; } As you can see, I set the incoming parameter to the local variable, and I use setEntity which does some of this work for me. I also have an "Entity" class, and the reason for this is, not everything that has "Stats" is an enemy, therefore I have "Entity" as the middleman. Problem The problem is at the end of this line of classes, the Ork Class. In other programs, for instance, my Hillracing program, my constructor for a similar class would look like this: public JuniorMember(string stringfirstname, string stringlastname, string stringmiddlename, string stringtitle, string strst, string strtwn, string strpc, string strEmail, int intMobile, int intHome, string shrnumber, string memtype, string username, string password, int noracesrun, float perraceswon, string mempic, string memclub, string gender, int memexp, int yearofbirth, int monthofbirth, int dayofbirth, string nextofkin, string docName, string docTel, string healthIssues, string parentalConsent) : base(stringfirstname, stringlastname, stringmiddlename, stringtitle, strst, strtwn, strpc, strEmail, intMobile, intHome, shrnumber, memtype, username, password, noracesrun, perraceswon, mempic, memclub, gender, memexp, yearofbirth, monthofbirth, dayofbirth) { So, the problem is, simply put, In this program I'm looking at a similar amount of parameters, and for me, personally, looking at these parameters I don't feel as if I'm doing this correctly. The example I gave from Hillracing works flawlessly, but I'm just wondering if this is the best way to do this, as the parameter list looks messy and it feels as if I'm creating things that have already been previously created. What I mean by this is, 90% of the information I need to create an Ork object comes from elsewhere. Edit Due to comments made, I removed the new Entity I had made in my enemy class, I now have the following Enemy class: public class Enemy : Entity { private string[] droplist; private int defaultgold; private string weaknesses; private string resistances; private string[] taunts; private string aggro; private string critchance; private string threshold; public string[] Droplist { get { return droplist; } set { droplist = value; } } public int Defaultgold { get { return defaultgold; } set { defaultgold = value; } } public string Weaknesses { get { return weaknesses; } set { weaknesses = value; } } public string Resistances { get { return resistances; } set { resistances = value; } } public string[] Taunts { get { return taunts; } set { taunts = value; } } public string Aggro { get { return aggro; } set { aggro = value; } } public string Critchance { get { return critchance; } set { critchance = value; } } public string Threshold { get { return threshold; } set { threshold = value; } } public void setEntity(string EnName, string EnType, string EnSpawnzone, string En_Class, int EnDefaultlevel, int EnMaxlevel, string Entrait, int Enstr, int Enagi, int Endex, int Enhel, int Enman) { setStats(Enstr, Enagi, Endex, Enhel, Enman); Name = EnName; Type = EnType; Spawnzone = EnSpawnzone; _Class = En_Class; Defaultlevel = EnDefaultlevel; Maxlevel = EnMaxlevel; trait = Entrait; } public Enemy(string[] Droplist, int Defaultgold, string Weaknesses, string Resistances, string[] Taunts, string Aggro, string Critchance, string Threshold) :base(Name,Type,Spawnzone,_Class,Defaultlevel,Maxlevel,trait,str,agi,dex,hel,man) { //Set all the local variables to the passed in parameters. setEntity(Name, Type, Spawnzone, _Class, Defaultlevel, Maxlevel, trait, str, agi, dex, hel, man); droplist = Droplist; defaultgold = Defaultgold; weaknesses = Weaknesses; resistances = Resistances; taunts = Taunts; aggro = Aggro; critchance = Critchance; threshold = Threshold; } My issue here is, I don't know how to get the information from Entity at this point, I can't access the Name,Type,Spawnzone,etc,etc variables because they expect an object reference.
Note: I see that you just edited to clarify that your Enemy class extends Entity. Then I'm not understanding why you are instantiating an Entity class inside the Enemy constructor. What is the logical relationship between Entity and Enemy? Is Enemy a type of Entity? Or, does Enemy have an Entity? Perhaps you can consider passing in the Entity instance to the Enemy constructor to avoid having to pass in all the individual components of the Entity class to the Enemy constructor. Something like this: public class Entity { // other code public Entity(string Type, string Spawnzone, string _Class, int Defaultlevel, int Maxlevel, string trait, int str, int agi, int dex, int hel, int man) { // move setEntity code here. } // other code } public class Enemy { // other code public Enemy(string[] Droplist, int Defaultgold, string Weaknesses, string Resistances, string[] Taunts, string Aggro, string Critchance, string Threshold, string Name, Entity entity) { this.entity = entity; droplist = Droplist; defaultgold = Defaultgold; weaknesses = Weaknesses; resistances = Resistances; taunts = Taunts; aggro = Aggro; critchance = Critchance; threshold = Threshold; } // other code }
Entity should be a base class that Enemy extends (with the additional stats that not all entities have). From Enemy's constructor you should call the parent Entity constructor. This makes sense because Enemy "is a(n)" Entity. Whereas, currently, your setup is such that Enemy "has a(n)" Entity, which doesn't make sense. Edit You have this already: public class Ork : Enemy I'm saying, you also need to have this: public class Enemy : Entity And C# I think class base class constructors automatically, so you don't have to do anything else. Just do everything common to all Entitys in the Entity constructor, Enemys in Enemy, and so forth.
I assume that your Enemy class is containing an instance of Entity. Which is a wrong practice in your case. And if your Enemy class is extended by Entity then you can use its constructor to set generic values to parent class. Just like you have done it in HillRacing program. (Make sure your Enemy class does not have a member of Entity Type. if it is base of Enemy ) public class Entity { public string Type; public string Spawnzone; public string _Class; public string Defaultlevel; public string Maxlevel; public string Trait; public string str; public string agi; public string dex; public string hel; public string man; public Entity(string Type, string Spawnzone, string _Class, int Defaultlevel, int Maxlevel, string trait, int str, int agi, int dex, int hel, int man) { this.Type = Type; this.Spawnzone = Spawnzone; this._Class = _Class; this.Defaultlevel = Defaultlevel; this.Maxlevel = Maxlevel; this.Trait = trait; this.str = str; this.agi = agi; this.dex = dex; this.hel = hel; this.man = man; } } public class Enemy { public string[] droplist;; public int defaultgold; public string weaknesses; public string resistances; public string[] taunts; public string aggro; public string critchance; public string threshold; public Enemy(string[] Droplist, int Defaultgold, string Weaknesses, string Resistances, string[] Taunts, string Aggro, string Critchance, string Threshold, string Name, string Type, string Spawnzone, string _Class, int Defaultlevel, int Maxlevel, string trait, int str, int agi, int dex, int hel, int man ) : base(Type, Spawnzone, _Class, Defaultlevel, Maxlevel, trait, str, agi, dex, hel, man) { droplist = Droplist; defaultgold = Defaultgold; weaknesses = Weaknesses; resistances = Resistances; taunts = Taunts; aggro = Aggro; critchance = Critchance; threshold = Threshold; } }
C# Immutable Classes and Gaming Objects
I was doing some reading here about creating immutable object in java and I was wondering, is it okay to create a mutable object in certain situations? For example, let's say we were creating a ping-pong game in C#, obviously, we would have a class that represents a ball, and the two paddles, would you write the ball class like this: class Ball { private readonly int xPosition; private readonly int yPosition; private readonly int ballSize; private readonly string ballColor; public Ball(int x, int y, int size, string color) { this.xPosition=x; this.yPosition=y; this.ballSize = size; this.ballColor = color; } public int getX { get { return this.xPosition; } } //left out rest of implementation. or like this: class Ball { private int xPosition; private int yPosition; private int ballSize; private string ballColor; public Ball(int x, int y, int size, string color) { this.xPosition=x; this.yPosition=y; this.ballSize = size; this.ballColor = color; } public int getX { get { return this.xPosition; } set { this.xPosition = value; } } } } In a situation where our object(ball) can change position, size(smaller or larger depending on level) and color, wouldn't it be better to provide a setter property? In this case making it mutable makes sense? How would you approach this?
If you are using c#, you do not need to go thru the overhead of creating separate fields to make objects immutable. Instead you can do something like this - class Ball { public Ball ( int x, int y, int size, string color) { ... } public int XPos {get; private set; } public int YPos {get; private set; } public int Size {get; private set; } public string BallColor {get; private set; } } This way, you can still write methods in the class to mutate the properties but nothing outside of the class can change their values.
How to store multiple database columns into an array with Linq2Sql
I have to work with multiple SQL Server tables that generally look like this: int id_this, int id_that, ..., double Value1, double Value2, ..., double Value96 I know this sucks, but I can't change it. What I want to do now is to define some class like public class Foo { public int Id_This { get; set; } public int Id_That { get; set; } ... public double Value[]; } The Value-Array being a property of course, but I think you get the idea. The question is, how to get the 96 columns into the array as painlessly as possible. I could do that with a plain SqlDataReader, since DataRow allows indexed access, but I wonder if I could declare some attributes or write some minimum amount of code to use the class directly with LINQ2SQL. As a minimum, I would like to do dataContext.ExecuteQuery<Foo>("SELECT * FROM Foo");
Ooh, that is... nice? The DataContext methods always expect an entity type; there is no ExecuteReader, which is a pain (but understandable, as it wants to behave as an ORM). To be honest, I would be tempted to use ADO.NET for the guts against this table, but if you have mapped the wide table to the DataContext you should be able to use either regular C# or reflection. Since the number doesn't change, unless you have multiple tables I'd just bite the bullet and write some ugly code: Foo foo = new Foo { Id_This = obj.Id_This, Id_That = obj.Id_That, Values = new double[] {obj.Value1, obj.Value2, ... } }; If you have multiple tables... reflection, perhaps optimised via Expression: using System; using System.Collections.Generic; using System.Linq.Expressions; class FooUgly { public int IdThis { get; set; } public int IdThat { get; set; } public double Value1 { get; set; } public double Value2 { get; set; } public double Value3 { get; set; } } class Foo { public int IdThis { get; set; } public int IdThat { get; set; } public double[] Values { get; set; } public Foo() { } internal Foo(FooUgly ugly) { IdThis = ugly.IdThis; IdThat = ugly.IdThat; Values = extractor(ugly); } // re-use this!!! static readonly Func<FooUgly, double[]> extractor = ValueExtractor<FooUgly, double>.Create("Value", 1, 3); } static class Program { static void Main() { FooUgly ugly = new FooUgly { IdThis = 1, IdThat = 2, Value1 = 3, Value2 = 4, Value3 = 5 }; Foo foo = new Foo(ugly); } } static class ValueExtractor<TFrom,TValue> { public static Func<TFrom, TValue[]> Create(string memberPrefix, int start, int end) { if(end < start) throw new ArgumentOutOfRangeException(); ParameterExpression param = Expression.Parameter(typeof(TFrom), "source"); List<Expression> vals = new List<Expression>(); for(int i = start ; i <= end ; i++) { vals.Add(Expression.PropertyOrField(param, memberPrefix + i)); } Expression arr = Expression.NewArrayInit(typeof(TValue), vals); return Expression.Lambda<Func<TFrom, TValue[]>>(arr, param).Compile(); } }