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

107 篇文章 10 订阅
47 篇文章 12 订阅


有限状态机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);
            }
        }
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值