有限状态机和封闭

Fer*_*ndo 1 c# state design-patterns

最近在我的工作中我“被迫”学习正确编程。我正在阅读很多 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

不像网上的一些例子,我不踩播放器调用State的Update方法,也不像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();

    }
}
Run Code Online (Sandbox Code Playgroud)

我对这条线和 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));

    }
Run Code Online (Sandbox Code Playgroud)

我违反了几个隧道,状态在构造函数中接收一个实体类并处理 World(实体也在其构造函数中接收的游戏的主类)和 StateMachine,我仍在实例化一个新状态而不是使用正如单例模式 (http://www.ai-junkie.com/books/toc_pgaibe.html) 中推荐的那样。状态我没有使用静态,因为我不知道如何应用,因为各种状态不仅需要玩家或 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()) ?


    }
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 5

很难说如何以更“OO”的风格重写 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
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道你在用这个以前状态的缓存和所有这些采取行动和诸如此类的逻辑做什么。FSM 非常简单;状态的数量是有限的,输入的数量也是有限的,并且每个输入都会根据有关如何从一种状态转换到另一种状态的简单规则产生一个新状态。