状态机(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-Sharp 调用命令行

    https://stackoverflow.com/questions/1469764/run-command-prompt-commands 带控制台 string strCmdText = &qu ...

  2. Union international inc引进微信线下支付,开启消费无现金时代

    长期以来,Union international inc娱乐集团(公司编号:20151533091)因其客户来自全球各国,特别是除了美国之外的中国用户居多,因此公司一直和中国领先的社交软件微信保持着良 ...

  3. java数据类型(基础篇)

    public class note02 { public static void main(String[] args) { //八大基本数据类型 //1.整数 byte num1 = 1; shor ...

  4. Unity3d 拖拽脚本报错Can't add the script component "" because the script class cannot be found

    解决办法: ①报错原因:文件名与文件内容中的类名不相符. ②关闭360.鲁大师等防护软件,重新安装系统.

  5. Django Admin后台管理功能使用+二次开发

    一  使用环境 开发系统: windows IDE: pycharm 数据库: msyql,navicat 编程语言: python3.7  (Windows x86-64 executable in ...

  6. 微信小程序登录流程解析

    小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识openid,快速建立小程序内的用户体系. 登录流程时序: 1.首先,调用 wx.login获取code ,判断用户是否授权读取用户 ...

  7. spring boot的 yml和properties的对比

    Spring Boot 虽然做了大量的工作来简化配置,但其配置依然是相当的复杂!支持的外部配置方式就有很多种,笔者没有去统计,也许是为了灵活使用吧.   application.yml 和 appli ...

  8. Java并发之ThreadPoolExecutor源码解析(三)

    Worker 先前,笔者讲解到ThreadPoolExecutor.addWorker(Runnable firstTask, boolean core),在这个方法中工作线程可能创建成功,也可能创建 ...

  9. mysql添加远程连接权限

    查看登录用户 mysql> select host,user,password from user; 想用本地IP登录,那么可以将以上的Host值改为自己的Ip即可. 这里有多个root,对应着 ...

  10. 洛谷P3285 [SCOI2014]方伯伯的OJ 动态开点平衡树

    洛谷P3285 [SCOI2014]方伯伯的OJ 动态开点平衡树 题目描述 方伯伯正在做他的 \(Oj\) .现在他在处理 \(Oj\) 上的用户排名问题. \(Oj\) 上注册了 \(n\) 个用户 ...