I am new to C# and the .Net framework and struggling to understand how to do something. Do I lean on Inheritance for something like this?
When the variable allDim is true, I want all class instances to return 0 for their dimPercent.
public class Program
{
//if this is true, all rooms should return 0
public bool allDim = false;
public class Room
{
//0 is lights out. 100 is as bright as possible
public Room(int dimPercent)
{
DimPercent = dimPercent;
}
private int dimPercent;
public int DimPercent
{
get
{
if (Program.allDim)
{
//if allDim is true, all lights should be dimmed to 0 percent
return 0;
}
else
{
return dimPercent;
}
}
set
{
dimPercent = value;
}
}
}
public static void Main()
{
Room livingRoom = new Room(80);
Room kitchen = new Room(85);
Room bedroom = new Room(65);
allDim = true;
// This should return 0 since allDim was set to true
Console.WriteLine(kitchen.DimPercent);
}
}
Creating a base class that holds allDim and allowing the Room class to be derived from this new base class did not feel right to me since allDim is technically not a property of each class instance. Apologies if I butchered some of the terminology.
If you make allDim into a private static field then you would easily achieve what you want. However from the point of responsibility, you should ask yourself if any of the room instances should be able to affect other rooms?
public class Room
{
private static bool allDim = false;
// I am not sure if we should make this into a static method
public void SetAllDim(bool isAllDim){
allDim = isAllDim;
}
...
}
Convert your boolean into a Static Member of the class.
public static bool allDim = false;
Related
Okay so I am working on a project that haves a abstract public abstract bool IsFull { get; } this is how the school wants me to set it up. I was trying to figure out a work around that but I can't. I have a few files not sure if I want them all to post. so in my class it is inherited from a different class. so when I initiate it from the program cs class I can't get the boolean to change with a simple IsFull = true. I tried IsFull.Equal(true); but read that just a comparison attribute. I will show my code. Remember this is 100% new to me so if you asked questions why don't i do it this way the answer is I never was taught that lol.
So is there a way I can override it within the sweettooth class?
My Ninja class
using System.Collections.Generic;
using IronNinja.Interfaces;
namespace IronNinja.Models
{
abstract class Ninja
{
protected int calorieIntake;
public List<IConsumable> ConsumptionHistory;
public Ninja()
{
calorieIntake = 0;
ConsumptionHistory = new List<IConsumable>();
}
public abstract bool IsFull { get; }
public abstract void Consume(IConsumable item);
}
}
my inherited class sweettooth
using IronNinja.Interfaces;
namespace IronNinja.Models
{
class SweetTooth : Ninja
{
public string Name;
public SweetTooth(string name)
{
Name = name;
}
public override bool IsFull { get; }
public override void Consume(IConsumable item)
{
// provide override for Consume
int sweet = 0;
if (calorieIntake >= 1500)
{
}
else
{
if (item.IsSweet)
{
sweet = 10;
}
ConsumptionHistory.Add(item);
calorieIntake += item.Calories + sweet;
}
item.GetInfo();
}
}
}
Lastly my Programs .cs file
using System;
using IronNinja.Models;
namespace IronNinja
{
class Program
{
static void Main(string[] args)
{
Buffet hungryJack = new Buffet();
SweetTooth Albert = new SweetTooth("Alby");
while (!Albert.IsFull)
{
Albert.Consume(hungryJack.Serve());
}
foreach (Food item in Albert.ConsumptionHistory)
{
Console.WriteLine(item.Name);
System.Console.WriteLine(item.GetInfo());
}
}
}
}
From my understanding, the IsFull property can simply provide the logic to return whether or not the SweetTooth is full:
public override bool IsFull => calorieIntake >= 1500;
And then in SweetTooth.Consume you would check if they are full before consuming more consumables:
public override void Consume(IConsumable item)
{
// provide override for Consume
int sweet = 0;
if (IsFull)
{
return;
}
else
{
if (item.IsSweet)
{
sweet = 10;
}
ConsumptionHistory.Add(item);
calorieIntake += item.Calories + sweet;
}
item.GetInfo();
}
You simply can't, by language design. You can't make your subclass "more permissive" than the parent class.
If you want to assign IsFull property, you have to do it into the SweetTooth class through the constructor. Generally if you set a property with private setter is because you want to manage its state internally and do not let the client code to handle it.
Then, change the SweetTooth constructor as per below:
public SweetTooth(string name, bool isFull)
{
Name = name;
IsFull = isFull;
}
The alternative is to add a private backing field, but again you can edit this only internally:
private bool _isFull;
public override bool IsFull => _isFull;
The Equal method compares two values. In your specific case you called bool.Equals(bool) overload which worked as Albert.IsFull == true
I am working on a C# game that will have predefined levels. I am trying to have a class that will hold the predefined data of all of the levels. Here's what I'm trying to do:
public static GameLevel startLevel = new Level() {
startLevel.Actions.Add(action);
startLevel.Actions.Add(action);
}
And so on. However, it seems that C# does not want me to initialize this way. How can I achieve my desired effect without throwing it into a massive constructor?
How do you think if we change the static variable as below:
private static GameLevel _startLevel;
public static GameLevel StartLevel
{
get
{
if(_startLevel == null)
{
_startLevel = new Level();
_startLevel.Action.Add(action1);
_startLevel.Action.Add(action2);
}
return _startLevel;
}
}
Since you have predefined levels, I suggest a little different approach.
Create a Level base class, and a class for each Level. The constructor for each level class can set up the Actions and any other things the game needs to know how to display itself.
using System;
public class Program
{
public static void Main()
{
new GameState(new Level1());
Console.WriteLine("Current level is " + GameState.CurrentLevel.Name);
Console.WriteLine("User leveled up");
GameState.CurrentLevel = new Level2();
Console.WriteLine("Current level is " + GameState.CurrentLevel.Name);
}
}
public class Level
{
public string Name;
// public static IEnumerable<Action> Actions { get; set; }
}
public class Level1 : Level
{
public Level1()
{
// level 1 init
Name = "1";
// Actions = new List<Action> { ... }
}
}
public class Level2 : Level
{
public Level2()
{
// level 2 init
Name = "2";
}
}
public class GameState
{
public static Level CurrentLevel { get; set; }
public GameState(Level startLevel)
{
CurrentLevel = startLevel;
}
}
Working copy: https://dotnetfiddle.net/qMxUbw
"...C# does not want me to initialize this way..."
You can init this way. You simply don't have the right syntax. This should work
public static Level startLevel = new Level()
{
Actions = new List<Action>()
{
new Action() {...},
new Action() {...}
},
OtherProprty = "Other"
};
NOTE: this has to be done under class scope
"Massive constructor" - you usually don't init static members in constructor unless this is static constructor. Sounds like you need to use Singleton pattern for this piece. Then again, you call all the needed code in constructor, "massive" or not. Break it into methods.
I'm making a game using Monogame, and I've been trying to figure out how to implement a function that acts similarly to AS3's and GML's with statement.
So far I have a system that works, but not entirely the way I want it to. I store my GameObjects in a Dictionary of Lists. This is so I can get to the specific type of object I want to access without having to loop through a list of ALL objects. The key used is the name of the type.
public static Dictionary<string, List<GameObject>> All =
new Dictionary<string, List<GameObject>>();
I access all of a specific type of object using AllOf. If a List containing that type exists in the Dictionary, it returns that List, else it returns an empty list.
public static List<GameObject> AllOf(Type type)
{
string key = type.Name;
if(All.ContainsKey(key))
{
return All[key];
}
return new List<GameObject>();
}
An example of how these are implemented
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
}
}
But I'd rather use something similar to the AS3/GML with statement, which would also allow for other, non-member codes to be executed.
with(typeof(Dummy))
{
Update(gameTime);
foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
Is there a way to accomplish this? My end goal is just to make my code look a little cleaner, and make it easier to make a lot of changes without having to type out a for loop each time.
No such syntax exists in C#, but you can access methods within the for that have nothing to do with the collection:
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
}
Note that you can also use foreach, which is a little cleaner if you don't need the indexer:
foreach(var item in list)
{
item.Update(gameTime);
item.foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
try
using(Object myObject = new Object()){
}
i think this might be what your looking to use?
I have a small solution for this use case. This may be a bit of a necropost, but it is a pretty neat solution. Additionally, I think all of the C# features that are required existed back when this question was asked.
You can do something very similar to the GML with(x){} by using some form of delegate as a parameter to a static method, and passing a lambda as that parameter. The function can even be genericised, and you can call it without the class name by the using static statement. You will need to explicitly provide the typed/named parameter, but it is possible. You would need to hook it up to your own types, but the general idea is:
namespace NiftyStuff {
public static class With {
public static void with<T>(Action<T> proc) where T : GameObj {
var typeName = typeof(T).Name;
foreach (var item in GameObj.AllOf(typeName)) { proc((T)item); }
}
}
public class GameObj {
private static Dictionary<string, List<GameObj>> All = new Dictionary<string, List<GameObj>>();
public static List<GameObj> AllOf(string name) {
return All.ContainsKey(name) ? All[name] : null;
}
public static void Add(GameObj foo) {
string typeName = foo.GetType().Name;
List<GameObj> foos = All.ContainsKey(typeName) ? All[typeName] : (All[typeName] = new List<GameObj>());
foos.Add(foo);
}
public float x, y, angle;
public GameObj() { x = y = angle = 0; }
public void Destroy() { AllOf(GetType().Name)?.Remove(this); }
}
public class Enemy : GameObj {
public float maxHealth, curHealth;
public Enemy() : base() { maxHealth = curHealth = 300; }
public Enemy(float health) : base() { maxHealth = curHealth = health; }
public bool Damage(float amt) {
if (curHealth > 0) {
curHealth -= amt;
return curHealth <= 0;
}
return false;
}
}
public class Pumpkin : GameObj {
public bool exists = false;
public Pumpkin() : base() { exists = true; }
public bool LookAt() { return (exists = !exists); }
}
}
Actually using the above code would work as follows:
using NiftyStuff;
using static NiftyStuff.With;
//...
with ((Enemy e) => {
if (e.Damage(50)) {
Log("Made a kill!"); // Whatever log function you have...
}
});
with ((Pumpkin p) => {
if (p.LookAt()) {
Log("You see the pumpkin");
} else {
Log("You no longer see the pumpkin");
}
});
While not exactly like GML's with statement, it would at least let you run code against all of the registered objects of some type.
One important note is that you can't destroy objects inside of a with this way (due to concurrent modification of a collection while iterating it). You would need to collect all objects to be destroyed, and then remove them from the list in All, typically in a game loop this is done at the end of a frame.
Hope this helps, despite being 2 years out of date.
I have something like this:
public class Ship
{
public void PositionX_pixels_set1(float _position_x){position_x = _position_x;}
public class Engine : Ship
{
public int engines() { return 5; }
public class Piston
{
public int pistons(){return 5;}
}
}
}
void Main
{
Ship ship = new Ship()
int a = ship.Engine.Piston.pistons;//why this not working?
}
I don't know what I'm doing wrong. Why isn't "ship.Engine.Piston.pistons" working?
Because Engine is type inside the Ship class, and its member.
To fix this can do something like:
public class Ship
{
public void PositionX_pixels_set1(float _position_x){position_x = _position_x;}
private void Engine _myEngine = new Engine(); //DEFINE ENGINE MEMBER
public Engine MyEngine { //DEFINE A PROPERTY TO ACCESS THAT MEMBER
get {
return _myEngine;
}
}
public class Engine : Ship
{
public int engines() { return 5; }
private Piston _myPiston = new Piston();//DEFINE PISTON MEMBER
public Piston MyPiston {//DEFINE A PROPERTY TO ACCESS THAT
get {
return _myPiston ;
}
}
public class Piston
{
public int pistons(){return 5;}
}
MEMBER
}
}
and after use it like:
int a = ship.MyEngine.MyPiston.pistons
You must initiate an object of your sub type (Nested type) in order to access its method, in your case you are not creating any object of your nested types so you can not access its methode.
While you create a new Ship() you are not creating any Engine or Piston, so you can not access the methode Pistons() of the non existing object.
Hi I'm new to OOP and I need help on a little problem.
I used a collection called Monsters to store 3 types of object. Spiders, Farmers, Gollum(irrelevant).
My collection as an indexer but when I use it to get an object out of the collection the object is typeless but I really need to TypeCast my next opperation.
private void Form1_Load(object sender, EventArgs e)
{
CurrentOpponent Opponent = new CurrentOpponent();
Gollum myGollum = new Gollum();
AngryFarmer myFarmer = new AngryFarmer();
Ugly_Spider mySpider = new Ugly_Spider();
myMonsters.AddGollum(myGollum);
myMonsters.AddFarmer(myFarmer);
myMonsters.AddUgly(mySpider);
progressBar1.Increment(100);
progressBar2.Increment(100);
Monster myCurrentOpponent = Opponent.randomEncounter();
//textBox1.Text = (this is where i need the type for a cast)myCurrentOpponent.name
}
Here is the randomEncounter where i extract the object
class CurrentOpponent
{
public Monster randomEncounter()
{
Random _random = new Random();
int opp = _random.Next(4);
return myMonsters[opp];
}
And finally the indexer wich returns a monster (parent of all 3 monster types)
public Monster this[int xxx]
{
get
{
return (Monster)List[xxx];
}
}
Help would be really appreciated..!!
Thanks in advance
Ideally, AngryFarmer, Ugly_Spider and Gollum should all inherit from Monster:
public class AngryFarmer : Monster
{
// ...
}
// etc.
You could then just use a List<Monster>:
myMonsters = new List<Monster>();
myMonsters.Add(new AngryFarmer()); // works because AngryFarmer is a kind of Monster
This will allow you to use polymorphism.
you need to use interfaces...... IMonster..... IMonster then has a name
then make all your monsters implement IMonster
and just have a List of IMonsters
you may wanna try it by using interfaces also! have a look...
public interface IMonster
{
String Name { get; }
Int32 Health { get; set; }
}
public class Spider : IMonster
{
public Spider()
{
_health = 100;
}
public string Name
{
get { return "Spider"; }
}
private int _health;
public int Health
{
get { return _health; }
set { _health = value; }
}
}
public class Gollum : IMonster
{
public Gollum()
{
_health = 250;
}
public string Name
{
get { return "Gollum"; }
}
private int _health;
public int Health
{
get { return _health; }
set { _health = value; }
}
}
class Program
{
static void Main(string[] args)
{
List<IMonster> monsters = new List<IMonster>()
{
new Gollum(),
new Spider()
};
IMonster randomMonster = GetRandomMonster(monsters);
Console.WriteLine(randomMonster.Name + "/" + randomMonster.Health);
}
private static IMonster GetRandomMonster(List<IMonster> monsters)
{
//Your code for getting a random monster goes here!
throw new NotImplementedException();
}
}
I like very much this approach... Imagine you have an element on your game that initially is not exactly a monster. Say it is a random element on your game that after a given event it becomes a monster that your Hero (say a game like heroes of mighty and magic) have to fight with. If you decided to add this feature long time after you created the game, it would become harmful/difficult/risky to change it, as this element might have already be inheriting from another class. If you were using interfaces you would simply implement it on this entity and it would promptly be capable of behaving like any other IMonster in your game. It means that this random entity would be able to be passed as a param to the method Fight(IHero hero, IMonster monster);
Ideally, AngryFarmer, Ugly_Spider and Gollum should all inherit
from Monster
I have learn your problem like the problem in the Tetris game:
1/ You have Monsters like I have Shapes.
2/ Each kind of Monster have it own properties (Health, Magic Point,...) and behaviours (attack, run, cast spell,..) like the Blocks have properties (color, position, state,..) and
behaviours (go down, rotate right, rotate left,...)
In the scene of the game you want to random a Monster that have the specific properties and behaviours, like I want to random a Shape. If it is your problem you can try my code:
public abstract class CMonster
{
int _HP;
int _MP;
//..and something like this
public int HP
{
get { return this._HP; }
set { this._HP=value;}
}
public int MP
{
get { return this._MP; }
set { this._MP = value; }
}
public abstract void Run();
public abstract void Attach();
public abstract void CastSpell();
}
public class CUgly_Spider : CMonster
{
public CUgly_Spider()
{
this.MP = 100;//your value here
this.HP = 100;//your value here
}
public override void Attach()
{
//your implemetation here
}
public override void Run()
{
//your implemetation here
}
public override void CastSpell()
{
//your implemetation here
}
}
public class CGollum : CMonster
{
public CGollum()
{
this.MP = 100;//your value here
this.HP = 100;//your value here
}
public override void Attach()
{
//your implemetation here
}
public override void Run()
{
//your implemetation here
}
public override void CastSpell()
{
//your implemetation here
}
}
class Test
{
private void InitTheGame()
{
CMonster curMonster=null;
Random rnd = new Random();
//sample random
if ((rnd.Next() % 2) == 0)
{
curMonster = new CGollum();
}
else
{
curMonster = new CUgly_Spider();
}
curMonster.Run();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
curMonster.Attach();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
curMonster.CastSpell();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
}
}
I hope that can help you.