2009-10-15 53 views
4

我仍然在爲我的迷宮遊戲製作我的Cell類。在另一個線程的幫助後,有人建議我爲我的Walls/Neighbors使用EnumMap,目前這個工作非常順利。如何將Enum與其相反的值相關聯,如在主要方向(南北,東西方等)?

這裏是我迄今:

enum Dir { 
    NORTH, SOUTH, EAST, WEST 
} 

class Cell { 
    public Map<Dir, Cell> neighbors = Collections 
      .synchronizedMap(new EnumMap<Dir, Cell>(Dir.class)); 
    public Map<Dir, Boolean> walls = Collections 
      .synchronizedMap(new EnumMap<Dir, Boolean>(Dir.class)); 

    public boolean Visited; 

    public Cell() { 
     Visited = false; 
     for (Dir direction : Dir.values()) { 
      walls.put(direction, true); 
     } 
    } 

    // Randomly select an unvisited neighbor and tear down the walls 
    // between this cell and that neighbor. 
    public Cell removeRandomWall() { 
     List<Dir> unvisitedDirections = new ArrayList<Dir>(); 
     for (Dir direction : neighbors.keySet()) { 
      if (!neighbors.get(direction).Visited) 
       unvisitedDirections.add(direction); 
     } 

     Random randGen = new Random(); 
     Dir randDir = unvisitedDirections.get(randGen 
       .nextInt(unvisitedDirections.size())); 
     Cell randomNeighbor = neighbors.get(randDir); 

     // Tear down wall in this cell 
     walls.put(randDir, false); 
     // Tear down opposite wall in neighbor cell 
     randomNeighbor.walls.put(randDir, false); // <--- instead of randDir, it needs to be it's opposite. 

     return randomNeighbor; 
    } 
} 

如果你在那最後的評論看那裏,我第一次推倒說,在我目前的小區北牆。然後,我帶走我的北方鄰居,現在我必須拆除我的南牆,這樣兩個單元之間的牆壁才被拆除。

什麼是一個簡單的方法來擴展我的枚舉,所以我可以給它一個方向,它返回給我它是相反的?

回答

10

最簡單的,我想只是爲它添加一個方法。請注意,這隻有在枚舉常量的數量不會隨時間變化時纔會有效。

enum Dir { 
    NORTH, 
    SOUTH, 
    EAST, 
    WEST; 

    public Dir opposite() { 
     switch(this) { 
      case NORTH: return Dir.SOUTH; 
      case SOUTH: return Dir.NORTH; 
      case EAST: return Dir.WEST; 
      case WEST: return Dir.EAST; 
      default: throw new IllegalStateException("This should never happen: " + this + " has no opposite."); 
     } 
    } 
} 

然後,在你的代碼,你可以這樣做:

randomNeighbor.walls.put(randDir.opposite(), false); 
+3

+1。你不應該在枚舉上「切換」,但由於循環依賴關係,這是最乾淨,最可讀的方式來執行它......假設你添加了'default:throw new AssertionError(this)':) – gustafc

+0

@ gustafc同意,我更新了我的答案。 – jqno

+1

@gustafc,通常不希望打開枚舉的原因是什麼? – Scorcher84

14

另一種方法不帶開關/箱,或具有存儲狀態:

public enum Dir { 
    NORTH { @Override public Dir opposite() { return SOUTH; }}, 
    EAST { @Override public Dir opposite() { return WEST; }}, 
    SOUTH { @Override public Dir opposite() { return NORTH; }}, 
    WEST { @Override public Dir opposite() { return EAST; }}, 
    ; 

    abstract public Dir opposite(); 
} 
+0

比我的方法更好。我只是看起來像過度工程;-) – toolkit

+2

注意這會創建五個類文件,而不是一個。 –

+0

是。代碼空間和數據空間之間的折衷。這不能很好地擴展到更大的數據結構,許多方法或許多枚舉......但是對於小小的調整它是一個快速修復。當大多數枚舉需要返回一個值時(除少數例外)也適用。 –

0
public enum Direction 
{ 
    NORTH,EAST,SOUTH,WEST; 

    public Direction opposite() 
    { 
     return Direction.values()[ (this.ordinal() + 2) & 3 ]; 
    } 
} 
+1

或甚至this.ordinal()^ 2? – araqnid

+0

這是一個好的觀點。 – fforw

1

你可以試試這個,關於這個「好」的事情是,你可以像枚舉數組一樣爲枚舉建立索引,並且因爲我們正在處理與之相反的對立始終是對,只要您將新值添加到結尾,代碼就支持它,所以您不會搞亂索引。

enum Directions { 

    NORTH(1), 
    SOUTH(0), 
    WEST(3), 
    EAST(2); 

    private final int opposite; 

    Directions(int opposite) { 
     this.opposite = opposite; 
    } 

    Directions opposite() { 
     return Directions.values()[this.opposite]; 
    } 

} 

例如,如果你想添加更多的方向,你只想補充一點:

NORTH_WEST(7), 
NORTH_EAST(6), 
SOUTH_WEST(5), 
SOUTH_EAST(4) 

容易。 :)

相關問題