Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >OpenFSM是全网最好用的C++有限状态机

OpenFSM是全网最好用的C++有限状态机

原创
作者头像
linyouhappy
修改于 2023-07-20 09:32:57
修改于 2023-07-20 09:32:57
1.9K0
举报
文章被收录于专栏:OpenLinyouOpenLinyou

OpenFSM

一个简单易用的C++有限状态机。

https://github.com/OpenMiniServer

编译和执行

请安装cmake工具,用cmake构建工程,可以在vs或者xcode上编译运行。

源代码:https://github.com/OpenMiniServer/openfsm

代码语言:txt
AI代码解释
复制
#克隆项目
git clone https://github.com/OpenMiniServer/openfsm
cd ./openfsm
#创建build工程目录
mkdir build
cd build
cmake ..
#如果是win32,在该目录出现openfsm.sln,点击它就可以启动vs写代码调试
make
./test

全部源文件

  • src/openfsm.h
  • src/openfsm.cpp

有限状态机设计星舰

星舰有四种状态:地面压力测试(StateTest),点火发射升空(StateLaunch),回收返航(ActionReturn)和发射失败(StateFailure)。

每一个状态由几个行为组成。这样,多个行为组成一个状态,多个状态组成一个状态机。

  1. 地面压力测试(StateTest):引擎测试(ActionTestEngine)和燃料罐测试(ActionTestTank);
  2. 点火发射升空(StateLaunch):星舰点火(ActionFireUp)和发射升空(ActionLaunch);
  3. 回收返航(ActionReturn):返回地面回收(ActionReturn);
  4. 发射失败(StateFailure):发射失败(ActionFailure);

状态切换。有两种状态切换。

  1. 地面压力测试(StateTest)如果成功,就切换到点火发射升空(StateLaunch),否则,切换到发射失败(StateFailure)
  2. 点火发射升空(StateLaunch)如果成功,就切换到回收返航(ActionReturn),否则,切换到发射失败(StateFailure)

在创建状态机之前,先进行动作注册。

代码语言:C++
AI代码解释
复制
OpenFSM::RegisterAction<ActionTestEngine>("ActionTestEngine");
OpenFSM::RegisterAction<ActionTestTank>("ActionTestTank");
OpenFSM::RegisterAction<ActionFireUp>("ActionFireUp");
OpenFSM::RegisterAction<ActionLaunch>("ActionLaunch");
OpenFSM::RegisterAction<ActionReturn>("ActionReturn");
OpenFSM::RegisterAction<ActionFailure>("ActionFailure");

选择一组动作,组成一个状态。共四个状态。

代码语言:C++
AI代码解释
复制
    OpenFSM::RegisterState("StateTest", { "ActionTestEngine", "ActionTestTank" }, EStateTest);
    OpenFSM::RegisterState("StateLaunch", { "ActionFireUp", "ActionLaunch" }, EStateLaunch);
    OpenFSM::RegisterState("StateRecycle", { "ActionReturn" }, EStateRecycle);
    OpenFSM::RegisterState("StateFailure", { "ActionFailure"}, EStateFailure);

指定状态可以切换到下一个状态。例如,星舰处理发射失败爆炸状态,那就无法切换到其他状态。

代码语言:C++
AI代码解释
复制
OpenFSM::RegisterRelation("StateTest", { "StateLaunch", "StateFailure" });
OpenFSM::RegisterRelation("StateLaunch", { "StateRecycle", "StateFailure" });

组装状态机,可以用状态名称或者id进行组装。

如果是传统火箭,只有三个状态StateTest, StateLaunch, StateFailure

星舰有回收状态,四个状态StateTest, StateLaunch, StateRecycle, StateFailure

代码语言:C++
AI代码解释
复制
openFSM_.setStates({ "StateTest", "StateLaunch", "StateRecycle", "StateFailure" });
openFSM_.setStates({ EStateTest, EStateLaunch, EStateRecycle, EStateFailure });

完整设计代码

代码语言:C++
AI代码解释
复制
#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 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
一个有限状态机的C++实现
先放一个用C++11实现的FSM的代码: kuafu 咱们先来看一下什么是有限状态机(Finite-state machine, FSM), 先给一个 百度百科的解释 简单说就是作一件事可能会经
扫帚的影子
2018/09/05
3.6K0
一个有限状态机的C++实现
AI 助力游戏开发实践-有限状态机
在数字娱乐产业中,游戏开发无疑是最具活力和创新性的领域之一。随着技术的进步和玩家需求的日益增长,游戏开发者面临着前所未有的挑战和机遇。游戏不仅要在图形和玩法上不断创新,还要提供流畅的用户体验和智能的游戏逻辑。在这样的背景下,有限状态机(FSM)成为了游戏开发中一个不可或缺的工具,它为游戏角色和系统的行为提供了一种清晰、可控的实现方式。
腾讯云开发者
2025/01/09
2670
AI 助力游戏开发实践-有限状态机
【Unity】高级——有限状态机
有限状态机是unity游戏开发中经常用到的一个概念,能制作敌人AI,玩家控制器等。
鸡先生
2023/05/01
2.3K0
【Unity】高级——有限状态机
AI 助力游戏开发实践-有限状态机
本文用实际案例讲述了腾讯 AI 代码助手是如何在 FSM 的开发过程中提供了高效的代码补全、优化和知识共享支持,显著提升了开发效率和代码质量的。
腾讯云代码助手
2025/01/08
910
有限状态机模型
在阅读harbor源码时,在jobservice代码中,发现实现了一个有限状态机。状态管理在系统设计中常被使用。通过实现它,可以方便的对程序的状态进行管理。状态在现实生活中,有很多存在的例子。例如,灯有开,关两种状态,当然如果较真的话,中间还可以有多个亮度的状态。红绿灯,登录状态,程序的生命周期等等,这个太多了。
暮雨
2018/11/15
1.7K0
有限状态机模型
关于有限状态机(FSM)的一些思考
有限状态机,英文翻译是 Finite State Machine,缩写为 FSM,简称为状态机。状态机有 3 个组成部分:状态(State)、事件(Event)、动作(Action)。其中,事件也称为转移条件(Transition Condition)。事件触发状态的转移及动作的执行。动作也不是必须的,也可能只转移状态,不执行任何动作。
巫山老妖
2023/09/24
2.4K0
关于有限状态机(FSM)的一些思考
【Socket】有限状态机
有限状态机 相关来源及参考-部分在具体模块有指明 《Linux高性能服务器编程》-游双 ---- 定义 维基百科: 在编程中有限状态机(finite state)是服务器程序逻辑单元内部的一种高效编程方法。 个人理解为控制程序执行的一个变量或是一段程序,根据这个变量或是程序的有限结果进行对应的操作。 有的应用层协议头部包含数据包类型字段,每种类型可以映射为逻辑单元的一种执行状态,服务器可以根据它来编写相应的处理逻辑,如下所示代码: STATE_MACHINE(Package _pack
半生瓜的blog
2023/05/13
5050
【Socket】有限状态机
相亲模型与有限状态机
如果有人问你需要几步可以把大象关进冰箱里,你脑海中肯定浮现起宋大妈的笑容并脱口而出:3步。
CS实验室
2022/08/01
4990
相亲模型与有限状态机
Go每日一库之134:fsm(基有限状态机库)
开发中,我们经常会遇到这种情况,服务模块有多种状态,它们有一定的顺序,先后执行,逐步切换。这时,fsm这个库可以帮助我们更好的管理多个状态。
luckpunk
2023/09/30
1.6K0
基于FPGA的有限状态机浅析
本文介绍了状态机在数字电路设计中的重要性,并通过一个简单的示例详细说明了状态机的实现过程。
NingHeChuan
2018/01/05
1.4K0
基于FPGA的有限状态机浅析
基于 Kotlin 特性开发的有限状态机
状态机是古老的计算机理论,在游戏开发、嵌入式开发、网络协议等领域,得到广泛地使用。
fengzhizi715
2020/02/25
1.5K0
基于 Kotlin 特性开发的有限状态机
有限状态机FSM的原理与GO的实现
有限状态机(Finite-state machine, 简写FSM)又可以称作有限状态自动机。它必须是可以附着在某种事物上的,且该事物的状态是有限的,通过某些触发事件,会让其状态发生转换。为此,有限状态机就是描述这些有限的状态和触发事件及转换行为的数学模型。 有限状态机组成 有限状态机有两个必要的特点,一是离散的,二是有限的。基于这两点,现实世界上绝大多数事物因为复杂的状态而无法用有限状态机表示。 而描述事物的有限状态机模型的元素由以下组成: 状态(State):事物的状态,包括初始状态和所有事件触发后的状
李海彬
2018/03/28
3.6K0
有限状态机FSM的原理与GO的实现
如何以面向对象的思想设计有限状态机
有限状态机又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型,用英文缩写也被简称为 FSM。
wenzid
2020/05/03
1.4K0
如何以面向对象的思想设计有限状态机
JavaScript与有限状态机
有限状态机(Finite-state machine)是一个非常有用的模型,可以模拟世界上大部分事物。 简单说,它有三个特征:   * 状态总数(state)是有限的。   * 任一时刻,只处在一
ruanyf
2018/04/12
1K0
JavaScript与有限状态机
如何用有限状态机识别地址的有效性?
在收发快递填写地址的时候,我们会经常手动输入地址让程序智能识别,标准的地址比如,xx省xx市xx县/区xx路xx号,不过有时候也可以简单写:xx市xx县/区xx路xx号,或者xx省xx县/区xx路xx号,或者xx市xx路xx号。
somenzz
2021/09/14
5580
超轻量级有限状态机Mini-FSM
有限状态机(Finite State Machine,简称FSM),表示有限个状态以及在这些状态之间的转移和动作等行为的处理模型。在任何给定的时间点,有限状态机都处于某一特定状态,并且可以根据当前状态和输入条件,从当前状态转移到另一个状态。有限状态机相关的核心概念主要包括:
Yiwenwu
2024/05/18
9100
超轻量级有限状态机Mini-FSM
有限状态机抽取地址
有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
DC童生
2019/07/26
1K0
有限状态机抽取地址
嵌入式中状态机的几种骚操作
状态机可以分为状态和事件 ,状态的跃迁都是受事件驱动的,因此可以通过一个二维表格来表示状态的跃迁。
混说Linux
2023/02/24
1.1K0
嵌入式中状态机的几种骚操作
如何基于FSM有限状态机实现Enemies AI
本文简单介绍如何基于FSM有限状态机实现Enemies AI,首先定义敌人的AI逻辑:默认状态下Enemy为巡逻状态,有若干巡逻点位,Enemy在这些点位之间来回巡逻走动,同时检测Player的位置,当Player进入一定范围内时,Enemy进入寻路状态,寻路到Player位置前,进入Attacking攻击状态,当Player离开一定距离时,Enemy重回巡逻状态进行巡逻。
CoderZ
2022/12/26
6760
如何基于FSM有限状态机实现Enemies AI
122. 精读《robot 源码 - 有限状态机》
有限状态机是指有限个数的状态之间相互切换的数学模型,在业务与游戏开发中有限状态都很常见,包括发请求也是一种有限状态机的模型。
黄子毅
2022/03/14
5050
122. 精读《robot 源码 - 有限状态机》
相关推荐
一个有限状态机的C++实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档