2011-05-08 45 views
1

我在TreeSet中從我正在處理的遊戲中刪除一個單元時遇到了問題。我正在製作一個塔防遊戲,路徑被分成不同長度的塊。塊知道它內部的單元和路徑上的下一個塊。當單位離開塊的邊界時,塊將其從列表中移除並將其添加到下一個塊。compareTo和TreeSet的問題

我正在使用TreeSet來跟蹤塊中單元的順序,這樣我就可以知道哪個單元沿着路徑最遠。這些單位有一個位置字段,用於跟蹤他們所在的路徑有多遠,位置越高,位置越遠。

在我的一些塊中,我注意到當它試圖從它的TreeSet中刪除一個單元時,remove將返回false。我使用了一些斷點,我可以看到該單元實際上在TreeSet中,所以我認爲我的問題是我的攻擊單位的compareTo方法。

這裏是我的代碼的compareTo:

public int compareTo(Object other) { 
    if (other != null && AttackingUnit.class.isAssignableFrom(other.getClass())) { 
     AttackingUnit o = (AttackingUnit) other; 
     int amount = position - o.position; 
     if (amount != 0) { 
      return amount; 
     } else if (amount == 0 && this == o) { 
      return 0; 
     } 
    } 
    return 1; 
} 

一個地方我注意到這個問題塊是單位進入前一個塊,拿一半的一角,並退出右側。該塊有兩個ArrayLists,一個用於從上到下(enPath)的單元,另一個用於從左到右的單元(exPath)。下面有其中我有問題的代碼:

for (int i = 0; i < exPath.size(); i++) { 
    AttackingUnit unit = exPath.get(i); 
    unit.stepX(); 
    if (unit.getX() > rightX) { 
     nextBlock.addUnit(unit); 
     units.remove(unit); 
     exPath.remove(unit); 
     i--; 
    } 
} 

單位爲exPath和在單元(TreeSet中),但units.remove(單元)返回false。關於如何在AttackingUnit上修改compareTo來解決這個問題的任何想法?

回答

1

你的compareTo方法很奇怪。首先,你的列表中不應該包含任何不正確類型的元素,也不應該包含空元素,因爲這樣會產生問題。所以你可以簡單地在這些情況下拋出異常,而不是返回1。其次,正如史蒂夫已經指出的那樣,this == o檢查是不正確的 - 這違反了你的關係的對稱性,給你找不到你的元素的情況。這使這個簡單的版本:

public int compareTo(Object other) { 
    AttackingUnit o = (AttackingUnit) other; 
    int amount = position - o.position; 
    return amount; 
} 

第三,保證位置(即您比較的結果),而單位是在TreeSet中不會改變。如果位置必須改變,首先從設置中刪除元素,改變位置,然後再次添加。

+0

我給了這個鏡頭,我的印象是,如果compareTo返回0,TreeSet會認爲這些對象是相同的,並且不會添加該單元。我很擔心這個,因爲如果兩個單位佔據相同的空間,那麼這個單位就不會被添加到樹中。 – Jonathan 2011-05-08 20:53:45

+0

如果你需要兩個對象在相同的位置不同,你需要一些其他的標準來區分它們,比如名字等。在這種情況下,不要簡單地返回1,因爲它不是對稱的。 – 2011-05-08 20:57:28

+0

我現在唯一擁有的單位是健康,x,y和位置。如果他們都是一樣的有一種獲得Java使用的變量ID的方法,所以我可以看到他們是否完全相同或不相同?如果他們不是,我可以用它來比較。 – Jonathan 2011-05-08 21:03:22

1

一個問題,我看到的是在你compareTo是:

} else if (amount == 0 && this == o) { 

你應該他們或運算(或擺脫this == o檢查)。就像現在一樣,具有相同position的兩個不同的AttackingUnit實例將返回爲1(第一個較大)。這肯定會給樹集上的不一致排序。

順便說一句,你可以替換:

if (other != null && AttackingUnit.class.isAssignableFrom(other.getClass())) 

if (other instanceof AttackingUnit) 

哪一個更容易閱讀。