华企号 互联网综合 C#数据结构-有限状态机

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

有限状态机FSM的要点是:

拥有一组状态,并且可以在这组状态之间进行切换。
状态机同时只能在一个状态。
一连串的输入或事件被发送给机器。
每个状态都有一系列的转换,转换与输入和另一状态相关。当输入进来,如果它与当前状态的某个转换匹配,机器转为转换所指的状态。
目前而言,游戏编程中状态机的实现方式,有两种可以选择:

 

用枚举配合switch case语句。
实现多态(也就是状态模式)。
状态模式的经典定义:允许对象在当内部状态改变时改变其行为,就好像此对象改变了自己的类一样

 

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

 

为状态定义一个接口。
为每个状态定义一个类。
恰当地进行状态委托。
注:下面的代码在unity中用C#实现,不过只是借用了unity的输入操作,对于理解有限状态机,没有阻碍。

初始化是站立状态;
按下向上的方向键,可以跳跃;在跳跃的状态,按向下的方向键,可以下斩,按向上的方向键,不做处理;
按下向下的方向键,可以下蹲;在下蹲的状态,按向下的方向键,不做处理,按向上的方向键,恢复站立状态;
代码来自于​ ​这里超链接​​

状态接口实现:

public interface HeroineBaseState
{
void HandleInput();
}
1.
2.
3.
4.
站立状态实现:

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);
}
}
}
}

有限状态机

 

作者: 华企网通王鹏程序员

我是程序员王鹏,热爱互联网软件开发和设计,专注于大数据、数据分析、数据库、php、java、python、scala、k8s、docker等知识总结。 我的座右铭:"业精于勤荒于嬉,行成于思毁于随"
上一篇
下一篇

发表回复

联系我们

联系我们

028-84868647

在线咨询: QQ交谈

邮箱: tech@68v8.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部