2012-02-03 65 views
1

我正在通過編寫一個小遊戲來學習C#。作爲其中的一部分,我將來自設備的輸入映射到包含遊戲中操作的枚舉,該操作由按鈕,操作對的字典定義。有沒有一種在C#中使用System.Enum的邏輯操作的好方法?

例如,我有這樣的事情,示意:

[Flags] 
enum Actions { None=0, MoveUp=1, MoveDown=2, MoveLeft=4, MoveRight=8 } 

Actions currentActions; 

private void SetActions() 
{ 
currentActions = Actions.None; 
if (UpPressed) 
    currentAction |= Actions.MoveUp; 
(etc) 

} 

public void Update() 
{ 
SetActions(); 
if (currentActions & Actions.MoveUp) == Actions.MoveUp) 
    MoveUp(); 
(etc) 
} 

我設置的操作基於輸入,然後我更新了遊戲的狀態取決於其行動是在列表中。我想做的是,有一個新的類「ActionManager」,其中包含與動作相關的數據和方法;

public Enum currentActions; 
public void SetActions(); 
public void UpdateActions(); 

和其他類,例如,對應於菜單類,可以添加自己的枚舉這一全球性枚舉,讓每一個可能的動作集負責處理輸入每一類中定義的,而不是在全局枚舉中被預先定義。

但我不能這樣做,因爲我無法添加或從一個枚舉中刪除,我不能從System.Enum繼承。我能想到的唯一辦法做到這涉及列出枚舉:

// In class ActionManager 
public List<Enum> allowedActions = new List<Enum>(); 
public List<Enum> currentActions = new List<Enum>(); 

public void SetActions(Enum action) 
{ 
currentActions.Clear(); 
foreach (Enum e in allowedActions) 
    if (IsKeyPressed(e))    
     currentActions.Add(e); 
} 

// In, say, GameMenu class 
[Flags] 
enum MenuActions { None=0, MenuUp = 1, ... } 

private actionManager ActionManager = new ActionManager(); 

public void DefineActions() 
{ 
foreach (MenuActions m in Enum.GetValues(typeof(MenuActions))) 
    actionManager.allowedActions.Add(m); 
    //also define the key corresponding to the action 
    //here, from e.g., a config file 
    //and put this into a Dictionary<buttons, actions> 
} 

public Update() 
{ 
actionManager.Update(); 

if (actionManager.currentActions.Contains(MenuActions.MenuUp)) 
(etc) 
} 

但這似乎愚蠢的,我把它換成廉價的邏輯運算與枚舉的列表,這似乎很尷尬。它也迫使我使用.Contains等,而不是算術,並使用引用類型,其中值類型更有意義(並且通用列表不應該暴露在外面)。

我知道我還可以用一個int代替我的名單,並投我的所有其他類的枚舉到整數這樣我就可以和動作組合,但是這並沒有枚舉類型安全。

所以,我的問題是: 有沒有辦法用枚舉來做到這一點? 有沒有更智能的方式來做這種事情(通常是枚舉或其他方式)?

我這樣做是爲了學習語言,所以如果有更好的方法來做這樣的事情,我將不勝感激!

回答

3

是;你可以使用位運算符:

Actions allowedActions = Actions.Up | Actions.Right; 
allowedActions |= Actions.Down; // to show building at runtime 
Actions currentActions = Actions.Right | Actions.Down; // union 

,然後使用各種&/|/~進行的測試和變化:

var limitedToAllowed = currentActions & allowedActions; // intersect 

// disallow "up" for some reason 
allowedActions &= ~Actions.Up; 

您可以通過測試重疊:

// test if **any** of the currentActions is in the allowedActions 
bool anyAllowed = currentActions & allowedActions != 0; 
// test if **all** of the currentActions are in the allowedActions 
bool allAllowed = currentActions & allowedActions == currentActions; 

關於「允許哪些值」的註釋通常可以通過添加.All枚舉(在您的案例中爲15)或者在IME:

Actions actions = 0; 
foreach(Actions action in Enum.GetValues(typeof(Actions))) { 
    actions |= action; 
} 
// actions now has all the flags that are defined 
+0

是的,我知道我能做到位操作,但沒有用它,在這裏我想怎麼辦內的所有可能的行動,一個全球性的枚舉,我不能做到這一點是有一個插件類級別的枚舉到ActionManager類中 - ActionManager類將不會提前知道這些操作。 – JMP 2012-02-03 06:57:46

+0

@JMP你能澄清你的意思嗎?當你使用'List '時,我看不出有什麼不同......如果你的意思是「我想要所有枚舉」,那麼很簡單 - 我將編輯... – 2012-02-03 07:30:41

相關問題