状态机(State Machine)是一个抽象概念,是一个逻辑严谨的数学抽象。它的这种概念在现实生活中处处都有应用,或者说现实世界就充满状态机。要讨论状态机,就涉及到相关概念,比如:State 状态,Event 事件,Action 动作,Transition 转换。状态机是计算机科学的重要基础概念之一,也可以说是一种总结归纳问题的思想,应用范围非常广泛。[1]

如果要便于理解,那么举灯开关现象的例子是最合适不过的!灯有两种状态:开和关,而状态间的转换是瞬间完成的,由开关动作触发转换,而整个触发转换的过程就是事件,如图:

那么上述就是灯的“状态机”。它描述了灯运行时的情况,有了这个,那么用程序逻辑就可以很好地解释它,模拟它,不然太过于具象了,很难用逻辑去表示它。

当然状态机还分类别,不同的事物抽象出来的状态机都不尽相同,而且结构都不一样。当然,它也有共通性[2]:

(1)可用“状态”来描述事物,并且任一时刻,事物总是处于一种状态

(2)事物拥有的状态总数是有限的,所以学名成为“有限状态机”(Finite-state machine, FSM)

(3)通过触发事物的某些行为,可以导致事物从一种状态过渡到另一种状态(自动机制)

(4)事物状态变化是有规则的,例如:A状态可以变换到B,B可以变换到C,A却不一定能变换到C

(5)同一种行为,可以将事物从多种状态变成同种状态,但是不能从同种状态变成多种状态

总之,它是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。看一些比较复杂的状态机模型:

<来自百度图片搜索>

笔者才疏学浅,就此对状态机介绍到这,读者感兴趣还想了解可自行查阅相关文档。


既然状态机很重要,那么在Processing的应用中也不可避免地会使用到相关概念和技术。早在2017年笔者就以状态量概念探讨了在Processing程序中的应用,见下文:

https://blog.csdn.net/fddxsyf123/article/details/62848357 ---Processing 状态量控制动画技巧

当然那没有机(系统)的概念。这次就以最简单的一种形式来初探-----线性的状态切换的情况

情景设计:

【一个装置有三盏灯组成,依次标为A、B、C。只有一个按钮用于转换装置状态,该装置可通过按钮或者自行的触发器依次循环点亮A、B、C三盏灯。】

我们画一张状态机示例:

代码实现

State类:

class State
{
boolean canChange = true;
int temp = 0;
void Enter() {
temp = 0;
println(this.getClass().getName()+" - Enter !");
} void Update() {
//println(this.getClass().getName()+" - Update !");
temp ++;
} void Exit() {
println(this.getClass().getName()+" - Exit !");
}
}

设了EnterUndateExit三个方法模拟状态的进入、执行(保持)、退出的过程,还有一个temp变量,只是临时为了调试方便设计的,方便查看Update方法的执行与否。这里其实可以设为抽象类,更科学。

StateMachine类:

class StateMachine
{
State currentState;
State lastState; StateMachine(State initState)
{
SwitchTo(initState);
} public void SwitchTo(State newState)
{
if (currentState!=null)
{
this.lastState = currentState;
lastState.Exit();
}
currentState = newState;
currentState.Enter();
} public void Update()
{
this.currentState.Update();
}
}

存有当前状态旧时状态,并赋予SwitchTo()Update()两个方法,依次分别是切换状态方法执行状态方法

Operator类:

class Operator
{
public StateMachine stateMachine;
private ArrayList<State> states;
private boolean mousePressedThisFrame = false; boolean ischecked = false; Operator()
{
states = new ArrayList<State>();
this.states.add(new StageA());
this.states.add(new StageB());
this.states.add(new StageC());
stateMachine = new StateMachine(states.get(0));
} void NextStage()
{
if (states.size() > 0)
{
State firstStage = states.remove(0);
states.add(firstStage);
stateMachine.SwitchTo(states.get(0));
}
} void setChecked()
{
ischecked = true;
} void Update()
{
if ((mousePressed && !mousePressedThisFrame) || ischecked)
{
mousePressedThisFrame = true;
ischecked = false;
if (stateMachine.currentState.canChange)
{
println("try Change To Next Stage.");
this.NextStage();
}
} this.stateMachine.Update(); if (!mousePressed && mousePressedThisFrame)
{
mousePressedThisFrame = false;
}
}
}

这是操控的类,顾名思义是操作运行创建好的状态机。成员变量有状态链表、状态机等。还有转换下一个状态NextStage()的具体方法和实时检测刷新的方法Update()



Light类:

class Light {
int cc;
PVector pos;
int alpha = 0;
boolean isopen;
Light(int _cc, int posx, int posy)
{
cc = _cc; //固定颜色
isopen = false;//默认关的状态
pos = new PVector(posx, posy);
}
//开关
public void update(boolean b)
{
isopen = b;
if( isopen == false ) //如果关了,亮度归位
alpha = 0;
} //运行时
public void working()
{
if (isopen)
alpha += 1; //如果开着,慢慢变量
alpha = constrain(alpha, 0, 255);
//println(alpha);
} public void draw()
{
if (isopen)//如果开,慢慢量
{
fill(cc, alpha);
} else//如果关,黑色的
{
fill(20, 250);
}
push();
translate(pos.x, pos.y);
rect(0, 0, 80, 150);//灯的表现形式
pop();
}
}

下面是三个state实现类:

class StageA extends State
{ StageA()
{
} void Enter()
{
super.Enter();
light1.update(true);
} void Update()
{
super.Update();
if (temp == 1)
println(this.getClass().getName()+" - Update !"); light1.working();
} void Exit() {
println(this.getClass().getName()+" - Exit !");
light1.update(false);
}
} class StageB extends State
{ StageB()
{
} void Enter()
{
super.Enter();
light2.update(true);
} void Update()
{
super.Update();
if (temp == 1) println(this.getClass().getName()+" - Update !");
light2.working();
} void Exit() {
println(this.getClass().getName()+" - Exit !");
light2.update(false);
}
} class StageC extends State
{ StageC()
{
} void Enter()
{
super.Enter();
light3.update(true);
} void Update()
{
super.Update();
if (temp == 1)
println(this.getClass().getName()+" - Update !");
light3.working();
} void Exit() {
println(this.getClass().getName()+" - Exit !");
light3.update(false);
}
}

最后是主程序:

Operator operSystem;

float timePassed;
float nextCheckTime;
float lastCheckTime;
float timeLapse = 1500; Light light1;
Light light2;
Light light3; void setup()
{
size(600,500); timePassed = 0;
lastCheckTime = 0;
nextCheckTime = timeLapse*2; //首次计时长一点 light1 = new Light(color(240,20,20),100,100);
light2 = new Light(color(20,240,20),250,100);
light3 = new Light(color(20,20,240),400,100);
operSystem = new Operator();
} void draw()
{
timePassed = millis() - lastCheckTime; operSystem.Update(); //“操作系统” 实时运行 light1.draw();
light2.draw();
light3.draw(); //计时器 - 触发(转换)
if(timePassed > nextCheckTime)
{
//println("Check!");
lastCheckTime = millis();
//nextCheckTime = lastCheckTime + timeLapse;
nextCheckTime = timeLapse;
operSystem.setChecked();
} } void mouseClicked()
{
} void keyPressed()
{
}

类的关系图参考:

总结

这是一个很好的有限状态机入门案例,一种线性的状态切换场景。下回我们来看看进一步的状态机,也就是离散的状态切换,其实有点像学数据结构的知识,那个状态机链表我们可以随意设计并调用。相信读者看到这,对状态机有个初步的认识了,并能在实际开发中尝试使用它,希望一切顺利,感谢您的阅读。

参考:

[1] https://zhuanlan.zhihu.com/p/47434856 ---- 什么是状态机

[2] https://www.zhihu.com/question/22363777/answer/652758029 -----什么是状态机?

[3] https://zhuanlan.zhihu.com/p/101020131 一生万物——Processing创意编程碎片

Processing 状态机应用研究(线性转换)的更多相关文章

  1. Qt状态机框架

    The State Machine Framework 状态机框架提供了用于创建和执行状态图的类.概念和符号是基于Harel的Statecharts: A visual formalism for c ...

  2. 趣说游戏AI开发:对状态机的褒扬和批判

    0x00 前言 因为临近年关工作繁忙,已经有一段时间没有更新博客了.到了元旦终于有时间来写点东西,既是积累也是分享.如题目所示,本文要来聊一聊在游戏开发中经常会涉及到的话题--游戏AI.设计游戏AI的 ...

  3. 基于FPGA的UART协议实现(通过线性序列机)

    //////////////////2018/10/15 更新源代码: 实现uart这东西其实早就写了,不过不太完善,对于一个完美主义者来说,必须解决掉它. 1.什么是UART?        通用异 ...

  4. labview状态机

    状态机主要由3部分组成,包括一个while循环,一个条件结构,以及while循环的移位寄存器,其中while循环用于保证程序的持续运行,条件结构用于处理不同状态的执行,移位寄存器用于实现从一个状态跳转 ...

  5. 通过spring statemmachine 自定义构建属于自己的状态机(两种方式)

    spring 的stateMachine 相对于当前的版本,还是比较新颖的,但是对于合适的业务场景,使用起来还是十分的方便的.但是对于官网提供的文档,讲解的是十分的精简,要想更深入的了解其内部架构,只 ...

  6. matlab神经网络实验

    第0节.引例  本文以Fisher的Iris数据集作为神经网络程序的测试数据集.Iris数据集可以在http://en.wikipedia.org/wiki/Iris_flower_data_set  ...

  7. freemodbus-v1.5.0 源码分析

    注:转载请注明出处   http://www.cnblogs.com/wujing-hubei/p/5935142.html FreeModbus协议栈作为从机,等待主机传送的数据,当从机接收到一帧完 ...

  8. 主元分析PCA理论分析及应用

    首先,必须说明的是,这篇文章是完完全全复制百度文库当中的一篇文章.本人之前对PCA比较好奇,在看到这篇文章之后发现其对PCA的描述非常详细,因此迫不及待要跟大家分享一下,希望同样对PCA比较困惑的朋友 ...

  9. CABAC

    CABAC(Context-based Adaptive Binary Arithmetic Coding),基于上下文的自适应二进制算术编码.CABAC是H.264/AVC标准中两种熵编码中的一种, ...

随机推荐

  1. c++ 获取当前程序的主模块句柄

    char text[2014]; GetModuleBaseNameA(GetCurrentProcess(), 0, text, 1024); HMODULE hModule = GetModule ...

  2. OpenCVE-开源漏洞预警平台

    0x01简介 主程序主要是通过使用NVD提供的JSON数据来更新CVE数据,并在前端进行展示.然后通过邮件进行通知,目前也只支持邮件.这个开源预警平台看上去并不是很完善,因为CVE本身就具有预警滞后性 ...

  3. TKMybatis

    TKMybatis与Mybatis-plus都是mybatis的扩展,有相同的地方,也有不同的地方. 1.导入坐标 <!--mybatis依赖--> <dependency> ...

  4. 小白养成记——MySQL中的排名函数

    1.ROW_NUMBER() 函数 依次排序,没有并列名次.如 SELECT st.ID '学号', st.`NAME` '姓名', sc.SCORE '成绩', ROW_NUMBER() OVER( ...

  5. Java基本概念:方法

    一.简介 描述: Java中方法是语句的集合,它们在一起执行一个功能. 方法是解决一类问题的步骤的有序组合,它在类中定义,属于类的成员,包含于类或对象中. 方法在程序中被创建后,在其他使用了该方法的地 ...

  6. Pandas初体验

    目录 Pandas 一.简介 1.安装 2.引用方法 二.series 1.创建方法 2.缺失数据处理 2.1 什么是缺失值 2.2 NaN特性 2.3 填充NaN 2.4 删除NaN 2.5 其他方 ...

  7. python爬取股票最新数据并用excel绘制树状图

    大家好,最近大A的白马股们简直 跌妈不认,作为重仓了抱团白马股基金的养鸡少年,每日那是一个以泪洗面啊. 不过从金融界最近一个交易日的大盘云图来看,其实很多中小股还是红色滴,绿的都是白马股们. 以下截图 ...

  8. Python3.x 基础练习题100例(51-60)

    练习51: 题目: 学习使用 按位与(&) . 分析: 0&0=0; 0&1=0; 1&0=0; 1&1=1. 程序: if __name__ == '__ma ...

  9. SQL-MYSQL的时间格式转换(持续补充)

    ======================SQLSERVER===================================== SELECT CONVERT(varchar(100), GE ...

  10. Linux-mysql服务级别对DB的操作要领[导出-导入(执行SQL)]及修改数据库名称

    A:docker容器的mysql docker exec -it mysql bash -- 进入容器 备份脚本 mysqldump -uroot -p123456 --databases dbNam ...