日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

有限状态机(使用状态模式C++实现)

發(fā)布時(shí)間:2025/3/21 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 有限状态机(使用状态模式C++实现) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
最近在研究怪物的AI,由于怪物的AI是使用有限狀態(tài)機(jī)來實(shí)現(xiàn)的。所以就查看關(guān)于有限狀態(tài)機(jī)的東西。根據(jù)這幾天的查看資料,知道了有限狀態(tài)機(jī)是計(jì)算機(jī)科學(xué)中一個(gè)很重要的概念。而且有限狀態(tài)機(jī)是一個(gè)抽象的概念,具體實(shí)現(xiàn)是多種多樣的。根據(jù)維基百科的介紹,它是這樣的一個(gè)概念: 有限狀態(tài)機(jī) 英語:finite-state machine 縮寫 FSM )又稱 有限狀態(tài)自動(dòng)機(jī) ,簡(jiǎn)稱 狀態(tài)機(jī) ,是表示有限個(gè) 狀態(tài) 以及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的 數(shù)學(xué)模型

? 就像上面說的,既然是數(shù)學(xué)模型當(dāng)然有很多的實(shí)現(xiàn)方法。其實(shí)最簡(jiǎn)單容易想到的方法就是使用switch case的寫法:

[cpp] view plain copy
  • swtich(case)??
  • {??
  • case?STATE1:??
  • ????????do?something;??
  • ????????break;??
  • case?STATE2:??
  • ????????do?something;??
  • ????????break;??
  • .......??
  • }??
  • [cpp] view plain copy
  • 但是這種寫法會(huì)帶來很多的問題,首先是當(dāng)狀態(tài)多的時(shí)候,switch?case的語句會(huì)寫的很長(zhǎng),使得可讀性非常差。其次,可維護(hù)性也很差,每當(dāng)要添加一個(gè)狀態(tài)轉(zhuǎn)換時(shí),就要在Switch?case添加相應(yīng)的狀態(tài)轉(zhuǎn)換函數(shù)。會(huì)使得代碼變得冗長(zhǎng),難以擴(kuò)展。??
  • [cpp] view plain copy
  • 當(dāng)使用狀態(tài)模式寫狀態(tài)機(jī)的時(shí)候,每一個(gè)狀態(tài)就是一個(gè)類,添加狀態(tài)只需要添加一個(gè)狀態(tài)類就行了。在每一個(gè)類中實(shí)現(xiàn)相應(yīng)的狀態(tài)轉(zhuǎn)換函數(shù)。??
  • [cpp] view plain copy
  • 使用狀態(tài)模式的好處:??
  • [cpp] view plain copy
  • 1?每一個(gè)狀態(tài)就是一個(gè)類,便于擴(kuò)展,可讀性高??
  • [cpp] view plain copy
  • 2?每一個(gè)類有一個(gè)狀態(tài)轉(zhuǎn)換函數(shù),使得整個(gè)代碼的層次結(jié)構(gòu),很清晰??
  • [cpp] view plain copy
  • 當(dāng)然,沒有一個(gè)東西是完美的。使用狀態(tài)模式實(shí)現(xiàn)的時(shí)候,會(huì)使得類可能會(huì)變得很龐大。當(dāng)總的來說,還是好處大于壞處的。畢竟代碼不僅是出產(chǎn)品,還要考慮這個(gè)代碼的擴(kuò)展性還有可讀性。一個(gè)只實(shí)現(xiàn)了功能,但擴(kuò)展性很差,或者是除了你沒有人看得懂,或者是很難看懂的代碼,絕不是好代碼。簡(jiǎn)單高效才是我們程序員追求的目標(biāo)。??
  • [cpp] view plain copy
  • 一個(gè)很簡(jiǎn)單的例子,仿照電梯的例子:??
  • [cpp] view plain copy
  • <pre?style="color:?rgb(37,?37,?37);?margin-top:?0px;?margin-bottom:?0px;"><pre?style="margin-top:?0px;?margin-bottom:?0px;"><span?style="?color:#008000;">/************************************************************************</span>??
  • Des: 狀態(tài)機(jī),負(fù)責(zé)狀態(tài)的裝換 ************************************************************************/ #include "statemachine.h" #include "StateDefine.h" using namespace std; StateMachine::StateMachine() { //起始的狀態(tài)為停止?fàn)顟B(tài) m_currentState = m_lastState = STOP_STATE; } StateMachine::~StateMachine() { } /** * @brief 狀態(tài)機(jī)的初始化函數(shù),負(fù)責(zé)把每一個(gè)狀態(tài)的類放入Map中進(jìn)行管理 */ void StateMachine::init() { m_stateManager[0] = new CloseState(); m_stateManager[1] = new OpenState(); m_stateManager[2] = new UpState(); m_stateManager[3] = new DownState(); m_stateManager[4] = new StopState(); (m_stateManager[4])->handle(this); } /** * @brief 狀態(tài)裝換函數(shù),當(dāng)需要切換狀態(tài)的時(shí)候,只需要調(diào)用此函數(shù) * @param stateId :每一個(gè)狀態(tài)都有一個(gè)相應(yīng)的ID,定義在StateDefine的頭文件中 */ void StateMachine::changeState(int stateId) { if( stateId == m_currentState ) { cout<<"curent state is "<<stateId<<"doesn't transfrom state"<<endl; return; } else { int temp = m_lastState; m_lastState = m_currentState; m_currentState = stateId; std::map<int,State*>::iterator it = m_stateManager.find(stateId); if( it != m_stateManager.end() ) { if( !(it->second)->handle(this)) { m_currentState = m_lastState; m_lastState = temp; } } } } /** * @brief 獲得上次的狀態(tài) * @return 返回狀態(tài)ID */ int StateMachine::getLastState() { return m_lastState; } /** * @brief 獲得當(dāng)前的狀態(tài) * @return 返回狀態(tài)ID */ int StateMachine::getState() { return m_currentState; } 然后是每一個(gè)狀態(tài)的類: /************************************************************************ Des: 下落的狀態(tài) /************************************************************************/ #include "downstate.h" #include "StateDefine.h" #include "statemachine.h" using namespace std; DownState::DownState() { } DownState::~DownState() { cout<<"destructor downstate"<<endl; } /** * @brief 處理相應(yīng)的狀態(tài)裝換 * @param 傳入狀態(tài)機(jī) * @return */ bool DownState::handle(StateMachine* p_machine) { //判斷上次的狀態(tài)是否能正確切換到現(xiàn)在的狀態(tài) if( (p_machine->getLastState() != CLOSE_STATE) || (p_machine->getLastState() != STOP_STATE)) { if(p_machine->getLastState() != CLOSE_STATE) cout<<"the lift must be close!"<<endl; else cout<<"the lift must be stoped"<<endl; return false; } cout<<"the lift is downing "<<endl; return true; } /************************************************************************ Des:關(guān)閉的狀態(tài) /************************************************************************/ #include "closestate.h" #include "StateDefine.h" #include "statemachine.h" using namespace std; CloseState::CloseState() { } CloseState::~CloseState() { cout<<"destructor closestate"<<endl; } bool CloseState::handle(StateMachine* p_machine) { if( (p_machine->getLastState() != OPEN_STATE)) { cout<<"the lift must be closed!"<<endl; return false; } cout<<"the lift is closing "<<endl; return true; } /************************************************************************ * Des: 開啟的狀態(tài) /************************************************************************/ #include "openstate.h" #include "StateDefine.h" #include "statemachine.h" using namespace std; OpenState::OpenState() { } OpenState::~OpenState() { } bool OpenState::handle(StateMachine* p_machine) { if( p_machine->getLastState() != STOP_STATE ) { cout<<"the lift must be stop!"<<endl; return false; } cout<<"the lift is opening"<<endl; return true; } /************************************************************************ * Des: 停止的狀態(tài) /************************************************************************/ #include "stopstate.h" #include "statemachine.h" #include "StateDefine.h" using namespace std; StopState::StopState() { } StopState::~StopState() { } bool StopState::handle(StateMachine* p_machine) { if(p_machine->getLastState() == p_machine->getState()) { cout<<"the lift is stop "<<endl; return true; } if( p_machine->getLastState() == STOP_STATE ) { cout<<"the lift have already be stopping!"<<endl; return false; } cout<<"the lift is stop "<<endl; return true; } /************************************************************************ * Des: 上升的狀態(tài) /************************************************************************/ #include "upstate.h" #include "StateDefine.h" #include "statemachine.h" using namespace std; UpState::UpState() { } UpState::~UpState() { cout<<"destrucotor update"<<endl; } bool UpState::handle(StateMachine* p_machine) { if( p_machine->getLastState() != CLOSE_STATE ) { cout<<"the lift must be close!"<<endl; return false; } cout<<"the lift is uping"<<endl; return true; } 下面是公共的頭文件,定義了每一個(gè)狀態(tài)對(duì)應(yīng)的枚舉值,方便管理 /************************************************************************ * Des: 定義一個(gè)枚舉,每一個(gè)狀態(tài)對(duì)于一個(gè)值 /************************************************************************/ #ifndef STATEDEFINE_H #define STATEDEFINE_H enum{ CLOSE_STATE, OPEN_STATE, UP_STATE, DOWN_STATE, STOP_STATE, }; #endif // STATEDEFINE_H 下面是每一個(gè)狀態(tài)的父類,使用了虛函數(shù),使得對(duì)外的切換狀態(tài)的接口是統(tǒng)一的 /************************************************************************ * Des: 每一個(gè)狀態(tài)的父類,定義了虛函數(shù)(handle),每一個(gè)狀態(tài)都實(shí)現(xiàn)了這個(gè)函數(shù), * 實(shí)現(xiàn)狀態(tài)的切換具體實(shí)現(xiàn),多態(tài)的體現(xiàn) /************************************************************************/ #ifndef STATE_H #define STATE_H class StateMachine; class State { public: State(); virtual ~State(); virtual bool handle(StateMachine* p_machine) = 0; }; #endif // STATE_H 使用次狀態(tài)模式的具體類: /************************************************************************ * Des: 電梯的具體類,負(fù)責(zé)實(shí)現(xiàn)電梯的具體邏輯 /************************************************************************/ #include "lift.h" #include <iostream> #include "StateDefine.h" using namespace std; Lift::Lift() { } Lift::~Lift() { delete this->m_stateMachine; this->m_stateMachine = nullptr; } /** * @brief 電梯的初始化,使用按鍵模擬電梯的行為 */ void Lift::init() { this->m_stateMachine = new StateMachine(); this->m_stateMachine->init(); while (true) { cout<<"enter the value"<<endl; char str[8] = {0}; cin>>str; if( !strcmp(str,"c")) { this->m_stateMachine->changeState(CLOSE_STATE); } else if( !strcmp(str,"o")) { this->m_stateMachine->changeState(OPEN_STATE); } else if( !strcmp(str,"u")) { this->m_stateMachine->changeState(UP_STATE); } else if( !strcmp(str,"d")) { this->m_stateMachine->changeState(DOWN_STATE); } else if( !strcmp(str,"s")) { this->m_stateMachine->changeState(STOP_STATE); } } } 使用狀態(tài)模式確實(shí)使得使用避免過度的使用了IF ELSE 或者是Switch case,也使得整個(gè)的邏輯變得清晰可見。初探狀態(tài)模式,還有些不足,以后改進(jìn)!!(_~ ~_)
    [cpp] view plain copy
  • <pre?style="margin-top:?0px;?margin-bottom:?0px;">??
  • 總結(jié)

    以上是生活随笔為你收集整理的有限状态机(使用状态模式C++实现)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。