简体   繁体   English

C#更新对象列表中的值也将更新其他值

[英]C# Updating a value in a list of objects is updating other values too

I was working on a simple turn based RPG game. 我当时正在研究一个简单的回合制RPG游戏。 I was working on a battle system. 我当时在战斗系统上工作。 I had it working with 1 enemy, and wanted to update it to work on multiple enemies. 我让它与1个敌人一起使用,并想对其进行更新以在多个敌人上使用。 I have it spawning multiple enemies, but I am having issues targeting them. 我产生了多个敌人,但针对他们却遇到了问题。

Basically, the enemies are stored in a list called actualEnemies. 基本上,敌人存储在一个称为“实际敌人”的列表中。 The enemies are generated at run time, and there can be between 1-3. 敌人是在运行时生成的,并且可能在1-3之间。 A label is generated to display the enemy name, and the enemy is selected by double clicking on it. 生成一个标签来显示敌人的名字,并通过双击敌人来选择它。

The issue seems to be in the naming of the enemy's. 问题似乎在于敌人的名字。 They have a property called characterName to identify an enemy. 他们有一个名为characterName的属性来识别敌人。 The problem is, there can be 2 or more of the same type of character (for example, 3x Goblin). 问题是,可能有2个或更多相同类型的字符(例如3x妖精)。 So in the code where the enemies are generated, I was wanting to add a 1 to the characterName if there already is one in the list. 因此,在生成敌人的代码中,如果列表中已经存在一个,我想在characterName上添加1。 The idea is to give each enemy a unique name. 这个想法是给每个敌人一个唯一的名字。

The problem is, when I try this, it changes the values of all of the enemies of the same name, and this is screwing with everything. 问题是,当我尝试执行此操作时,它会更改所有同名敌人的值,并且这一切都搞砸了。 Here is the relevant section of code: 这是代码的相关部分:

if (EnemyExists(e)) {
    e.characterName += c.ToString();                            
}

c is simply a counter that is being used, to let me know if it is enemy 1, 2 or 3. c只是一个正在使用的计数器,让我知道它是敌人1、2还是3。

The EnemyExists function is as follows: EnemyExists函数如下:

public bool EnemyExists(Enemy e) {
    bool exists = false;
    int eCount = 0;

    foreach (Enemy en in actualEnemies) {
        if (en.characterName == e.characterName) {
            eCount++;
        }
    }

    if (eCount > 1) {
        exists = true;
    }

    return exists;
}

Just to note, the enemies all start off with a default name. 请注意,所有敌人都以默认名称开始。 For this example I am working on, there are only 2 kinds of enemy. 对于我正在研究的这个示例,只有两种敌人。 The game picks a random number between 1-3, to decide how many enemies there are. 游戏选择1-3之间的随机数,以确定有多少个敌人。 Each enemy will be one of the 2 pre defined enemies, picked at random again. 每个敌人将是2个预先定义的敌人之一,并再次随机选择。 This is why I just want to add a number to the end of a name that is already present. 这就是为什么我只想在已经存在的名称的末尾添加一个数字。

I suspect it has something to do with how I am creating the list of enemies: 我怀疑这与我创建敌人列表有关:

public void CreateActualEnemies() {
    int r;
    int potEnemyNum = potentialEnemies.Count;         
    int numEnemies;
    Random rand = new Random();
    numEnemies = rand.Next(1, 4 );

    for (int i = 0; i < numEnemies; i++) {
        r = rand.Next(0,potEnemyNum);
        Enemy ene = new Enemy();
        ene = potentialEnemies.ElementAt(r);
        actualEnemies.Add(ene);
    }

    DisplayEnemyDetails();
}

When I add to actualEnemies, am I just pointing to an address in potentialEnemies, so even though I am instantiating a new Enemy, each one, if it has the same name, points to the same place? 当我添加实际敌人时,是否只是在指向潜在敌人中的地址,所以即使我实例化了一个新的敌人,如果每个敌人都具有相同的名称,它都指向同一位置吗? Do I need to properly copy the object? 我需要正确复制对象吗?

It is late, I am tired, but I feel like I am getting closer, any help would be great, thanks. 已经很晚了,我很累,但是我觉得我越来越近了,任何帮助都会很大,谢谢。

EDIT: 编辑:

Enemy Class: 敌人等级:

public class Enemy:Character {
    public int xpGiven { get; set; }
    public LootTable lootTable { get; set; }
    public int goldDropped { get; set; }
    public bool alive { get; set; }
    public NamedTimer timer { get; set; }

    public Enemy() {
        alive = true;
        xpGiven = 10;
        lootTable = new LootTable();
        goldDropped = 10;
        timer = new NamedTimer();            
    }
}

Breaking down your question: 分解您的问题:

When I add to actualEnemies, am I just pointing to an address in potentialEnemies, so even though I am instantiating a new Enemy, each one, if it has the same name, points to the same place? 当我添加实际敌人时,是否只是在指向潜在敌人中的地址,所以即使我实例化了一个新的敌人,如果每个敌人都具有相同的名称,它都指向同一位置吗?

By doing 通过做

Enemy ene = new Enemy();

You are essentialy creating a new pointer in memory with a "blank" valued-reference. 您必须在内存中使用“空白”值引用创建新的指针。 However, since you did 但是,既然你做了

ene = potentialEnemies.ElementAt(r);

You overwrote it with the reference to the element in the list. 您使用对列表中元素的引用来覆盖它。 So whatever changes you do the ene object will reflect the item in the list. 因此,您对ene对象所做的任何更改都将反映列表中的项目。

If you want to segregate said changes, try using a MemberwiseClone . 如果要隔离所说的更改,请尝试使用MemberwiseClone

From the example given at MSDN: 从MSDN给出的示例中:

public class Person 
{
    public int Age;
    public string Name;
    public IdInfo IdInfo;

    public Person ShallowCopy()
    {
       return (Person) this.MemberwiseClone();
    }

    public Person DeepCopy()
    {
       Person other = (Person) this.MemberwiseClone();
       other.IdInfo = new IdInfo(IdInfo.IdNumber);
       other.Name = String.Copy(Name);
       return other;
    }
}

1: Property names should start with a capital letter in C#. 1:属性名称应以C#中的大写字母开头。 Ie public int xpGiven { get; set; } public int xpGiven { get; set; } public int xpGiven { get; set; } public int xpGiven { get; set; } should be public int XpGiven { get; set; } public int xpGiven { get; set; }应该是public int XpGiven { get; set; } public int XpGiven { get; set; } public int XpGiven { get; set; } . public int XpGiven { get; set; } If it's a class variable (no get or set defined), you start with a lower case letter. 如果它是一个类变量(未定义get或set),则以小写字母开头。 To more easily identify class variables from local variables, programmers typically start them with a _, although this is not mandatory. 为了更容易地从局部变量中识别类变量,程序员通常以_开头,尽管这不是强制性的。

2: When doing == , please be aware enemyA == enemya will return false. 2:做== ,请注意enemyA == enemya将返回false。 Use enemyA.Equals(enemya, StringComparison.OrdinalIgnoreCase) to ignore capital differences. 使用enemyA.Equals(enemya, StringComparison.OrdinalIgnoreCase)忽略资本差异。

3: 3:

public void CreateActualEnemies()
    {
        int r;
        int potEnemyNum = potentialEnemies.Count;         
        int numEnemies;
        Random rand = new Random();
        numEnemies = rand.Next(1, 4 );
        for (int i = 0; i < numEnemies; i++)
        {
            r = rand.Next(0,potEnemyNum);
            Enemy ene = new Enemy();
            ene = potentialEnemies.ElementAt(r);
            actualEnemies.Add(ene);
        }
        DisplayEnemyDetails();
    }

should be: 应该:

public void CreateActualEnemies()
    {
        Random rand = new Random();
        int numEnemies = rand.Next(1, 4 );

        for (int i = 0; i < numEnemies; i++)
        {
            Enemy ene = new Enemy();
            ene.characterName = "" + ene.GetType().Name + " " + i; // or something similar to give the ene a unique name.
            actualEnemies.Add(ene);
        }
        DisplayEnemyDetails();
    }

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

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