首页 > 编程语言 >C#数据结构-有限状态机

C#数据结构-有限状态机

时间:2022-11-29 20:32:04浏览次数:65  
标签:account balance C# void heroine 状态机 state 数据结构 public




有限状态机FSM的要点是:

  1.     拥有一组状态,并且可以在这组状态之间进行切换。
  2.     状态机同时只能在一个状态。
  3.     一连串的输入或事件被发送给机器。
  4.     每个状态都有一系列的转换,转换与输入和另一状态相关。当输入进来,如果它与当前状态的某个转换匹配,机器转为转换所指的状态。

    


目前而言,游戏编程中状态机的实现方式,有两种可以选择:


  1.     用枚举配合switch case语句。
  2.     实现多态(也就是状态模式)。

状态模式的经典定义:允许对象在当内部状态改变时改变其行为,就好像此对象改变了自己的类一样


状态模式的实现要点,主要有三点:


  1.     为状态定义一个接口。
  2.     为每个状态定义一个类。
  3.     恰当地进行状态委托。

注:下面的代码在unity中用C#实现,不过只是借用了unity的输入操作,对于理解有限状态机,没有阻碍。

  •       初始化是站立状态;
  •       按下向上的方向键,可以跳跃;在跳跃的状态,按向下的方向键,可以下斩,按向上的方向键,不做处理;
  •       按下向下的方向键,可以下蹲;在下蹲的状态,按向下的方向键,不做处理,按向上的方向键,恢复站立状态;

代码来自于​​这里超链接​

状态接口实现:

public interface HeroineBaseState
{
void HandleInput();
}

站立状态实现:

using UnityEngine;

public class StandingState : HeroineBaseState
{
private Heroine _heroine;
public StandingState(Heroine heroine)
{
_heroine = heroine;
Debug.Log("进入站立状态!");
}

public void HandleInput()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
Debug.Log("get KeyCode.UpArrow!");
_heroine.SetHeroineState(new JumpingState(_heroine));
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Debug.Log("get KeyCode.DownArrow!");
_heroine.SetHeroineState(new DuckingState(_heroine));
}
}
}

跳跃状态实现:

using UnityEngine;

public class JumpingState : HeroineBaseState
{

private Heroine _heroine;
public JumpingState(Heroine heroine)
{
_heroine = heroine;
Debug.Log("进入跳跃状态!");
}

public void HandleInput()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
Debug.Log("已经在跳跃状态中!");
return;
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Debug.Log("get KeyCode.DownArrow!");
_heroine.SetHeroineState(new DrivingState(_heroine));
}
}
}

下蹲状态实现:

using UnityEngine;

public class DuckingState : HeroineBaseState
{
private Heroine _heroine;
public DuckingState(Heroine heroine)
{
_heroine = heroine;
Debug.Log("进入下蹲躲避状态!");
}

public void HandleInput()
{
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Debug.Log("已经在下蹲躲避状态中!");
return;
}
if (Input.GetKeyUp(KeyCode.UpArrow))
{
Debug.Log("get GetKeyUp.UpArrow!");
_heroine.SetHeroineState(new StandingState(_heroine));
}
}
}

下斩状态实现:

using UnityEngine;

public class DrivingState : HeroineBaseState
{
private Heroine _heroine;
public DrivingState(Heroine heroine)
{
_heroine = heroine;
Debug.Log("进入下斩状态!");
}

public void HandleInput()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
Debug.Log("get KeyCode.UpArrow!");
_heroine.SetHeroineState(new StandingState(_heroine));
}
}
}

女主角实现:

public class Heroine
{
HeroineBaseState _state;

public Heroine()
{
_state = new StandingState(this);
}

public void SetHeroineState(HeroineBaseState newState)
{
_state = newState;
}

public void Update()
{
_state.HandleInput();
}

}

测试代码,在Unity里要挂在一个GameObject上执行。

using UnityEngine;

public class TestHeroine : MonoBehaviour
{
private Heroine _heroine;

// 初始化调用,先执行
void Start()
{
_heroine = new Heroine();
}

// 每帧调用一次
void Update()
{
_heroine.Update();
}
}

上面用的接口,还可以用虚函数或者抽象函数来实现多态。下面模拟了银行存款取款,账户的状态的变化。

C#代码实现:

using System;

namespace StructScript
{

public class StateScript
{
static void Main(string[] args)
{
Account account = new Account();
account.Add(500);
account.Add(3000);
account.Remove(1000);
account.Remove(10000);

Console.ReadLine();
}
}

public class Account
{
private State state;

public Account()
{
state = new RedState(0.0, this);
}

public State State
{
get { return state; }
set { state = value; }
}

public void Add(int amount)
{
Console.WriteLine("Add " + amount);
state.Add(amount);
Console.WriteLine("Balance: " + state.Balance);
Console.WriteLine("State: " + state.GetType().Name);
}

public void Remove(int amount)
{
Console.WriteLine("Remove " + amount);
state.Remove(amount);
Console.WriteLine("Balance: " + state.Balance);
Console.WriteLine("State: " + state.GetType().Name);
}
}

/// <summary>
/// 状态基类
/// </summary>
public abstract class State
{
protected Account account;
protected double balance;
protected double lowerLimit;
protected double upperLimit;

public Account Account
{
get { return account; }
set { account = value; }
}

public double Balance
{
get { return balance; }
set { balance = value; }
}

public abstract void Add(int amount);
public abstract void Remove(int amount);
}

/// <summary>
/// 红色账户状态
/// </summary>
public class RedState : State
{
public RedState(State state) : this(state.Balance, state.Account) { }

public RedState(double balance, Account account)
{
this.balance = balance;
this.account = account;
lowerLimit = -100.0;
upperLimit = 0.0;
}

public override void Add(int amount)
{
balance += amount;
StateChangeCheck();
}

public override void Remove(int amount)
{
Console.WriteLine("余额不足");
}

private void StateChangeCheck()
{
if (balance > upperLimit)
{
account.State = new SilverState(this);
}
}
}

/// <summary>
/// 银色账户状态
/// </summary>
public class SilverState : State
{
public SilverState(State state) : this(state.Balance, state.Account) { }

public SilverState(double balance, Account account)
{
this.balance = balance;
this.account = account;
lowerLimit = 0.0;
upperLimit = 1000.0;
}

public override void Add(int amount)
{
balance += amount;
StateChangeCheck();
}

public override void Remove(int amount)
{
double remain = balance - amount;
if (remain < -100)
{
Console.WriteLine("余额不足");
}
else
{
balance = remain;
StateChangeCheck();
}
}

private void StateChangeCheck()
{
if (balance < lowerLimit)
{
account.State = new RedState(this);
}
else if (balance > upperLimit)
{
account.State = new GoldState(this);
}
}
}

/// <summary>
/// 金色账户状态
/// </summary>
public class GoldState : State
{
public GoldState(State state) : this(state.Balance, state.Account) { }

public GoldState(double balance, Account account)
{
this.balance = balance;
this.account = account;
lowerLimit = 1000.0;
upperLimit = 10000000.0;
}

public override void Add(int amount)
{
balance += amount;
StateChangeCheck();
}

public override void Remove(int amount)
{
double remain = balance - amount;
if (remain < -100)
{
Console.WriteLine("余额不足");
}
else
{
balance = remain;
StateChangeCheck();
}
}

private void StateChangeCheck()
{
if (balance < 0.0)
{
account.State = new RedState(this);
}
else if (balance < lowerLimit)
{
account.State = new SilverState(this);
}
}
}
}





标签:account,balance,C#,void,heroine,状态机,state,数据结构,public
From: https://blog.51cto.com/u_6871414/5897015

相关文章

  • 【最通俗易懂】A*寻路算法C#实现
    A*算法其实也不复杂,首先有以下几个概念:开启的节点表(OpenList)存放着所有的待检测的节点(坐标),每次都会从其中寻找出符合某个条件的节点。关闭的节点表(ClosedList)存放着所有......
  • 有限状态机
    有限状态机简介有限状态机(FSM)是许多数字系统中用来控制系统和数据流路径行为的时序电路。FSM的实例包括控制单元和时序。本实验介绍了两种类型的FSM(Mealy和Moore)的概念,以......
  • 【最通俗易懂】C#有限状态机
    有限状态机表示有限个状态以及在这些状态之间的转换和动作等行为的数学模型。 有限状态机框架:Transitionenum:此枚举包含可由系统触发的转换标签。StateID枚举:这是游戏具......
  • win10 git报错:Unable to negotiate with port: no matching host key type found. The
    现象已经生成id_rsa的密钥,并且在git上进行了配置。但是用gitclone失败。报错:Unabletonegotiatewithport:nomatchinghostkeytypefound.Theiroffer:ssh-rsa。......
  • WGCLOUD - 如何实现监测mysql主从节点同步状态是否正常
    WGCLOUD的自定义监控项,可以执行一些我们自定义的指令或脚本,非常灵活本文我们尝试使用此功能来监测我们的mysql从节点是否在正常工作,如果如下两项值都为yes,那么slave节点是......
  • 如果摄像头不支持Web Socket,猿大师播放器还能在网页中播放RTSP流吗?
    问:我们的情况比较复杂,摄像头设备品牌和数量都比较多,分布在全国各地都有,地点分布比较广泛,有的甚至是比较老的型号,如果摄像头设备不支持WebSocket,猿大师播放器还可以在网页......
  • 3种CSS简单方法实现文字竖向排版
    下面介绍3种使用CSS实现文字竖向排版的方法:1、一个句子的竖向排列如图:<!DOCTYPEhtml><html><head><title>test</title><metacharset="UTF-8"></head>......
  • es6 class 实践
    ClassinES6从es6开始引入了class这个语法糖,针对babel,或者tsc,转码后,类会变成什么样,这篇文章将阐述编译后的结果。首先看看es5中的类的实现,举个栗子functionclassA()......
  • 【开发小技巧】028—使用CSS创建卡通动画加载效果
    在实际项目开发中,一般都会设计一个动画加载效果,今天这个加载效果非常有趣,可以帮助用户在等待程序加载时,缓解用户着急的情绪。HTML代码:在本文中,设计了代码的基本结构。<!DOCT......
  • services资源+pod详解
    services资源+pod详解一、Service虽然每个Pod都会分配一个单独的PodIP,然而却存在如下两问题:PodIP会随着Pod的重建产生变化PodIP仅仅是集群内可见的虚拟IP,外部无......