最近的狀態極差,甚至代碼也寫不下去了。給自己手臂上的兩刀沒有任何的作用,看來早已經是麻痹了。
一直想弄一個勉強能用的狀態機,用於在各種涉及到狀態轉換的時候用到,然而腦子並不是太清醒。
先放在這里一個接口,以后會用到的。
狀態機主要由3部分組成: 狀態,輸入,轉換。可以在Input中實現狀態機的轉換藍圖;“狀態”可以用枚舉來表示。每當存在一個新的狀態,那么就需要繼承一次下面的接口。
其中的StateStack可以用來做下推自動機,這樣可以在狀態更新之后,用來還原之前的狀態。
如果一個對象擁有多個狀態,那么就要用到並發狀態機。這個原理大概是,這個對象的成員中存在兩個StateBase的子類對象。兩者既不相互干擾還能做到同時更新。
UpdateBegin 和 UpdateEnd用來定義狀態進出時的行為。但我總覺得,將它放在Input函數中而不是Update函數中更為合適。
C++14的代碼,VS2017。
1 #pragma once 2 #include <chrono> 3 #include <stack> 4 5 #define GetTimeNowMicroSec \ 6 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() 7 8 template<typename TState, typename TIn, typename TTarget> 9 class StateBase 10 { 11 private: 12 StateBase(); 13 14 public: 15 typename std::stack<StateBase<TState, TIn, TTarget>*> StateStack; //Pushdown Automation 16 17 StateBase(TState st); 18 virtual ~StateBase(); 19 20 public: 21 const TState& GetStateType() const; 22 23 public: 24 virtual void Input(TTarget& tag, TIn& input) = 0; 25 virtual void Updating(TTarget& tag) = 0; 26 27 virtual void UpdateBegin(TTarget& tag); 28 virtual void UpdateEnd(TTarget& tag); 29 virtual void Update(TTarget& tag); 30 31 template<class ST, 32 typename std::enable_if < 33 std::is_base_of<StateBase, ST>::value, ST 34 > ::type * = nullptr >> 35 virtual bool operator==(const ST& left, const ST& right) const 36 { 37 return left._st == right._st; 38 } 39 40 private: 41 TState _st; 42 time_t _time; //micro 43 }; 44 45 template<typename TState, typename TIn, typename TTarget> 46 inline StateBase<TState, TIn, TTarget>::~StateBase() 47 { 48 _time = 0; 49 } 50 51 template<typename TState, typename TIn, typename TTarget> 52 inline StateBase<TState, TIn, TTarget>::StateBase(TState st): 53 _st(st) 54 { 55 } 56 57 template<typename TState, typename TIn, typename TTarget> 58 inline const TState & StateBase<TState, TIn, TTarget>::GetStateType() const 59 { 60 return _st; 61 } 62 63 template<typename TState, typename TIn, typename TTarget> 64 inline void StateBase<TState, TIn, TTarget>::UpdateBegin(TTarget & tag) 65 { 66 _time = GetTimeNowMicroSec; 67 } 68 69 template<typename TState, typename TIn, typename TTarget> 70 inline void StateBase<TState, TIn, TTarget>::UpdateEnd(TTarget & tag) 71 { 72 _time = GetTimeNowMicroSec - _time; 73 } 74 75 template<typename TState, typename TIn, typename TTarget> 76 inline void StateBase<TState, TIn, TTarget>::Update(TTarget & tag) 77 { 78 UpdateBegin(tag); 79 Updating(tag); 80 UpdateEnd(tag); 81 }