2011-11-28 66 views
1

最近在我的工作中,我「強迫」學會正確編程。 我正在閱讀很多terns,DDD,TDD等。 推薦書籍「Clean Code」和「Refactoring to Patterns」,因爲它們非常好。最終,這導致我選擇了一些我準時實施的遊戲原型,並嘗試重新正確應用OOP,因爲從那時起,只需按照我的直覺(沒有研究任何東西)即可。有限狀態機和封閉

爲了實現這些遊戲的有限狀態機,我遇到了幾個問題。

public class StateMachine 
{ 
    private IState _globalState; 
    private IState _currentState; 
    private readonly List<IState> _previousStates; 

    public StateMachine(IState globalState, IState currentState) 
    { 
     _globalState = globalState; 
     _currentState = currentState; 
     _previousStates = new List<IState>(); 
    } 

    public void Execute() 
    { 
     if (_globalState != null) 
      _globalState.Update(); 
     if (_currentState != null) 
      _currentState.Update(); 
    } 

    public void ChangeState(IState state) 
    { 
     _previousStates.Add(_currentState); 
     _currentState.Exit(); 
     _currentState = state; 
     _currentState.Enter(); 
    } 

    public void BackToPreviousStates() 
    { 
     _currentState.Exit(); 
     _currentState = _previousStates[_previousStates.Count-1]; 
     _previousStates.Remove(_currentState); 
     _currentState.Enter(); 
    } 

    public void SetCurrentState(IState state) 
    { 
     _currentState = state; 
    } 

    public void SetGlobalState(IState state) 
    { 
     _globalState = state; 
    } 
} 

與互聯網的一些例子,我不踩玩家呼籲國家的更新方法,也沒有在普羅拉的StateMachine爲ViniGodoy的(例子http://sofiaia.wordpress.com/2008/07/11和...... -states /),因爲我無法理解爲什麼。

是一個國家的例子

public class RunAway : TargetState 
{ 
    public RunAway(IEntity entity, IEntity target) 
     : base(entity, target) 
    { 
    } 

    public override void Exit() 
    { 
     // throw new NotImplementedException(); 
    } 

    public override void Enter() 
    { 
     // throw new NotImplementedException(); 
    } 

    public override void Update() 
    { 
     if (Target.X > Entity.X) 
     { 
      Entity.Move(Key.Down); 
     } 


     Entity.StateMachine.BackToPreviousStates(); 

    } 
} 

我就行了,只是Entity.StateMachine.BackToPreviousStates(),因爲這是對OOP的模式,我附上我的實體的第一的StateMachine疑惑(玩家或敵人)。

的另一個問題是,在某些情況下,我會

public override void Update() 
    { 
     var enemy; 
      foreach (IEntity entity in Entity.World.Entities){ 

      if(entity .GetType() == typeOf(Enemy)) 
{ 
      enemy =(Enemy) entity; 
      break; 
} 
    } 

    if (enemy != null) 
     Entity.StateMachine.SetCurrentState(new RunAway(Entity, enemy)); 

    } 

我違反幾個隧道,國家接收在構造一個實體類和處理世界(主類遊戲,該實體還收到它的構造函數)和StateMachine,而且我仍然實例化一個新的狀態,而不是像Singleton模式推薦的那樣使用usal(http://www.ai-junkie.com/books/toc_pgaibe.html)。 國家我沒有使用Static,因爲我不知道如何申請,因爲各種狀態不僅需要玩家或StateMachine的信息,而且需要一個特定的環境(例如Runaway State需要他逃跑的敵人)。

我想的是如何改善這一實施意見,並沒有違反封裝....

[編輯]

爲清楚起見

public abstract class State : IState 
{ 
    private readonly IEntity _entity; 

    protected IEntity Entity 
    { 
     get { return _entity; } 
    } 

    protected State(IEntity entidade) 
    { 
     _entity = entidade; 
    } 

    public abstract void Exit(); 
    public abstract void Enter(); 
    public abstract void Update(); 
} 


public class Sleep: State 
{ 
    private int _time; 

    public Sleep(IEntity entidade) : base(entidade) 
    { 
    } 

    public override void Exit() 
    { 
     // _time = 0; 
    } 

    public override void Enter() 
    { 

     _time = 0; 
    } 

    public override void Update() 
    { 
     _time++; 

     if (_time == 20) 
      Entity.StateMachine.ChangeState(new Awake()); //<-- My Questions: Singletons ou instance? 
                 //  how to enclosing it? using Entity.ChangeState(new Awake()) ? 


    } 
} 
+3

你似乎認爲面向對象本身很好。面向對象是好的,因爲它降低了設計,構建和維護複雜軟件的成本,在這些複雜軟件中,不同團隊在不同時間構建了許多不同的組件,並且必須一起工作。如果這不是你所處的情況,你爲什麼要重寫「更多面向對象」風格的工作代碼?這只是一個學習練習,還是你真的有一個商業案例花費時間和精力做出不必要的改變? –

+0

我真的很想和遊戲一起工作,那麼專業代碼多少更好 –

+0

@FernandoMondo:你應該減少你遇到的問題。此外,建議通常不適合在此提出問題。您應該旨在揭示代碼中的特定問題,然後詢問這些問題。 – casperOne

回答

0

此代碼是很難理解,因爲您不會顯示StateMachine類或TargetState類的定義。你也不知道你實際上想要做什麼。

在數學上,一個state machine可以簡單地實現爲一個靜態枚舉單例。

顯然你想要做的比這更多......你究竟想要做什麼?

(我的猜測是,你正在實施actor pattern

+0

如果您可以查看此鏈接http://www.ai-junkie.com/architecture/state_driven/tut_state1.html,則TargetState僅保存目標和實體以避免重複 –

4

這真的很難說如何改寫你的FSM的代碼更「面向對象」的風格,因爲它似乎沒有什麼我都會想着首先是有限狀態機。一個有限狀態機的結構如下:

sealed class Machine 
{ 
    public readonly static State StartState = whatever; 
    public State CurrentState { get; private set; } 
    public Machine() 
    { 
     CurrentState = StartState; 
    } 
    public void ApplyNextInput(Input input) 
    { 
     CurrentState = ApplyPolicy(CurrentState, input); 
    } 
    private static State ApplyPolicy(State state, Input input) 
    { 
     // compute the new state based on the old state and the current input 
    } 
} 

我不知道你用這個緩存以前的狀態,並且所有這些邏輯採取行動和諸如此類的東西做的。 FSM非常簡單;存在有限數量的狀態,存在有限數量的輸入,並且基於關於如何從一個狀態轉換到另一個狀態的簡單規則,每個輸入產生新狀態。

+0

。對不起我英語不好... –