利用回调函数实现有限自动机

Action,每种状态下的具体操作,eOnEntry,进入改装态时执行一次; eDo, 处于在该状态时便一直执行; eOnExit, 推出状态时执行一次; eOnEvent, 当该状态接收到某一事件时执行一次, 如果接受到某一事件开始需要执行一连串的动作, 则应考虑状态的转移;


State, 状态,每种状态维护 1--输入事件和回调函数的映射关系,2--输入事件和状态转移的关系;


Transition, 就是转移表的元素,输入事件与下一个状态的映射;


StateMachine,状态机,接受输入事件,内部决定是执行相应操作还是进行转台转移;


#pragma once 


template<typename T>
class Action
{
  typedef void (T::*ActionFunc)();


public:
  Action():m_iId(0),m_iEventId(0),m_iMaxEventNum(6),m_pFunc(NULL)
  {
    
  }


  Action(int id, int iEventId, ActionFunc pFunc):
  m_iId(id),
  m_iEventId(iEventId),
  m_iMaxEventNum(6),
  m_pFunc(pFunc)
  {
    
  }


  virtual ~Action()
  {


  }


  void SetId(int iId) { m_iId = iId; }
  int GetId() const { return m_iId; }


  void SetType(int iType) { m_iType = iType; }
  int GetType() const { return m_iType; }


  void SetEventId(int iEventId) { m_iEventId = iEventId; }
  int GetEventId() const { return m_iEventId; }


  void SetActionFunc(ActionFunc pActionFunc) { m_pFunc = pActionFunc; }
  ActionFunc GetActionFunc() const { return m_pFunc; }


  void Execute(T* pt)
  {
    if(m_pFunc!=NULL)
    {
      (pt->*m_pFunc)();
    }
  }


  enum eWhen
  {
    eOnEntry = 0,	// Action taken on entering the state
    eDo,			// Action taken during entering the state until leaving the state
    eOnExit,		// Action taken on leaving the state
    eOnEvent		// Action taken based on the event received
    // - Specify Event, Arguments, and Condition
  };


  enum eType
  {
    eAction = 0,	
    eSendEvent		
  };


private:
  int m_iId;
  int m_iType;
  int m_iEventId; // the event trigger this action


  int m_iMaxEventNum;
  ActionFunc m_pFunc;
};


#pragma once 

class Transition
{
public:
  void SetEventId(int iEventId) { m_iEventId = iEventId; }
  int GetEventId() const { return m_iEventId; }

  void SetNextStateId(int iNextStateId) { m_iNextStateId = iNextStateId; }
  int GetNextStateId() const { return m_iNextStateId; }

private:
  int m_iEventId;
  int m_iNextStateId;
};


#pragma once

#include <map>

#include "State.h"
#include "Action.h"
#include "Transition.h"


template<typename T>
class State
{
  typedef void (T::*ActionFunc)();
  typedef std::map<int, Transition*> TransitionMap;
  typedef std::map<int, Action<T>*> ActionMap;

public:
  State(T* pInstance) { m_pInstance = pInstance; }
  virtual ~State(){ m_pInstance=NULL; }
public:
  virtual bool Enter( int iEvent = 0 );

  virtual bool DoOnce( int iEvent );

  virtual void Run();

  virtual int Exit( int iEvent );

  //
  void AddTransition (int iEventId, int iStateId);

  void AddAction (int when, int type, int id, ActionFunc funcPtr);	// Set default action

  void AddAction (int when, int type, int id, int Eventid, ActionFunc funcPtr);	// Set OnEvent action

  void SetId(int iId) { m_iId = iId; }
  int GetId() const { return m_iId; }

  void SetInstance(T* pInstance) { m_pInstance = pInstance; }
  T* GetInstance() const { return m_pInstance; }

  int GetEventNum() const { return m_iEventNum; }

  int GetMaxEventNum() const { return m_iMaxEventNum; }

  int GetTransitionNum() const;// 

private:
  T* m_pInstance;

  int m_iId;
  int m_iEventNum; // 事件数
  int m_iMaxEventNum; 

  ActionMap m_mapActions; // 操作列表,key-- enter,do,exit,event
  TransitionMap m_mapTransitions; // 转移函数表,key--EventId
};


template<typename T>
bool State<T>::Enter( int iEvent )
{
  if (m_mapActions.size() > 2)// 0,1,2为固定事件
  {
    ActionMap::iterator iter = m_mapActions.find(Action<T>::eOnEvent);
    for(iter;iter!=m_mapActions.end();++iter)
    {
      Action<T>* pAction = iter->second;
      if(pAction->GetEventId()==iEvent)
      {
        pAction->Execute(m_pInstance);
      }
    }
  }

	ActionMap::iterator iter = m_mapActions.find(Action<T>::eOnEntry);
	if(iter!=m_mapActions.end())
	{
	  Action<T>* pAction = iter->second;
	  if(pAction) pAction->Execute(m_pInstance);
	}

    return true;
}

template<typename T>
void State<T>::Run()
{
	ActionMap::iterator iter = m_mapActions.find(Action<T>::eDo);
	if(iter!=m_mapActions.end())
	{
		Action<T>* pAction = iter->second;
		if(pAction) pAction->Execute(m_pInstance);
	}
}

template<typename T>
bool State<T>::DoOnce( int iEvent )
{
	ActionMap::iterator iter = m_mapActions.find(Action<T>::eOnEvent);
	if(iter!=m_mapActions.end())
	{
		Action<T>* pAction = iter->second;
		if(pAction)
		{
			if( pAction->GetEventId()==iEvent )
			{
				pAction->Execute(m_pInstance);

				return true;
			}
		}
	}

	return false;
}

template<typename T>
int State<T>::Exit( int iEvent )
{
  // Find the State to which this event is tied to
  TransitionMap::iterator iter = m_mapTransitions.find(iEvent);
  if(iter!=m_mapTransitions.end())
  {
    Transition* pTransition = iter->second;

    ActionMap::iterator iterAc = m_mapActions.find(Action<T>::eOnExit);
    if(iterAc!=m_mapActions.end())
    {
      Action<T>* pAction = iterAc->second;
      if(pAction)
      {
        pAction->Execute(m_pInstance);
      }
    }

    if(pTransition)
    {
      return pTransition->GetNextStateId();
    }
  }

  return -1;
}


template<typename T>
void State<T>::AddTransition (int iEventId, int iStateId)
{
  // Add a transition to the list
  if (m_mapTransitions.size() < m_iMaxEventNum)
  {
    Transition* pTransition = new Transition;
    pTransition->SetEventId( iEventId );
    pTransition->SetNextStateId( iStateId );

    m_mapTransitions.insert(TransitionMap::value_type(iEventId,pTransition));
  }
}

template<typename T>
void State<T>::AddAction(int when, int type, int id, ActionFunc funcPtr)
{
  if ( (when == Action<T>::eOnEntry) 
    || (when == Action<T>::eDo) 
    || (when == Action<T>::eOnExit) )
  {
    if ( type == Action<T>::eAction )
    {
      Action<T>* pAction = new Action<T>;
      pAction->SetId(id);
      pAction->SetType(type);
      pAction->SetActionFunc(funcPtr);

      m_mapActions.insert(ActionMap::value_type(when,pAction));
    }
  }
}

template<typename T>
void State<T>::AddAction(int when, int type, int id, int Eventid, ActionFunc funcPtr)
{
  if ( (when == Action<T>::eOnEvent) )
  {
    if ( (type == Action<T>::eAction) && (m_mapActions.size() < m_iMaxEventNum) )
    {
      Action<T>* pAction = new Action<T>;
      pAction->SetId(id);
      pAction->SetType(type);
      pAction->SetActionFunc(funcPtr);
      pAction->SetEventId(Eventid);

      m_mapActions.insert(ActionMap::value_type(when,pAction));
    }
  }
}

#pragma once

#include <list>
#include "State.h"
#include "../../Game/GameEvent.h"

template<typename T>
class StateMachine
{
  typedef std::list<State<T>*> StateList;

public:
  StateMachine(){}

  virtual ~StateMachine()
  {
	  DeleteSTLContainer( m_listStates );
  }

public:

  virtual bool InEvent (int iEvent = 0);

  virtual bool OnEvent(int iEvent);

  virtual bool OutEvent (int iEvent);

  virtual void AddState( State<T> * pState );

  virtual State<T>* CreateState(T* pT);
  //
  State<T>* GetCurState() const { return m_pCurState; }
  void SetCurState(State<T>* pState) { m_pCurState = pState; }

  State<T>* GetState(int iStateId);
private:
  StateList m_listStates;
  State<T>* m_pCurState;
};

template<typename T>
bool StateMachine<T>::InEvent (int iEvent)
{
  if( GetCurState() != NULL )
  {
    return GetCurState()->Enter(iEvent);
  }

  return false;
}

template<typename T>
bool StateMachine<T>::OutEvent (int iEvent)
{
  if( !m_listStates.empty() && GetCurState() )
  {
    State<T>* pNextState = GetState( GetCurState()->Exit(iEvent) );

    if(pNextState!=NULL)
    {
      SetCurState(pNextState);

      return GetCurState()->Enter(iEvent);
    }
	else
	{
		return OnEvent(iEvent);
	}

  }

  return false;
}

template<typename T>
bool StateMachine<T>::OnEvent (int iEvent)
{
	if( GetCurState() )
	{
		return GetCurState()->DoOnce(iEvent);
	}

	return false;
}


template<typename T>
State<T>* StateMachine<T>::CreateState(T* pT)
{
	State<T>* pState = new State<T>(pT);

	m_listStates.push_back(pState);

	SetCurState( pState );

	return pState;
}

template<typename T>
void StateMachine<T>::AddState( State<T> * pState )
{
  m_listStates.push_back(pState);

  SetCurState( pState );
}

template<typename T>
State<T>* StateMachine<T>::GetState(int iStateId)
{
  State<T>* pState = NULL;
  StateList::iterator iter = m_listStates.begin();
  for(iter;iter!=m_listStates.end();++iter)
  {
    if((*iter)->GetId() == iStateId)
    {
      pState = (*iter);
      break;
    }
  }

  return pState;
}

~ 欢迎留言讨论 ~    代码调试通过可使用,转载请注明出处,谢谢 ~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值