状态机(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. 倒计时2天!2021 NGK新加坡区块链峰会与你不见不散!

    1月31日14时,NGK将于新加坡召开"2021 NGK新加坡区块链峰会",并将在全球开启同步直播.   据了解,本次峰会将汇聚全球二十多位顶尖区块链专家学者,与NGK灵石技术团队 ...

  2. PHP反序列化字符串逃逸

    通过CTF比赛了解PHP反序列化,记录自己的学习. 借用哈大佬们的名言 任何具有一定结构的数据,如果经过了某些处理而把结构体本身的结构给打乱了,则有可能会产生漏洞. 0CTF 2016piapiapi ...

  3. Javascript中的事件冒泡与捕获

    事件冒泡和事件捕获 起因:今天在封装一个bind函数的时候,发现el.addEventListener函数支持第三个参数,useCapture:是否使用事件捕获,觉得有点模糊 Js事件流 页面的哪一部 ...

  4. Python基础之:数字字符串和列表

    目录 简介 数字 字符串 字符串对象str 列表 简介 Python的主要应用是进行科学计算,科学计算的基础就是数字,字符串和列表.本文将会详细的给大家介绍一下这三个数据类型的使用情况. 数字 数字是 ...

  5. 在next主题添加微信公众号二维码

    在侧边栏添加微信公众号二维码 首先,当然是准备一张微信公众号二维码.有两种添加方式,添加到侧边栏或者添加到推文的结尾处.我的next主题是7.x版本的,使用的主题是Gemini,设置的侧栏显示方式是一 ...

  6. iOS拍照之系统拍照

    拍照在App中使用频次高,入门级别直接调用系统拍照 思路: 系统拍照使用UIImagePickerController 1.设置下plist,否则没权限,报错 2.判断摄像头,获取权限,否则弹出界面黑 ...

  7. 自关联映射:一个表自己关联自己,此时从同一个表中查询,通过起别名将一张表变成两张表,使用join语句。

    实例1:id自关联. 隐式内连接: 实例二:编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 id .返回结果 不要求顺序 . 查询结果格式如下例: Weather +--- ...

  8. SpringCloud之服务降级

    1.Hystrix(断路器) 1.1定义 扇出:多个微服务调用的时候,假设微服务A调用微服务B和C,微服务B和C又调用其他的服务.服务雪崩:如果扇出的链路上某个微服务的调用时间过长或不可用,对微服务A ...

  9. Centos8.2安装Mongodb4.4.2(社区版)

    1:下载 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-4.4.2.tgz 官网地址: 2:解压 tar -zxv ...

  10. springboot启动抛出javax.websocket.server.ServerContainer not available

    问题描述:spring boot接入websocket时,启动报错:javax.websocket.server.ServerContainer not available <dependenc ...