C
C#β€’3mo ago
Shrow

Can't assign a method to a list, is there a way to get a list to execute code?

So in this turn based video game I'm trying to develop, thanks to some help from users on this discord earlier, the characters can now be selected and so can the Monsters. My new roadblock now is I want to change the selection menu in the game from a switch statement to a similar selection I have going with hero and monster selection, this will make it so that the command list can be any size I want, where as a switch statement is fixed and hardcoded. Unfortunately I can't wrap my head around trying to put the options from the switch cases into a list. A list only accepts Int's and strings, not methods. So it can't execute code. I'm not sure if I can assign an int nor string to a method either. First image is a visual representation of what I want it to do on a whiteboard, second image is the method, third is the hero selection, fourth is the skills class and the fifth is what the switch statement looks like that I'd like to switch into a foreach. As far as I'm aware array's can't execute methods either so I can't just make it an array instead. Also I'm currently assigning the skills to each character via a set of int's (though it could be strings too). Then I will have the computer read each number to determine if the character has that skill or not. So first number determines if they can attack, next number is defending, third is dodging, etc... This doesn't seem like a good way to do it but I can't think of a better way to assign skills to each hero.
No description
No description
No description
No description
No description
71 Replies
Jimmacle
Jimmacleβ€’3mo ago
you can assign methods to a list/array/variables in general using delegates delegate typed variables can hold any method with a matching signature you don't necessarily need delegates either, you can accomplish something similar with OOP
Shrow
ShrowOPβ€’3mo ago
Thank you for taking the time to help. OOP means object oriented programming right? How would I accomplish this task using that?
Jimmacle
Jimmacleβ€’3mo ago
you could have an object hierarchy that represents the actions you want to do like
public interface IAction
{
string Name { get; }
void Do(Player target);
}

public class DamageAction : IAction
{
public string Name => "Damage";
public void Do(Player target) => target.Hp--;
}

public class HealAction : IAction
{
public string Name => "Heal";
public void Do(Player target) => target.Hp++;
}
public interface IAction
{
string Name { get; }
void Do(Player target);
}

public class DamageAction : IAction
{
public string Name => "Damage";
public void Do(Player target) => target.Hp--;
}

public class HealAction : IAction
{
public string Name => "Heal";
public void Do(Player target) => target.Hp++;
}
then code like
var actions = new List<IAction>
{
new DamageAction(),
new HealAction()
};

foreach (var action in actions)
Console.WriteLine(action.Name);

var choice = int.Parse(Console.ReadLine());
actions[choice].Do(player);
var actions = new List<IAction>
{
new DamageAction(),
new HealAction()
};

foreach (var action in actions)
Console.WriteLine(action.Name);

var choice = int.Parse(Console.ReadLine());
actions[choice].Do(player);
as a rough example you'll have to reorganize your code so the menu system doesn't need to know details of the actions like how to figure out how much damage to do, etc.
Moonlit
Moonlitβ€’3mo ago
You could actually have certain things on the objects you want to modify though and then make the do 2nd param the value. So you could maybe put a method on the player like AdjustHealth(int amount) and then inside of DamageAction you can do target.AdjustHealth(-value); or in HealAction target.AdjustHealth(value); I think it'd be a lot easier to make the IAction more universal that way? You can add things like equipping armour, picking up and etc inside of the IAction do then.
Shrow
ShrowOPβ€’3mo ago
thank you! I don’t fully understand this yet but I will look into each line and il see if I can use it.
Jimmacle
Jimmacleβ€’3mo ago
yeah, depends how composable it needs to be really i would imagine that eventually different heroes would have different abilities so you wouldn't want to hardcode them in the hero class
Moonlit
Moonlitβ€’3mo ago
Is there a specific part that you'd like more understanding of?
Shrow
ShrowOPβ€’3mo ago
Thank you for taking the time to reply. Yeah I just need to wrap my head around what each line is doing. Like I need to look up again how interfaces work. the "void Do(Player target);" line, I need to figure out what's that's doing. Then from there figure out what everything else means. I'm still new to code so It's very tough
Moonlit
Moonlitβ€’3mo ago
If it helps. The reason you can't put a class into a list directly is because variables need to be the same type, when code is compiled it needs to know what things are. Even though they are classes, each class is it's own type really A class that doesn't inherit could be anything and your code has no idea what it is expected to do with it. Like if you put 3 classes in, 1 might have Damage(), 1 might have Heal(), 1 might have Eat() and it wouldn't know So see it this way... When you call things, your code needs to know what it's calling, it doesn't "Assume" So when you use an interface you are telling it exactly what is going in there. Because "IAction" has the "Do()" method, it knows that whenever you access that list, it will have a "Do()" because it is "IAction" You're basically guranteeing that list will be filled with IActions
public interface IAction
{
string Name { get; }
void Do(Player target);
}
public interface IAction
{
string Name { get; }
void Do(Player target);
}
So when you add "IAction" to anything, that class will contain everything IAction has! So your DamageAction has "Name" and it has "Do" same as HealAction. So whenever you get it from a list, your code knows it has a ".Do" does that make sense? I probably explained that really badly sorry πŸ˜…
Shrow
ShrowOPβ€’3mo ago
Yes, so how do i add IAction to a list?
Moonlit
Moonlitβ€’3mo ago
You just add the method that inherits "IAction", it'll do it for you But you can only call "IAction" things from the list
Shrow
ShrowOPβ€’3mo ago
So when I type a method like static int IncreaseMethod(int x, int y) { int z = x += y; Console.WriteLine($"Power increased to " + x); return z; } Where would I add IAction to that?
Moonlit
Moonlitβ€’3mo ago
EG you can have
public interface IAction
{
string Name { get; }
void Do(Player target);
}

public class DamageAction : IAction
{
public string Name => "Damage";
public void Do(Player target) => target.Hp--;

public void ExtraFunction(){};
}
public interface IAction
{
string Name { get; }
void Do(Player target);
}

public class DamageAction : IAction
{
public string Name => "Damage";
public void Do(Player target) => target.Hp--;

public void ExtraFunction(){};
}
On your list you can call the DamageAction.Do or DamageAction.Name, but you can't call ExtraFunction() from the list because it doesn't know it exists
Shrow
ShrowOPβ€’3mo ago
What's ExtraFunction?
Moonlit
Moonlitβ€’3mo ago
You'd need to make it a class and inherit from IAction by adding : IAction then put what you want to do inside of a "Do" method but you'd need to pass in the player Nothing, it's just an example that if you add other things inside of a class that inherits from IAction, the list won't have access to anything that isn't part of IAction
Shrow
ShrowOPβ€’3mo ago
public class Skills : IAction { public string Name { get; set; } public string Desc { get; set; } public string Method { get; set; } public Skills(string name, string desc, string metho) { Name = name; Desc = desc; Method = metho; } } Okay so a class like this then right?
Moonlit
Moonlitβ€’3mo ago
Not quite You don't actually use "IAction" in it Let me show you some simplified code to just show a bit of how Interfaces work!
public class Player
{
public int Hunger { get; set; }
public int Money { get; set; }
}

public interface IEdible
{
void Eat(Player player);
}

public interface ISellable
{
void Sell(Player player);
}

public class Apple : IEdible, ISellable
{
public void Eat(Player player)
{
player.Hunger += 10;
}

public void Sell(Player player)
{
player.Money += 6;
}
}

public class Program
{
public static void Main()
{
Player player = new Player { Hunger = 0, Money = 0 };
Apple apple = new Apple();

// Storing apple as IEdible
IEdible edibleApple = apple;
// We can use .Eat because we know that IEdible has it!
edibleApple.Eat(player);
// Next line would fail... Sell isn't inside of IEdible
// edibleApple.Sell(player)
Console.WriteLine($"Player's hunger after eating: {player.Hunger}");

// Storing apple as ISellable
ISellable sellableApple = apple;
sellableApple.Sell(player);
// We can't use sellableApple.Eat because it's not in ISellable
Console.WriteLine($"Player's money after selling: {player.Money}");
}
}
public class Player
{
public int Hunger { get; set; }
public int Money { get; set; }
}

public interface IEdible
{
void Eat(Player player);
}

public interface ISellable
{
void Sell(Player player);
}

public class Apple : IEdible, ISellable
{
public void Eat(Player player)
{
player.Hunger += 10;
}

public void Sell(Player player)
{
player.Money += 6;
}
}

public class Program
{
public static void Main()
{
Player player = new Player { Hunger = 0, Money = 0 };
Apple apple = new Apple();

// Storing apple as IEdible
IEdible edibleApple = apple;
// We can use .Eat because we know that IEdible has it!
edibleApple.Eat(player);
// Next line would fail... Sell isn't inside of IEdible
// edibleApple.Sell(player)
Console.WriteLine($"Player's hunger after eating: {player.Hunger}");

// Storing apple as ISellable
ISellable sellableApple = apple;
sellableApple.Sell(player);
// We can't use sellableApple.Eat because it's not in ISellable
Console.WriteLine($"Player's money after selling: {player.Money}");
}
}
You see how because Apple : ISellable contains ISellable that we know it can be sold? Because it is an ISellable
Shrow
ShrowOPβ€’3mo ago
I think I'm starting to get it thank you!
Moonlit
Moonlitβ€’3mo ago
brilliant! So if you make something an "IAction" you can only call things from it that are inside of IAction if that is what you are storing it as So I could make a list of "ISellables" or a list of "IEdibles" And I could add different fruit to them! Even if some are different You might have a golden apple! That would be ISellable but not IEdible
// This can't be eaten!
public class GoldenApple : ISellable
{
public void Sell(Player player)
{
player.Money += 6;
}
}
// This can't be eaten!
public class GoldenApple : ISellable
{
public void Sell(Player player)
{
player.Money += 6;
}
}
Shrow
ShrowOPβ€’3mo ago
I see it now, I would make skills as IAction(s) then what each skills does would go under different type of interfaces like damage, healing etc... Say in that example could all the apples go under a list too so they can be used in a foreach?
Moonlit
Moonlitβ€’3mo ago
Yes sec
Shrow
ShrowOPβ€’3mo ago
ok
Moonlit
Moonlitβ€’3mo ago
public class Player
{
public int Hunger { get; set; }
public int Money { get; set; }
}

public interface IEdible
{
int Nutrition { get; }
void Eat(Player player);
}

public interface ISellable
{
int Value { get; }
void Sell(Player player);
}

public class Fruit : IEdible, ISellable
{
public string Name { get; }
public int Nutrition { get; }
public int Value { get; }

public Fruit(string name, int nutrition, int value)
{
Name = name;
Nutrition = nutrition;
Value = value;
}

public void Eat(Player player)
{
player.Hunger += Nutrition;
}

public void Sell(Player player)
{
player.Money += Value;
}
}

public class Program
{
public static void Main()
{
Player player = new Player { Hunger = 0, Money = 0 };

List<Fruit> fruits = new List<Fruit>
{
new Fruit("Apple", 10, 6),
new Fruit("Banana", 8, 4)
};

foreach (var fruit in fruits)
{
Console.WriteLine($"Fruit: {fruit.Name}, Nutrition: {fruit.Nutrition}, Value: {fruit.Value}");
}
}
}
public class Player
{
public int Hunger { get; set; }
public int Money { get; set; }
}

public interface IEdible
{
int Nutrition { get; }
void Eat(Player player);
}

public interface ISellable
{
int Value { get; }
void Sell(Player player);
}

public class Fruit : IEdible, ISellable
{
public string Name { get; }
public int Nutrition { get; }
public int Value { get; }

public Fruit(string name, int nutrition, int value)
{
Name = name;
Nutrition = nutrition;
Value = value;
}

public void Eat(Player player)
{
player.Hunger += Nutrition;
}

public void Sell(Player player)
{
player.Money += Value;
}
}

public class Program
{
public static void Main()
{
Player player = new Player { Hunger = 0, Money = 0 };

List<Fruit> fruits = new List<Fruit>
{
new Fruit("Apple", 10, 6),
new Fruit("Banana", 8, 4)
};

foreach (var fruit in fruits)
{
Console.WriteLine($"Fruit: {fruit.Name}, Nutrition: {fruit.Nutrition}, Value: {fruit.Value}");
}
}
}
Shrow
ShrowOPβ€’3mo ago
Good! That way they can be printed out and the player can choose which they'd like to eat. Perfect!
Moonlit
Moonlitβ€’3mo ago
Yeh but generally I just wanted to give you a better understanding of Interfaces
Shrow
ShrowOPβ€’3mo ago
I thank you for that! I do understand them much more now.
Moonlit
Moonlitβ€’3mo ago
We know that Fruit can be eaten because it's IEdible. We know Fruit can be sold because they are ISellable
private static List<Fruit> fruits = new List<Fruit>();

Public static void Main(){
fruits.Add(new Fruit("Kiwi", 6, 3);
}
private static List<Fruit> fruits = new List<Fruit>();

Public static void Main(){
fruits.Add(new Fruit("Kiwi", 6, 3);
}
I'm glad! You should go back to what Jimmacle suggested and give it another read Good luck πŸ™‚
Shrow
ShrowOPβ€’3mo ago
I will! Thank you so much! πŸ₯°
Moonlit
Moonlitβ€’3mo ago
Also I read back and noticed I kept saying "Method" instead of "Class" my bad πŸ˜… I've edited to correct them! Brain derp Btw I suggest we use generics for your Abilities Ever heard of Generics? It can pair really well with Interfaces
Shrow
ShrowOPβ€’3mo ago
I'm back I can't think of what Generics are atm I probably read about them then forgot. I'm all ears on your suggestion
Moonlit
Moonlitβ€’3mo ago
So Generics goes a bit against what I just told you... So try not to get confused Generics is when we pass a type into something but it's not always the same So you know when you create lists? That's generics List<Int>() List<string>() Which is List<T>() T is the generic type
Shrow
ShrowOPβ€’3mo ago
So that list can be any type of list like string or int right?
Moonlit
Moonlitβ€’3mo ago
I suggest it so that you can make your IAction better
public interface IAction<T>
{
string Name { get; }
void Do(T target)
}
public interface IAction<T>
{
string Name { get; }
void Do(T target)
}
No I mean like when you do "List<string>()` you're calling List<T>() Remember that everything is code... Either you write it or someone else wrote it When you are creating a list, it takes in a "Generic" type and there is code behind the scenes that makes that happen List<string>() is you telling it to make a list of type string List<int>() make a list of type int List<T> is what you are calling, it takes in a Generic type Make sense? So back to this... You might want to Do an action to an "IObject" like a chair! You might want to damage something that is an IDamageable, you might want to sell something that is ISellable So we can use "T" which means you can pass in any class you want
Shrow
ShrowOPβ€’3mo ago
So Instead of player target which only limits it's use to the player <T> allows it to be used any way we want?
Moonlit
Moonlitβ€’3mo ago
Yes I hate writing in discord lol
Shrow
ShrowOPβ€’3mo ago
In this code right here: public interface IAction<T> { string Name { get; } void Do(T target); } public class DamageAction : IAction { public string Name => "Damage"; public void Do(T target) => target.Hp--; } public class HealAction : IAction { public string Name => "Heal"; public void Do(T target) => target.Hp++; } The IAction(s) after Damage and Heal are in red and the T(s) on both interfaces after are red too. We could convers in a different way if you'd like Do I need to declare T somewhere prior to this code? like var T =;?
Moonlit
Moonlitβ€’3mo ago
You're close You tell Action that its being passed a generic So
public interface IAction<T>
{
string Name { get; }
void Do(T target, int amount);
}
public interface IAction<T>
{
string Name { get; }
void Do(T target, int amount);
}
Then when calling it, let it know what class it's recieving
public class HealSpell : IAction<Hero>
{
public string Name => "HealSpell";

public void Do(Hero target, int amount)
{
target.Health += amount;
Console.WriteLine($"{target.Name} has been healed by {amount} points!");
}
}
public class HealSpell : IAction<Hero>
{
public string Name => "HealSpell";

public void Do(Hero target, int amount)
{
target.Health += amount;
Console.WriteLine($"{target.Name} has been healed by {amount} points!");
}
}
This is exactly what you want yes? Even with generics the rule still exists that it needs to know what it is! It can't guess
Shrow
ShrowOPβ€’3mo ago
Wouldn't putting "Hero" make it less generic?
Moonlit
Moonlitβ€’3mo ago
@Shrow It doesn't have to be hero It's generic
Shrow
ShrowOPβ€’3mo ago
Oh or "hero" should be used for everything that has a healthbar I see I should name Hero to something more generic
Moonlit
Moonlitβ€’3mo ago
Well no you can make up whatever you want, that's just an example
Shrow
ShrowOPβ€’3mo ago
I think I understand
Moonlit
Moonlitβ€’3mo ago
public interface IHealth
{
int Health { get; set; }
void Heal(int amount);
}

public interface IAction<T>
{
string Name { get; }
void Do(T target);
}

public class HealSpell : IAction<IHealth>
{
public string Name => "Heal Spell";

public void Do(IHealth target)
{
target.Heal(20);
}
}

public class Hero : IHealth
{
public int Health { get; set; }

public Player(int initialHealth)
{
Health = initialHealth;
}

public void Heal(int amount)
{
Health += amount;
System.Console.WriteLine($"Player healed by {amount}. Current health: {Health}");
}
}
public interface IHealth
{
int Health { get; set; }
void Heal(int amount);
}

public interface IAction<T>
{
string Name { get; }
void Do(T target);
}

public class HealSpell : IAction<IHealth>
{
public string Name => "Heal Spell";

public void Do(IHealth target)
{
target.Heal(20);
}
}

public class Hero : IHealth
{
public int Health { get; set; }

public Player(int initialHealth)
{
Health = initialHealth;
}

public void Heal(int amount)
{
Health += amount;
System.Console.WriteLine($"Player healed by {amount}. Current health: {Health}");
}
}
Shrow
ShrowOPβ€’3mo ago
Thank you for the example!
Moonlit
Moonlitβ€’3mo ago
You don't have to, Hero is fine... We can just make the health system an Interface and then you can add it to anything you want You might have "Critter : IHealth" which is different to hero's If you understand this then hopefully this should be exactly what you were looking for?
Shrow
ShrowOPβ€’3mo ago
Well I think I do, I'll need to put it all together in my file and see if I understood everything.
Moonlit
Moonlitβ€’3mo ago
It's pretty versatile Btw you could technically add Damage(int amount) to IHealth too! Then give Furniture IHealth and it'd be possible for people to attack a chair and they can break it But yeh that's the general gist of it all! πŸ˜… Good luck again! I know I said it last time but I felt like our previous suggestions were good but they were so simplistic that you'd be back later because you'd have problems making different types of actions
Shrow
ShrowOPβ€’3mo ago
That would be great. This first game I'm developing I'm planning on keeping it simple for now, but the next game I have already planned out will have have stuff like furniture that can take damage. so having generic OOP will be paramount to making it work
Moonlit
Moonlitβ€’3mo ago
Yeh games are generally OOP You have DOP but data orientation is a bit more of a pain...
Shrow
ShrowOPβ€’3mo ago
I very much appreciate the help with it all. I probably will need more help in the future but it will hopefully be for something entirely different. Trying to learn code on my own through the internet is proving to be very difficult as learning sites and programs aren't as good as they look from the outside.
Moonlit
Moonlitβ€’3mo ago
Fully understand, I was self taught
Shrow
ShrowOPβ€’3mo ago
What's DOP?
Moonlit
Moonlitβ€’3mo ago
Tutorials and guides are very good at showing you how to do a very specific thing...
Shrow
ShrowOPβ€’3mo ago
Oh you too? What did you use to learn code
Moonlit
Moonlitβ€’3mo ago
I would follow a Unity tutorial and then when I finished I'd then task myself with making changes to what it helped me create
Shrow
ShrowOPβ€’3mo ago
I find too many tutorials only cover the basics and it doesn't help when they are all variations of printing 'Hello World".
Moonlit
Moonlitβ€’3mo ago
Haha yeh it's either 1 person explaining what a string is... or 1 person skipping what interfaces are when teaching you how to make a procedurally generated world by utilising a matrix that uses cells that inherit from tile
Shrow
ShrowOPβ€’3mo ago
Like one tutorial teaches how to create a text file and hoe to have print a dog and then have overwrite the file and rpint a different accii dog. But I need to learn how i can make those files into something more useful rather then just printing text.
Moonlit
Moonlitβ€’3mo ago
Json files?
Shrow
ShrowOPβ€’3mo ago
Yes exactly, either way too simple or way too advanced! notepad files
Moonlit
Moonlitβ€’3mo ago
Okay well learn to load from Json files You'll want to use the library "Newtonsoft.Json"
Shrow
ShrowOPβ€’3mo ago
I'l will search that up, games typical keeps lots of data on files so it would be nice to write a program able to generate files, read files, write files and execute code from files.
Moonlit
Moonlitβ€’3mo ago
Execute code from files? That is tricky Funny enough... That's literally what I am writing right now πŸ˜… But erm... Generally you shouldn't need to execute code from files What do you want it for?
Shrow
ShrowOPβ€’3mo ago
Something like, if I save x = 2; y = 4; z = 2+4; As a notepad file Then I would like to have a program be able to open a file and read the file and not print it into a string but rather executing the code and then printing z. I haven't found a tutorial that teaches that although i don't think it's nessesary for the game any way it would nice to know I suppose.
Moonlit
Moonlitβ€’3mo ago
Well that's a poor example... You'd need a more explicit use case for me to really give you advice on it but generally you wouldn't use files for that... But lets just say for that exact case you mention, if I wanted to have a bunch of numbers and then add them up from files... I'd have them as a Json file and it'd contain an array of numbers. My program would load the file and then add all the numbers together and print it I wouldn't do the code in the notepad... I'd use the values in the Json file that my code needs to work
Shrow
ShrowOPβ€’3mo ago
Yes I think I'm misunderstanding the need for it.
Moonlit
Moonlitβ€’3mo ago
Example I have a Bot that connects to Twitch! All the code for connecting to twitch is in my bot but the details I need to connect the server are in a .json file So after I build my bot and compile all my code, I can edit the details without needing to rebuild the bot My bot can also save new details to it For instance, I get a Token from twitch but it only lasts a limit time, when it runs out my bot needs to request a new one and then it saves it That's kinda what you'll mostly be using files for! And for save files, like you can use Newtonsoft to serialize your Hero class and save it, then you can load it Anyway I feel we've drifted from the general topic πŸ˜… So I suggest moving to either #chat or feel free to DM me if you want to converse about anything
Shrow
ShrowOPβ€’3mo ago
We have drifted yes! That's okay I appreciate the share of knowledge regardless, I do have to mosey now. I have company that's expecting but we can talk later I'd love to hear about it!
Moonlit
Moonlitβ€’3mo ago
Have fun and gl with your project
Shrow
ShrowOPβ€’3mo ago
Thank you! Good luck to your projects as well!
Moonlit
Moonlitβ€’3mo ago
:Moon_JJ_Love:
Want results from more Discord servers?
Add your server