2017-07-17 105 views
0

我正在製作一個簡單的回合制RPG遊戲。我正在制定戰鬥系統。我曾與1個敵人合作,並且想要更新它來處理多個敵人。我有它產卵多個敵人,但我有針對他們的問題。C#更新對象列表中的值也會更新其他值

基本上,敵人存儲在名爲actualEnemies的列表中。敵人在運行時產生,可能在1-3之間。生成一個標籤來顯示敵人的名字,雙擊敵人就可以選擇敵人。

這個問題似乎是在對敵人的命名。他們有一個名爲characterName的屬性來識別敵人。問題是,可以有2個或更多相同類型的角色(例如3x Goblin)。因此,在生成敵人的代碼中,如果列表中已經存在一個,我想向characterName添加1。這個想法是給每個敵人一個獨特的名字。

問題是,當我嘗試這個時,它改變了所有相同名字的敵人的值,並且這一切都是一團糟。下面是代碼的相關章節:

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

c的只是正在使用一個計數器,讓我知道,如果是敵人1,2或3

的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; 
    } 

要注意的是,敵人都以默認名稱開始。對於我正在研究的這個例子,只有兩種敵人。遊戲在1-3之間挑選一個隨機數字,以確定有多少敵人。每個敵人將成爲2個預先定義的敵人之一,隨機選取。這就是爲什麼我只想添加一個數字到已經存在的名稱的末尾。

我懷疑它是與我是怎麼創造的敵人名單:

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(); 
    } 

當我添加到actualEnemies,我只是指着potentialEnemies地址,所以即使我實例一個新的敵人,每一個,如果它有相同的名字,指向同一個地方?我是否需要正確複製對象?

它已經很晚了,我很累,但我覺得我正在接近,任何幫助都會很棒,謝謝。

編輯:

敵對階級:

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();    
    } 

} 
+0

請提供'Enemy' – Chrotenise

+0

市民階級敵人的類定義:字符 { 公衆詮釋xpGiven {獲得;組; } public LootTable lootTable {get;組; } public int goldDropped {get;組; } public bool alive {get;組; } public NamedTimer timer {get;組; } public Enemy() { alive = true; xpGiven = 10; 012otlootTable = new LootTable(); goldDropped = 10; timer = new NamedTimer(); } } – rm46

+0

只需使用代碼標記將其編輯爲原始問題即可。 – Chrotenise

回答

0

1:屬性名稱應與在C#中以大寫字母開頭。即public int xpGiven { get; set; }應該是public int XpGiven { get; set; }。如果它是一個類變量(沒有獲取或設置定義),則以小寫字母開頭。爲了更容易地從局部變量中識別類變量,程序員通常以_開頭,儘管這不是強制性的。

2:在做==時,請注意enemyA == enemya會返回false。使用enemyA.Equals(enemya, StringComparison.OrdinalIgnoreCase)忽略資本差異。

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(); 
    } 

應該是:

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(); 
    } 
+0

感謝您的迴應。我現在的問題是,敵人都處於默認狀態,而不是從預先定義的列表中進行選擇。有沒有辦法從一個列表中獲取一個對象的副本,將它添加到另一個列表中,但它是一個新對象,不再持有對原始列表的引用? – rm46

+0

1.這不是強制性的:冰淇淋口味和命名習慣一樣多。沒有正確的。 2.如果兩種類型都是字符串,那麼_absolutely_沒有理由不使用== == 3.介紹解釋修正? –

+0

@ rm46通常沒有。你可以做'var ene = new Enemy(){characterName = actualEnemies [i] .characterName,level = otherEnemy.level}'並且以這種方式設置所有屬性,基於另一個enemey的屬性。或者您可以使用反射遍歷所有屬性並複製它們的值。你不能做的就是說'ene = otherEne',因爲這會將'ene'指向另一個對象。 – Chrotenise

2

打破你的問題:

當我添加到actualEnemies,我只是指向一個地址potentialEnemies,所以即使我正在實例化一個新的敵人,每一個,如果它有相同的名字,指向同一個地方?

這樣做

Enemy ene = new Enemy(); 

您essentialy在內存中創建一個新的指針與「空白」價值基準。 不過,既然你做了

ene = potentialEnemies.ElementAt(r); 

您在列表中的參考元素可以覆蓋它。因此,無論您做什麼更改,ene對象都會反映列表中的項目。

如果要分隔所述更改,請嘗試使用MemberwiseClone

從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

非常感謝,我添加了淺拷貝方法並使用它。工作過一種享受。 – rm46

+0

如果這個答案有幫助,將它投票並標記爲* *答案:)很高興有幫助。 –

+1

@ rm46,你可能想要使用類似'DeepCopy()'的方法,因爲類'Enemy'的一些屬性看起來像引用類型,比如'lootTable'和'timer'。你新創建的'Enemy',如果你實現了類似於'ShallowCopy()'的東西,最終會引用同樣的'lootTable'和'timer'對象。這可能會導致出現類似於當前問題的新問題。 – Poosh