2016-12-25 114 views
0

在開始之前,我會介紹一下我正在嘗試做什麼。然後我會提供一些代碼,並最終陳述我的問題/問題/問題。軟件設計解決方案 - 遊戲

該場景如下: 設計了回合制RPG遊戲的戰鬥系統。在戰鬥中, 玩家輸入可以產生不同的結果,具體取決於戰鬥的「當前狀態」 。我正在實施國家模式來解決這個問題。

例如,如果戰鬥處於動作選擇狀態,則使用向上和向下鍵使玩家 突出顯示他想要採取的動作,然後使用ENTER鍵激活它。

戰鬥系統進入的下一個狀態取決於所選擇的動作。 例如如果選擇「Attack」,則戰鬥進入SelectTargetState。如果選擇 「Spell」,則戰鬥進入SelectSpellState,然後進入SelectTargetState的 。

下面我用Java提供了一些代碼,其中只包括那些直接相關的部分。之後,實際問題被詢問。

// The BattleScene class, representing the whole battle system 
public class BattleScene 
{ 
    private State currentState; // The current state of the system 
    // Below are all other attributes such as, heroes, enemies etc. 
    .. 
    .. 

    public void input(int key) 
    { currentState.input(key); } 
    // The actual implementation depends on the state 
    // As said above: "player input can produce different results, 
    // depending on the 'current state'" 

    // Setter 
    public void setState(State state) 
    { currentState = state; } 

} 

// The abstraction of all States 
public abstract class State 
{ 
    // All of them contain a reference to the system they belong to, 
    // so that they can "change/control" it 
    private BattleScene parent; 

    // Constructor 
    public State(BattleScene parent) 
    { this.parent = parent; } 

    // The actual input handling is to be represented by subclasses 
    public abstract void input(int key); 
} 

// A concrete State class, displaying a proper example 
public class ActionSelectState extends State 
{ 
    private String[] actions; // List of available actions 
    private int index; // The currently "highlighted" action 

    // Constructor 
    public ActionSelectState(BattleScene parent, String[] actions) 
    { 
     super(parent); 
     this.actions = actions; 
    } 

    public void input(int key) 
    { 
     switch(key) 
     { 
      case DOWN: 
       incIndex(); // Increases index safely by 1 
       break; 
      case UP: 
       decIndex(); // Decreases index safely by 1 
       break; 
      case ENTER: 
       activateAction(); 
       break; 
     } 
    } 

// THE ACTUAL PROBLEM - READ BELOW 
    private void activateAction() 
    { 
     if(action.compareTo("Attack")==0) 
      parent.setState(new SelectTargetState(parent)); 
     else if(action.compareTo("Spell")==0) 
      parent.setState(new SelectSpellState(parent)); 
    } 
} 

的問題/問題是,對於一切可能的行動,有可能是一個不同的 路徑和許多州必須遵循。例如: - Attack-> Select Target-> Execute Action - Spell-> Select Spell-> Select Target(s) - > Execute Action - Item - > ........ - 可能有數十個命令在未來....-> ....-> ....

上面的activateAction()需要幾十個「if..else」。並且如果其他州需要取決於行動的類似條件選擇呢? 這就需要每個州都有很長的「if..else」聲明。 Maybye 即使未來會有數量/種類的狀態發生變化,例如會增加更多狀態。

有沒有針對這個問題的複雜解決方案? 任何方式使其抵抗縮放(即避免 條件語句的指數增加)? 還是我只限於大的if..else(或switch..doesn't事)?

任何想法,建議,解決方案。 Maybye有些不同的整體設計? 另一種模式?其他模式?如果你想了解更多細節,請告訴我。 關於代碼,如果您更方便 ,您也可以提供等效的C++代碼。我對一個設計解決方案感興趣,從軟件工程的角度來看 ......不是語言特定的解決方案。

+0

您是否嘗試過定義更多抽象狀態並使用策略模式爲每個操作提供變化性?我的意思是,你有一般的國家:等待 - 選擇行動 - 建立行動 - 執行行動。該策略爲行爲建立了一般功能,並且每種可能的行爲(例如攻擊,法術,項目)都可以有其自己的具體實施,並且可以通過擴展來實施其他行動。如果需要,我可以繪製一些圖表。 – darlinton

+0

@darlinton我真的很想看到一些圖或maybye一些代碼,以哪一個更容易爲準。因此,如果對你沒有太大麻煩.. :-) – KonGous

+0

要針對多個if-else的問題,可以通過將每個案例封裝在類中的if-else中來使每個州具有一定的靈活性,然後您可以管理案例動態爲每個國家。 –

回答

1

我會使用策略模式不同的一點:

// The abstraction of all States 
public abstract class State 
{ 
    // All of them contain a reference to the system they belong to, 
    // so that they can "change/control" it 
    private BattleScene parent; 

    // Constructor 
    public State(BattleScene parent) 
    { this.parent = parent; } 

    // The actual input handling is to be represented by subclasses 
    public void input(int key) 
    { 
     switch(key) 
     { 
      case DOWN: 
       incIndex(); // Increases index safely by 1 
       break; 
      case UP: 
       decIndex(); // Decreases index safely by 1 
       break; 
      case ENTER: 
       activateAction(); 
       break; 
     } 
    } 

    protected abstract void activateAction(); 
} 



// A concrete State class, displaying a proper example 
public class ActionSelectState extends State 
{ 
    private String[] actions; // List of available actions 
    private int index; // The currently "highlighted" action 

    // Constructor 
    public ActionSelectState(BattleScene parent, String[] actions) 
    { 
     super(parent); 
     this.actions = actions; 
    } 


// THE ACTUAL PROBLEM - READ BELOW 
    @Override 
    protected void activateAction() 
    { 
     if(action.compareTo("Attack")==0) 
      parent.setState(new SelectTargetState(parent)); 
     else if(action.compareTo("Spell")==0) 
      parent.setState(new SelectSpellState(parent)); 
    } 
} 

如果input()方法始終是相同的,使用子類實現不同activateAction()方法(如果你需要捕捉不同的密鑰在input()方法,在子類中重寫此方法)。

而且,作爲旁註,我建議使用action.equals("Attack")而不是action.compareTo("Attack")==0

+0

只是好奇,爲什麼等於而不是compareTo? - 有用的改進,但仍然存在多個「if..else」的問題。不過,我感激不盡! – KonGous

+0

我認爲這是「更好」,因爲你的目標是檢查平等。如果你需要知道某物是大於還是小於另一物,則使用「compareTo」。但是,當然,這兩種方法都是正確的。關於多重「if..else」:我認爲你可以用'State'的子類的適當層次來解決這個問題? – user7291698