简体   繁体   English

关于在 C# 中使用抽象类的困惑

[英]Confusion over using abstract class in c#

I have a question since I'm new in programming Im really confused about how to implement a best practice solution for the following problem, Its a game logic,here are the possible ways of making points我有一个问题,因为我是编程新手我真的很困惑如何为以下问题实施最佳实践解决方案,这是一个游戏逻辑,这里有可能的积分方法

EnemyA 400,
EnemyB 500,
EnemyC 700,
Coin   200,
FireBall 300

means hitting Coin gives you 200 points and shooting FireBall gives you 300 &...意味着击中Coin给你 200 分和射击FireBall给你 300 & ...

if you reach 1000 points you will get an extra life, the logic simple but implementing the best practice is not(at least to me)should I use abstract class or Dictionary ?如果您达到 1000 分,您将获得额外的生命,逻辑很简单,但实现最佳实践不是(至少对我而言)我应该使用abstract class还是Dictionary

So far, I used a Dictionary , I read a given file (txt) file which is written (EnemyA,EnemyB,Coin,Coin,Coin,Coin) then I calculate the points:到目前为止,我使用了Dictionary ,我读取了一个给定的文件 (txt) 文件,该文件是 (EnemyA,EnemyB,Coin,Coin,Coin,Coin) 然后我计算点:

public int pointCal(IEnumerable<string> enemyType)
{
    var possiblePoints = new Dictionary< EnemisEntity,int>()
    {
        {new EnemisEntity{enemyType="EnemyA"},400 },
        {new EnemisEntity{enemyType="EnemyB" },500 },
        {new EnemisEntity{enemyType="EnemyC"},700 },
        {new EnemisEntity{enemyType="Fireball"},300 },
        {new EnemisEntity{enemyType="Coin"},200 },
    };
    int z=0;
    List<int> myPoints=new List<int> ();         
    foreach (var item in enemyType)
    {
        z = possiblePoints.FirstOrDefault(f => f.Key.enemyType.Equals(item)).Value;
                myPoints.Add(z);
    }
    int finalPonts= g.Sum(s=>Convert.ToInt32(s));
    return finalPonts;
}


  Enemy entity class:

     public  class EnemisEntity
    {
       public string enemyType { get; set; }
       
     }

It depends.这取决于。 Are the enemies different types of objects (with different properties and such)?敌人是不同类型的物体(具有不同的属性等)吗?

Then it might make sense to create an abstract class and child classes.那么创建一个抽象类和子类可能是有意义的。

public abstract class Shootable {
    public int points;
}

public class EnemyA: Shootable {
}

public class EnemyB: Shootable {
}

public class Coin: Shootable {
}

// etc

If all your items are just shootable with one description, then如果你所有的物品都可以用一个描述拍摄,那么

public class Shootable {
    public int points { get; set; }
    public string enemyType { get; set; }
    public Shootable(int points, string enemyType ){
        this.points = points;
        this.enemyType = enemyType;
    }
}

// then create like
var coin = new Shootable(500, "coin");

If all enemies can be modeled in the same class, then you only need shootable class如果所有敌人都可以在同一个类中建模,那么您只需要可射击类

Then get the points:然后获得积分:

IEnumerble<Shootable> shootableItems = GetShootableFromFile();
var score = shootableItems.Sum(s => s.Points);

You GetShootableFromFile should create one object per file row.GetShootableFromFile应该为每个文件行创建一个对象。 So it is a viable situation to create the same objects twice:因此,两次创建相同的对象是一种可行的情况:

// This is a mock to indicate multiple instances of the same class.
public IEnumerble<Shootable> GetShootableFromFile() {
    List<Shootable> shootable = new List<Shootable>();
    shootable.Add(new Shootable(500,"coin"));
    shootable.Add(new Shootable(500,"coin"));
    shootable.Add(new Shootable(500,"coin"));
    shootable.Add(new Shootable(300,"enemyA"));
    shootable.Add(new Shootable(300,"enemyB"));
    // etc
}

To me, this is a question of design.对我来说,这是一个设计问题。 When the only difference between enemies is just the value of points as well as their name it is not a good idea to define a class hierarchy.当敌人之间的唯一区别只是点的值及其名称时,定义类层次结构不是一个好主意。 The only thing different between a EnemyA and a EnemyB class would be just the values contained within each class. EnemyAEnemyB类之间唯一不同的就是每个类中包含的值。 So you can use a single common class to hold information for each enemy and process the points.因此,您可以使用单个公共类来保存每个敌人的信息并处理点数。

Below is the simplest working prototype that I could code that implements this design.下面是最简单的工作原型,我可以编写代码来实现这个设计。 It relies on two classes.它依赖于两个类。 The EnemyEntity class to hold the type of enemy and its points, and a Game class that contains the logic behind scoring and keeping a record of all possible enemies. EnemyEntity类用于保存敌人的类型及其点数,以及包含得分背后的逻辑和记录所有可能的敌人的Game类。

public class EnemyEntity
{
    public EnemyEntity(string type, int points)
    {
        Type=type;
        Points=points;
    }

    public string Type { get; }
    public int Points { get; }
}

public class Game
{
    public Game(params (string type, int points)[] values)
    {
        this.Enemies = new List<EnemyEntity>();
        foreach (var (type, points) in values)
        {
            Enemies.Add(new EnemyEntity(type, points));
        }
    }

    public List<EnemyEntity> Enemies { get; }

    public int CalculatePoints(IEnumerable<string> targets)
    {
        int points = 0;
        foreach (var item in targets)
        {
            var target = Enemies.FirstOrDefault((enemy) => enemy.Type.Equals(item));
            if (target!=null)
            {
                points+= target.Points;
            }
        }
        return points;
    }

}


class Program
{
    static void Main(string[] args)
    {
        var game = new Game(
            ("EnemyA", 400),
            ("EnemyB", 500),
            ("EnemyC", 700),
            ("Coin", 200),
            ("FireBall", 300));

        var input = "EnemyA,EnemyB,Coin,Coin,Coin,Coin";
        var targets = input.Split(',');
        var points = game.CalculatePoints(targets);

        Console.WriteLine(points);
        // 1700
    }
}

NOTES:笔记:

The simplest approach is to use a List<EnemyEntity> and do the lookup with .FirstOrDefault() .最简单的方法是使用List<EnemyEntity>并使用.FirstOrDefault()进行查找。 I could use a Dictionary<string,EnemyEntity> which would simplify the lookup process.我可以使用Dictionary<string,EnemyEntity>来简化查找过程。 Here is how the Game class would change using a dictionary.以下是使用字典更改Game类的方式。

public class Game
{
    public Game(params (string type, int points)[] values)
    {
        this.Enemies = new Dictionary<string, EnemyEntity>();
        foreach (var (type, points) in values)
        {
            Enemies[type] = new EnemyEntity(type, points);
        }
    }

    public Dictionary<string, EnemyEntity> Enemies { get; }

    public int CalculatePoints(IEnumerable<string> targets)
    {
        int points = 0;
        foreach (var item in targets)
        {
            var target = Enemies[item];
            if (target!=null)
            {
                points+= target.Points;
            }
        }
        return points;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM