本文的目的是基于C语言实现简单高效的状态机。例子是倒计时bomb。Bomb有两种状态,一种是设置状态,一种是倒计时。一旦开始计时,要想回到设置状态必须要调整code的值等于bomb预设的密码值,否则无法进行状态转换。倒计时到0就BOMB了啦。基于这个例子来实现状态机。状态机实现框架包括以下几个部分:
1. 状态
enum BombStates {
SETTING_STATE,//设置
TIMING_STATE//倒计时
};
2. 触发状态转换的信号事件,用键盘模拟
enum BombSignals {
UP_SIG, //按u
DOWN_SIG,//按d
ARM_SIG,//按a,状态转换键
TICK_SIG//0.1秒发出一个倒计时事件
};
3. 信号事件的数据结构
typedef struct EventTag {
uint16_t sig; // BombSignals的赋值
/* 可以添加其他属性到这里 */
} Event;
此外,还要定义信号事件附带的参数:
typedef struct TickEvtTag {
Event super; //继承Event
uint8_t fine_time; //毫秒值,为0时代表倒计1秒
} TickEvt;
4. 状态全局变量
typedef struct Bomb1Tag {
uint8_t state; // BombStates状态赋值
uint8_t timeout; //当前倒计时间,为0游戏结束
uint8_t code; //用于调整数值,等于defuse密码才能转换状态
uint8_t defuse; //解除bomb的密码,需要预设
} Bomb1;
5. 状态初始化
#define INIT_TIMEOUT 10
#define TRAN(target_) (me->state = (uint8_t)(target_))
void Bomb1_ctor(Bomb1 *me, uint8_t defuse){
me->defuse = defuse;
}
void Bomb1_init(Bomb1 *me) {
me->timeout = INIT_TIMEOUT;
TRAN(SETTING_STATE);
}
6. 状态转换
void Bomb1_dispatch(Bomb1 *me, Event const*e) {
switch (me->state) {
case SETTING_STATE: {
switch (e->sig) {
case UP_SIG: {
if (me->timeout < 60){
++me->timeout;
BSP_display(me->timeout);
}
break;
}
case DOWN_SIG: {
if (me->timeout > 1){
--me->timeout;
&nb