我是靠谱客的博主 幽默宝马,这篇文章主要介绍C++有限状态机实现详解,现在分享给大家,希望可以做个参考。

前提:因为最近打算学设计模式的状态模式,但不是很明白有限状态机和状态模式之间的关系,索性用C++实现了一个简单案例复习了一下FSM,如果有更好的实现方法,欢迎留言

有限状态机四大要素

  • 现态:当前所处状态
  • 次态:当条件满足后,即将转移的下一个状态
  • 动作:当满足某个事件时执行的动作;动作执行完毕后可以转移到另一个状态或保持原有状态
  • 条件:转移状态所需的条件,当满足条件时,会触发一个动作或进行状态转移

C++函数指针实现

案例:学生的日常生活。

  • 学生的日常生活包含以下几个状态:起床、上学、吃午饭、做作业、睡觉;
  • 每个状态之间进行转移需要执行相应的事件。

我分为以下几个步骤来实现:

  • (1)绘制状态转移图
  • (2)创建状态转移的FSMItem类
    • 枚举:所有状态State、所有事件Event;
    • 成员变量:现态_curState、事件_event、次态_nextState
    • 成员函数:动作函数
  • (3)创建有限状态机FSM类
    • 成员变量:状态转移表vector<FSMItem*> _fsmTable
    • 成员函数:初始化状态转移表、状态转移、根据事件执行相应动作
  • (4)测试FSM

(1)绘制状态转移图

(2)FSMItem类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//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类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<iostream> #include<vector> 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; }

执行效果:

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注靠谱客的更多内容!

最后

以上就是幽默宝马最近收集整理的关于C++有限状态机实现详解的全部内容,更多相关C++有限状态机实现详解内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(109)

评论列表共有 0 条评论

立即
投稿
返回
顶部