用C++来实现有限状态机(附代码)
来源:网络素材
整理:李肖遥
这篇文章主要为大家详细介绍了C++有限状态机的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
目录
有限状态机四大要素
C++函数指针实现
总结
前提:因为最近打算学设计模式的状态模式,但不是很明白有限状态机和状态模式之间的关系,索性用C++实现了一个简单案例复习了一下FSM,如果有更好的实现方法,欢迎留言
有限状态机四大要素
现态:当前所处状态
次态:当条件满足后,即将转移的下一个状态
动作:当满足某个事件时执行的动作;动作执行完毕后可以转移到另一个状态或保持原有状态
条件:转移状态所需的条件,当满足条件时,会触发一个动作或进行状态转移
C++函数指针实现
案例:学生的日常生活。
学生的日常生活包含以下几个状态:起床、上学、吃午饭、做作业、睡觉;
每个状态之间进行转移需要执行相应的事件。
我分为以下几个步骤来实现:
(1)绘制状态转移图
(2)创建状态转移的FSMItem类
枚举:所有状态State、所有事件Event;
成员变量:现态_curState、事件_event、次态_nextState
成员函数:动作函数
(3)创建有限状态机FSM类
成员变量:状态转移表vector<FSMItem*> _fsmTable
成员函数:初始化状态转移表、状态转移、根据事件执行相应动作
(4)测试FSM
(1)绘制状态转移图

(2)FSMItem类
//FSM状态项class FSMItem{friend class FSM;private://动作函数static void getUp(){cout << "student is getting up!" << endl;}static void go2School(){cout << "student is going to school!" << endl;}static void haveLunch(){cout << "student is having lunch!" << endl;}static void doHomework(){cout << "student is doing homework!" << endl;}static void sleeping(){cout << "student is sleeping!" << endl;}public://枚举所有状态enum State{GETUP = 0,GOTOSCHOOL,HAVELUNCH,DOHOMEWORK,SLEEP};//枚举所有事件enum Events{EVENT1 = 0,EVENT2,EVENT3};public://初始化构造函数FSMItem(State curState, Events event, void(*action)(), State nextState):_curState(curState), _event(event), _action(action), _nextState(nextState) {}private:State _curState; //现态Events _event; //条件void (*_action)(); //动作State _nextState; //次态};
(3)FSM类
class FSM{public://初始化状态机FSM(FSMItem::State curState= FSMItem::GETUP):_curState(curState){initFSMTable();}//状态转移void transferState(FSMItem::State nextState){_curState = nextState;}//根据当前状态和发生的事件,执行相应的动作,并进行状态转移void handleEvent(FSMItem::Events event){FSMItem::State curState = _curState; //现态void (*action)() = nullptr;//动作FSMItem::State nextState; //次态bool flag = false;for (int i = 0; i < _fsmTable.size(); i++){if (event == _fsmTable[i]->_event && curState == _fsmTable[i]->_curState){flag = true;action = _fsmTable[i]->_action;nextState = _fsmTable[i]->_nextState;break;}}//找到对应的状态项,执行动作,转移状态if (flag){if (action){action();}transferState(nextState);}}private://根据画的状态转移图初始化状态转移表void initFSMTable(){_fsmTable.push_back(new FSMItem(FSMItem::GETUP, FSMItem::EVENT1, &FSMItem::getUp, FSMItem::GOTOSCHOOL));_fsmTable.push_back(new FSMItem(FSMItem::GOTOSCHOOL, FSMItem::EVENT2, &FSMItem::go2School, FSMItem::HAVELUNCH));_fsmTable.push_back(new FSMItem(FSMItem::HAVELUNCH, FSMItem::EVENT3, &FSMItem::haveLunch, FSMItem::DOHOMEWORK));_fsmTable.push_back(new FSMItem(FSMItem::DOHOMEWORK, FSMItem::EVENT1, &FSMItem::doHomework, FSMItem::SLEEP));_fsmTable.push_back(new FSMItem(FSMItem::SLEEP, FSMItem::EVENT2, &FSMItem::sleeping, FSMItem::GETUP));}public:FSMItem::State _curState; //现态private:vector<FSMItem*> _fsmTable; //状态转移表};
(4)测试FSM
using namespace std;//测试事件变换void testEvent(FSMItem::Events& event){switch (event){case FSMItem::EVENT1:event = FSMItem::EVENT2;break;case FSMItem::EVENT2:event = FSMItem::EVENT3;break;case FSMItem::EVENT3:event = FSMItem::EVENT1;break;}}int main(){FSM *fsm = new FSM();auto event = FSMItem::EVENT1;while (1){cout << "event " << event << " is coming..." << endl;fsm->handleEvent(event);cout << "fsm current state is " << fsm->_curState << endl;testEvent(event);}return 0;}
执行效果:
总结
本篇文章就到这里了,希望能够给你带来帮助,后台回复 状态机 查看状态机的更多内容!
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
关注我的微信公众号,回复“加群”按规则加入技术交流群。
点击下面图片,有星球具体介绍,新用户有新人优惠券,老用户半价优惠,期待大家一起学习一起进步。
点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

