一个简单易用的C++有限状态机。
https://github.com/OpenMiniServer
请安装cmake工具,用cmake构建工程,可以在vs或者xcode上编译运行。
源代码:https://github.com/OpenMiniServer/openfsm
#克隆项目
git clone https://github.com/OpenMiniServer/openfsm
cd ./openfsm
#创建build工程目录
mkdir build
cd build
cmake ..
#如果是win32,在该目录出现openfsm.sln,点击它就可以启动vs写代码调试
make
./test
星舰有四种状态:地面压力测试(StateTest),点火发射升空(StateLaunch),回收返航(ActionReturn)和发射失败(StateFailure)。
每一个状态由几个行为组成。这样,多个行为组成一个状态,多个状态组成一个状态机。
状态切换。有两种状态切换。
在创建状态机之前,先进行动作注册。
OpenFSM::RegisterAction<ActionTestEngine>("ActionTestEngine");
OpenFSM::RegisterAction<ActionTestTank>("ActionTestTank");
OpenFSM::RegisterAction<ActionFireUp>("ActionFireUp");
OpenFSM::RegisterAction<ActionLaunch>("ActionLaunch");
OpenFSM::RegisterAction<ActionReturn>("ActionReturn");
OpenFSM::RegisterAction<ActionFailure>("ActionFailure");
选择一组动作,组成一个状态。共四个状态。
OpenFSM::RegisterState("StateTest", { "ActionTestEngine", "ActionTestTank" }, EStateTest);
OpenFSM::RegisterState("StateLaunch", { "ActionFireUp", "ActionLaunch" }, EStateLaunch);
OpenFSM::RegisterState("StateRecycle", { "ActionReturn" }, EStateRecycle);
OpenFSM::RegisterState("StateFailure", { "ActionFailure"}, EStateFailure);
指定状态可以切换到下一个状态。例如,星舰处理发射失败爆炸状态,那就无法切换到其他状态。
OpenFSM::RegisterRelation("StateTest", { "StateLaunch", "StateFailure" });
OpenFSM::RegisterRelation("StateLaunch", { "StateRecycle", "StateFailure" });
组装状态机,可以用状态名称或者id进行组装。
如果是传统火箭,只有三个状态StateTest, StateLaunch, StateFailure
星舰有回收状态,四个状态StateTest, StateLaunch, StateRecycle, StateFailure
openFSM_.setStates({ "StateTest", "StateLaunch", "StateRecycle", "StateFailure" });
openFSM_.setStates({ EStateTest, EStateLaunch, EStateRecycle, EStateFailure });
完整设计代码
#include <assert.h>
#include <time.h>
#include <math.h>
#include "openfsm.h"
using namespace open;
enum EFMSState
{
EStateTest = 100,
EStateLaunch = 101,
EStateRecycle = 102,
EStateFailure = 103,
};
struct StarShip
{
OpenFSM openFSM_;
void start()
{
std::srand((int)time(NULL));
openFSM_.setCustom(this);
// or openFSM_.setStates({ "StateTest", "StateLaunch", "StateRecycle", "StateFailure" });
openFSM_.setStates({ EStateTest, EStateLaunch, EStateRecycle, EStateFailure });
openFSM_.enterState(EStateTest);
}
bool testEngine() {return std::rand() % 3 == 0;}
bool testTank() {return std::rand() % 3 == 0;}
bool fireUp() {return std::rand() % 3 == 0;}
bool launch() {return std::rand() % 3 == 0;}
bool update()
{
openFSM_.update();
return openFSM_.focusEState() == EStateRecycle;
}
};
//StateTest
class ActionTestEngine: public OpenFSMAction
{
virtual void enter(OpenFSM& fsm) const
{
printf("[%s.%s] enter\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
virtual void update(OpenFSM& fsm) const
{
printf("[%s.%s] update\n", fsm.focusStateName().c_str(), actionName_.c_str());
if (fsm.custom<StarShip>()->testEngine())
{
printf("==>StarShip Engine Ok\n");
fsm.nextAction();
}
else
{
printf("==>StarShip Engine Bad\n");
fsm.nextState(EStateFailure);
}
}
virtual void exit(OpenFSM& fsm) const
{
printf("[%s.%s] exit\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
};
class ActionTestTank: public OpenFSMAction
{
virtual void enter(OpenFSM& fsm) const
{
printf("[%s.%s] enter\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
virtual void update(OpenFSM& fsm) const
{
printf("[%s.%s] update\n", fsm.focusStateName().c_str(), actionName_.c_str());
if (fsm.custom<StarShip>()->testTank())
{
printf("==>StarShip Tank Ok\n");
fsm.nextAction();
}
else
{
printf("==>StarShip Tank Bad\n");
fsm.nextState(EStateFailure);
}
}
virtual void exit(OpenFSM& fsm) const
{
printf("[%s.%s] exit\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
};
//StateLaunch
class ActionFireUp : public OpenFSMAction
{
virtual void enter(OpenFSM& fsm) const
{
printf("[%s.%s] enter\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
virtual void update(OpenFSM& fsm) const
{
printf("[%s.%s] update\n", fsm.focusStateName().c_str(), actionName_.c_str());
if (fsm.custom<StarShip>()->fireUp())
{
printf("==>StarShip FireUp Ok\n");
fsm.nextAction();
}
else
{
printf("==>StarShip FireUp Failed\n");
fsm.nextState(EStateFailure);
}
}
virtual void exit(OpenFSM& fsm) const
{
printf("[%s.%s] exit\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
};
class ActionLaunch : public OpenFSMAction
{
virtual void enter(OpenFSM& fsm) const
{
printf("[%s.%s] enter\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
virtual void update(OpenFSM& fsm) const
{
printf("[%s.%s] update\n", fsm.focusStateName().c_str(), actionName_.c_str());
if (fsm.custom<StarShip>()->launch())
{
printf("==>StarShip Launch Ok\n");
fsm.nextAction();
}
else
{
printf("==>StarShip Launch Failed\n");
fsm.nextState(EStateFailure);
}
}
virtual void exit(OpenFSM& fsm) const
{
printf("[%s.%s] exit\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
};
//StateRecycle
class ActionReturn : public OpenFSMAction
{
virtual void enter(OpenFSM& fsm) const
{
printf("[%s.%s] enter\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
virtual void update(OpenFSM& fsm) const
{
printf("[%s.%s] update\n", fsm.focusStateName().c_str(), actionName_.c_str());
printf("==>Congratulation! Complete mission!\n");
}
virtual void exit(OpenFSM& fsm) const
{
printf("[%s.%s] exit\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
};
//StateFailure
class ActionFailure : public OpenFSMAction
{
virtual void enter(OpenFSM& fsm) const
{
printf("[%s.%s] enter\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
virtual void update(OpenFSM& fsm) const
{
printf("[%s.%s] update\n", fsm.focusStateName().c_str(), actionName_.c_str());
printf("==>StarShip Launch again\n");
fsm.nextState(EStateTest);
}
virtual void exit(OpenFSM& fsm) const
{
printf("[%s.%s] exit\n", fsm.focusStateName().c_str(), actionName_.c_str());
}
};
int main()
{
OpenFSM::RegisterAction<ActionTestEngine>("ActionTestEngine");
OpenFSM::RegisterAction<ActionTestTank>("ActionTestTank");
OpenFSM::RegisterAction<ActionFireUp>("ActionFireUp");
OpenFSM::RegisterAction<ActionLaunch>("ActionLaunch");
OpenFSM::RegisterAction<ActionReturn>("ActionReturn");
OpenFSM::RegisterAction<ActionFailure>("ActionFailure");
OpenFSM::RegisterState("StateTest", { "ActionTestEngine", "ActionTestTank" }, EStateTest);
OpenFSM::RegisterState("StateLaunch", { "ActionFireUp", "ActionLaunch" }, EStateLaunch);
OpenFSM::RegisterState("StateRecycle", { "ActionReturn" }, EStateRecycle);
OpenFSM::RegisterState("StateFailure", { "ActionFailure"}, EStateFailure);
OpenFSM::RegisterRelation("StateTest", { "StateLaunch", "StateFailure" });
OpenFSM::RegisterRelation("StateLaunch", { "StateRecycle", "StateFailure" });
StarShip starShip;
starShip.start();
int count = 1000;
while (count-- > 0)
{
if (starShip.update())
break;
}
return getchar();
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有