2011-07-26 156 views
0

總之,我有一個對象叫做PersonList,它有一個列表對象。我創建了一個PersonLists二維數組來模擬一張地圖並隨機放置並移動該地圖內的Person對象。但是,我在從PersonList的二維數組中刪除Person時遇到問題。同時,即使它在那裏移動,似乎也不會將同一個人添加到二維數組中的相同位置。列表的二維數組有問題

我已盡力創建一個小版本的我下面的內容。我有一種感覺,我失去了一些明顯的東西。我也開放了我可以更好地實施這個系統的方法,因爲這可能是最低效的方式。

public class Person { 
    private int id; 
    private int[] pos = new int[2]; 

    public Person(int id) { this.id = id; } 

    public int getId() { return id; } 
    public int[] getPos() { return pos; } 
    public void setPos(int x, int y) { pos[0] = x; pos[1] = y; } 

    public boolean equals(Object obj) { 
     if (obj == null) { return false; } 
     if (obj == this) { return true; } 
     if (obj.getClass() != getClass()) { return false; } 

     Person rhs = (Person) obj; 
     return id == rhs.getId(); 
    } 

    public int hashCode() { return id; } 
} 

PersonList

import java.util.*; 

public class PersonList { 
    List<Person> listPersons = new ArrayList<Person>(); 

    PersonList() {} 

    public void add(Person p) { listPersons.add(p); } 
    public void remove(Person p) { listPersons.remove(p); } 
    public int getSize() { return listPersons.size(); } 
} 

現在,我還有一個控制某些人,包含PersonLists的二維數組類。它看起來像這樣:

import java.util.*; 

public class Control { 
    List<Person> persons = new ArrayList<Person>(); 
    PersonList[][] pmap; 

    //numPeople is the number of Person objects to use 
    //size is the size of the pmap (used as both length and width)  
    public Control(int numPeople, int size) { 
     pmap = new PersonList[size][size]; 
     //Initialize all PersonList objects within array 
     for(int y = 0; y < size; y ++) { 
      for(int x = 0; x < size; x ++) { 
       pmap[x][y] = new PersonList(); 
      } 
     } 

     for(int i = 0; i < numPeople; i ++) { 
      persons.add(new Person(i)); 
     } 
     // Defined below  
     placePersons(); 
    } 

    // Randomly place Person on the pmap  
    private void placePersons() { 
     Iterator<Person> i = persons.listIterator(); 
     while(i.hasNext()) { 
      Person p = i.next(); 
      int x, y; 
      // Random method to obtain valid position within pmap stored in x and y 
      p.setPos(x, y); 
      pmap[x][y].add(p); 
     } 
    } 

    //Move person from "src" on pmap to "dest" on pmap  
    private void movePerson(Person p, int[] src, int[] dest) { 
     pmap[src[0]][src[1]].remove(p); 
     pmap[dest[0]][dest[1]].add(p); 
     p.setPos(dest[0], dest[1]); 
    } 

    //Makes every person wander around the pmap 
    public void wander() { 
     for(Person p : persons) { 
      int[] xy = new int[2]; 
      // Random method to obtain valid position within pmap stored in xy 
      movePerson(p, p.getPos(), xy); 
     } 
    }     
} 

想象一下,我在一個循環中啓動「Control.wander()」。我遇到了一個問題,那就是沒有正確地從pmap中刪除人員。我用pmap中的每個PersonList的大小打印出一個網格,數字永遠不會減少。但是,他們的數量不會超過「人員」名單中的人數。

也就是說,它們似乎不能被刪除,但即使它們移動到那裏,也不會有多人添加到pmap中的同一位置。

我的問題立即明顯,或應該從理論上工作?

隨時問任何問題。感謝您的幫助,我非常感謝。

編輯:我已經添加了我做了一些改變 - 我現在用的不是for-each循環迭代器,我已經定義了人一個簡單的hashCode方法。作爲一個測試,我在PlayerPos中添加了一個返回列表中第0個對象的方法(getFirst()),如果沒有,則返回null。

在movePerson,我有這樣的:

System.out.println(p + " and " + pmap[src[0]][src[1]].getFirst()); 

它期待打印兩個匹配的id(我只用1人在我的測試)。我還在PersonList中的remove(Person p)函數本身中添加了相同的行。但是,多數情況下,這個「getFirst()」結果將顯示爲空。 remove(Person p)在我的movePerson測試後立即被調用,那麼爲什麼它會返回一些東西,但PersonList本身沒有東西?這是否對我的問題有更多的瞭解?感謝所有幫助到目前爲止。

編輯2:我也試着讓PersonList的listPersons公開並直接操縱它,但我似乎仍然有同樣的問題。

編輯3:隨着越來越多的測試,在movePerson,我已經打印出每行之間的SRC和DEST PMAP的大小,它好像它正在從SRC PMAP正確刪除,但添加後到dest,src pmap的大小再次增加。我三重檢查了我的add函數(這是一個簡單的單行),並確保數組索引是正確的。這怎麼可能發生?

回答

2
private void movePerson(Person p, int[] src, int[] dest) { 
    pmap[src[0]][src[1]].remove(p); 
    pmap[dest[0]][src[1]].add(p); 
    p.setPos(dest[0], dest[1]); 
} 

應該

private void movePerson(Person p, int[] src, int[] dest) { 
    pmap[src[0]][src[1]].remove(p); 
    pmap[dest[0]][dest[1]].add(p); //fix on this line 
    p.setPos(dest[0], dest[1]); 
} 

所以它看起來像人正在加入到不到哪裏以爲他們是其他的地方。

還要注意的是,你不應該需要在src傳遞給方法,因爲Person已經跟蹤它在哪裏:

private void movePerson(Person p, int[] dest) { 
    int[] pos = p.getPos(); 
    pmap[pos[0]][pos[1]].remove(p); 
    pmap[dest[0]][dest[1]].add(p); 
    p.setPos(dest[0], dest[1]); 
} 

編輯:確保覆蓋hashCode()每當你重寫equals() 。不存在這可能會干擾List方法remove()。有人提到這個,但答案已被刪除。

對於您的目的hashCode()應該只是返回id假設這是唯一的。不要將位置因素考慮在內 - 例如,您希望Person成爲一個身份,而不管它們在哪裏。測試這個,然後更新你的問題,如果它仍然無法正常工作。

+0

對不起,這DEST行是在我的代碼是正確的,我只是做了錯誤,當我寫在這裏。 – noisesolo

+0

@noisesolo:就像忽必烈所說的,你也需要實施hascode方法來去除List的方法。 – Kowser

+0

我已經添加了hashCode()方法來返回id。仍然沒有運氣。 (還是)感謝你的建議。 – noisesolo

0

您的隨機方法PlacePersons是故意註釋掉的,還是您真的想將所有人放在[0,0]中。
我不認爲PersonList類增加任何價值,我想有一個結構如下:
Map<Integer, Set<Person>>

地圖將代表y座標的整數鍵,以及個人的位置在集合中將代表他們的x座標。
您可以選擇是否將每個人的內部座標存儲在Person類中,只要他們被移動,或者您可以(付費)更改getPos來遍歷Map/Set,直到他們找到自己並返回這些座標。

甚至更​​好Map<Person, Coord>其中Coord是一個類,它擁有x-y座標位置。

記得爲Person實現equals和hashCode。

+0

爲簡潔起見,隨機方法被註釋掉。這是一個簡單的部分,我敢肯定的作品。感謝您的建議,我會給這個實施一個鏡頭。 – noisesolo

0

使用:

for(Person p : persons) 
{  
    int[] xy = new int[2];    
    // Random method to obtain valid position within pmap stored in xy    
    movePerson(p, p.getPos(), xy);   
} 

你獲得從你的人的ArrayList來者P的引用,然後使用foreach循環所產生的符號引用來移動它們。如果你真的想對你的集合使用remove操作,你需要設置一個迭代器。

See this for a good explaination

+0

雖然他不是從集合中刪除人員 - 只能從二維數組中的PersonLists中刪除。 –

+0

如果仔細觀察placePersons()的構造,您會注意到兩個集合上都放置了相同的對象。它是一種非常複雜的存儲東西的方式,很多問題都會在這個設計中看到可變對象,但我們並沒有在這裏討論。 – Grambot

+0

保持對多個集合中對象的引用沒有任何問題,假設它們的hashCode()和equals()被正確實現。據我所知,他擁有所有人的主索引,除了基於位置的索引之外,沒有任何錯誤。 –