本篇內容主要講解“如何實現C++有限狀態機”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何實現C++有限狀態機”吧!
有限狀態機四大要素
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
#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++有限狀態機”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。