最近在研究怪物的AI,由于怪物的AI是使用有限状态机来实现的。所以就查看关于有限状态机的东西。根据这几天的查看资料,知道了有限状态机是计算机科学中一个很重要的概念。而且有限状态机是一个抽象的概念,具体实现是多种多样的。根据维基百科的介绍,它是这样的一个概念: 有限状态机 ( 英语:finite-state machine , 缩写 : FSM )又称 有限状态自动机 ,简称 状态机 ,是表示有限个 状态 以及在这些状态之间的转移和动作等行为的 数学模型

就像上面说的,既然是数学模型当然有很多的实现方法。其实最简单容易想到的方法就是使用switch case的写法:

[cpp] view plain copy
  1. swtich(case)
  2. {
  3. case STATE1:
  4. do something;
  5. break;
  6. case STATE2:
  7. do something;
  8. break;
  9. .......
  10. }
[cpp] view plain copy
  1. 但是这种写法会带来很多的问题,首先是当状态多的时候,switch case的语句会写的很长,使得可读性非常差。其次,可维护性也很差,每当要添加一个状态转换时,就要在Switch case添加相应的状态转换函数。会使得代码变得冗长,难以扩展。
[cpp] view plain copy
  1. 当使用状态模式写状态机的时候,每一个状态就是一个类,添加状态只需要添加一个状态类就行了。在每一个类中实现相应的状态转换函数。
[cpp] view plain copy
  1. 使用状态模式的好处:
[cpp] view plain copy
  1. 1 每一个状态就是一个类,便于扩展,可读性高
[cpp] view plain copy
  1. 2 每一个类有一个状态转换函数,使得整个代码的层次结构,很清晰
[cpp] view plain copy
  1. 当然,没有一个东西是完美的。使用状态模式实现的时候,会使得类可能会变得很庞大。当总的来说,还是好处大于坏处的。毕竟代码不仅是出产品,还要考虑这个代码的扩展性还有可读性。一个只实现了功能,但扩展性很差,或者是除了你没有人看得懂,或者是很难看懂的代码,绝不是好代码。简单高效才是我们程序员追求的目标。
[cpp] view plain copy
  1. 一个很简单的例子,仿照电梯的例子:
[cpp] view plain copy
  1. <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: 状态机,负责状态的装换
************************************************************************/
#include "statemachine.h"
#include "StateDefine.h"
using namespace std;
StateMachine::StateMachine()
{
//起始的状态为停止状态
    m_currentState = m_lastState = STOP_STATE;
}
StateMachine::~StateMachine()
{
}
/**
 * @brief 状态机的初始化函数,负责把每一个状态的类放入Map中进行管理
 */
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 状态装换函数,当需要切换状态的时候,只需要调用此函数
 * @param stateId :每一个状态都有一个相应的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 获得上次的状态
 * @return 返回状态ID
 */
int StateMachine::getLastState()
{
    return m_lastState;
}
/**
 * @brief 获得当前的状态
 * @return 返回状态ID
 */
int StateMachine::getState()
{
    return m_currentState;
}

然后是每一个状态的类:

/************************************************************************
     Des: 下落的状态
/************************************************************************/
#include "downstate.h"
#include "StateDefine.h"
#include "statemachine.h"
using namespace std;
DownState::DownState()
{
}
DownState::~DownState()
{
    cout<<"destructor downstate"<<endl;
}
/**
 * @brief 处理相应的状态装换
 * @param 传入状态机
 * @return 
 */
bool DownState::handle(StateMachine* p_machine)
{
    //判断上次的状态是否能正确切换到现在的状态
    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:关闭的状态
/************************************************************************/
#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: 开启的状态
/************************************************************************/
#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: 停止的状态
/************************************************************************/
#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: 上升的状态 
/************************************************************************/
#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;
}

下面是公共的头文件,定义了每一个状态对应的枚举值,方便管理

/************************************************************************
 *  Des: 定义一个枚举,每一个状态对于一个值
/************************************************************************/
#ifndef STATEDEFINE_H
#define STATEDEFINE_H
enum{
    CLOSE_STATE,
    OPEN_STATE,
    UP_STATE,
    DOWN_STATE,
    STOP_STATE,
};
#endif // STATEDEFINE_H
下面是每一个状态的父类,使用了虚函数,使得对外的切换状态的接口是统一的
/************************************************************************
 *  Des: 每一个状态的父类,定义了虚函数(handle),每一个状态都实现了这个函数,
 *       实现状态的切换具体实现,多态的体现
/************************************************************************/
#ifndef STATE_H
#define STATE_H
class StateMachine;
class State
{
public:
    State();
    virtual ~State();
    virtual bool handle(StateMachine* p_machine) = 0; 
};
#endif // STATE_H

使用次状态模式的具体类:

/************************************************************************
 *   Des: 电梯的具体类,负责实现电梯的具体逻辑
/************************************************************************/
#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);
        }
    }
}

使用状态模式确实使得使用避免过度的使用了IF ELSE 或者是Switch case,也使得整个的逻辑变得清晰可见。初探状态模式,还有些不足,以后改进!!(_~ ~_)

[cpp] view plain copy
  1. <pre style="margin-top: 0px; margin-bottom: 0px;">

有限状态机(使用状态模式C++实现)相关推荐

  1. Java 有限状态机 (设计模式——状态模式)

    Java 有限状态机 (设计模式--状态模式) 编写代码的时候,有时会遇见较为复杂的swith...case...和if...else...语句.这一刻有时会想到状态机,用有限状态机替换swith.. ...

  2. 状态模式 - Unity(有限状态机)

    文章目录 状态模式(有限状态机) 结构 实现(有限状态机) 应用场景 优缺点 与其他模式的关系 状态模式(有限状态机) 状态模式是一种对象型模式,他将复杂的逻辑判断提取到不同状态对象中,允许状态对象在 ...

  3. 状态模式 有限状态机_有限状态机解释

    状态模式 有限状态机 The finite state machine (FSM) is a software design pattern where a given model transitio ...

  4. 【游戏设计模式】之三 状态模式、有限状态机

    转载自:https://blog.csdn.net/poem_qianmo/article/details/52824776 游戏开发过程中,各种游戏状态的切换无处不在.但很多时候,简单粗暴的if e ...

  5. 【游戏设计模式】之三 状态模式、有限状态机 Unity版本实现

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接: http://blog.csdn.net/poem_qianmo/article/details/52824776 作者:毛星云(浅 ...

  6. 状态模式、有限状态机 Unity版本实现

    游戏开发过程中,各种游戏状态的切换无处不在.但很多时候,简单粗暴的if else加标志位的方式并不能很地道地解决状态复杂变换的问题,这时,就可以运用到状态模式以及状态机来高效地完成任务.状态模式与状态 ...

  7. 【游戏设计模式】之三 状态模式 有限状态机 Unity版本实现

     本系列文章由@浅墨_毛星云 出品,转载请注明出处.    文章链接: http://blog.csdn.net/poem_qianmo/article/details/52824776  作者:毛星 ...

  8. 游戏开发设计模式之状态模式 有限状态机 c#委托事件(unity3d 示例实现)

    命令模式:游戏开发设计模式之命令模式(unity3d 示例实现) 对象池模式:游戏开发设计模式之对象池模式(unity3d 示例实现) 原型模式:游戏开发设计模式之原型模式 & unity3d ...

  9. 有限状态机FSM详解(2)——采用状态模式的FSM

    [状态模式] 状态模式主要解决的是当控制一个对象状态转换的条件判断过于复杂时,把判断逻辑转移到表示不同状态的一系列类中,从而简化复杂的逻辑判断.(如果状态转换条件判断很简单,就没必要用状态模式了) [ ...

最新文章

  1. Jquery JQZoom Plugin 放大鏡效果 Two
  2. 一道关于整型提升/截断的经典练习题
  3. cnblogs反对按钮点击测试
  4. 【朱-刘算法】【最小树形图】hdu6141 I am your Father!
  5. Java实现海明距离简单计算
  6. 中国科学院大学2014年数学分析高等代数考研试题
  7. P5488-差分与前缀和【NTT,生成函数】
  8. 基本数据结构 - 栈和队列
  9. apex您所在的地区目前不提供此物品_《APEX英雄》入门指南传奇篇-命脉
  10. 编程语言对比 面向对象
  11. python opencv去图片水印(图片底色为白色)
  12. ABP文档笔记 - 通知
  13. Idea的类注释和方法注释
  14. packet tracer配置ssh、telnet
  15. 自动秘钥密码(Autokey)
  16. 使用DiskMan(DiskGen)恢复被删除的分区
  17. 第九天 (集合 ArrayList)
  18. LeetCode——883. 三维形体投影面积
  19. 【SPSS】基础图形的绘制(条形图、折线图、饼图、箱图)详细操作过程
  20. PPTP协议详解及报文解析

热门文章

  1. 预装鸿蒙系统的手机,首款预装鸿蒙系统的手机入网,麒麟9000加持,型号亮了...
  2. ad 原理图差分线_Altium差分线如何从原理图到PCB布线?
  3. 计算机科学summer program,UCBLeadershipandInnovationSummerProgram加州大学伯克利分校夏季领导力创新课程.doc...
  4. 菜鸟刚入手Python第一天
  5. 顺序表应用8:最大子段和之动态规划法
  6. ACM《数据结构》顺序表
  7. 7.分布式数据库HBase第3部分
  8. Python-OpenCV 处理视频(一): 输入输出
  9. Java并发编程(8):多线程环境中安全使用集合API(含代码)
  10. 如何用 C++ 在 10 行内写出八皇后?