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

 

有限状态机FSM的要点是:

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

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

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

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

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

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

 

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

代码来自于这里超链接

状态接口实现:

 
  1. public interface HeroineBaseState

  2. {

  3. void HandleInput();

  4. }

站立状态实现:

 
  1. using UnityEngine;

  2.  
  3. public class StandingState : HeroineBaseState

  4. {

  5. private Heroine _heroine;

  6. public StandingState(Heroine heroine)

  7. {

  8. _heroine = heroine;

  9. Debug.Log("进入站立状态!");

  10. }

  11.  
  12. public void HandleInput()

  13. {

  14. if (Input.GetKeyDown(KeyCode.UpArrow))

  15. {

  16. Debug.Log("get KeyCode.UpArrow!");

  17. _heroine.SetHeroineState(new JumpingState(_heroine));

  18. }

  19. if (Input.GetKeyDown(KeyCode.DownArrow))

  20. {

  21. Debug.Log("get KeyCode.DownArrow!");

  22. _heroine.SetHeroineState(new DuckingState(_heroine));

  23. }

  24. }

  25. }

跳跃状态实现:

 
  1. using UnityEngine;

  2.  
  3. public class JumpingState : HeroineBaseState

  4. {

  5.  
  6. private Heroine _heroine;

  7. public JumpingState(Heroine heroine)

  8. {

  9. _heroine = heroine;

  10. Debug.Log("进入跳跃状态!");

  11. }

  12.  
  13. public void HandleInput()

  14. {

  15. if (Input.GetKeyDown(KeyCode.UpArrow))

  16. {

  17. Debug.Log("已经在跳跃状态中!");

  18. return;

  19. }

  20. if (Input.GetKeyDown(KeyCode.DownArrow))

  21. {

  22. Debug.Log("get KeyCode.DownArrow!");

  23. _heroine.SetHeroineState(new DrivingState(_heroine));

  24. }

  25. }

  26. }

下蹲状态实现:

 
  1. using UnityEngine;

  2.  
  3. public class DuckingState : HeroineBaseState

  4. {

  5. private Heroine _heroine;

  6. public DuckingState(Heroine heroine)

  7. {

  8. _heroine = heroine;

  9. Debug.Log("进入下蹲躲避状态!");

  10. }

  11.  
  12. public void HandleInput()

  13. {

  14. if (Input.GetKeyDown(KeyCode.DownArrow))

  15. {

  16. Debug.Log("已经在下蹲躲避状态中!");

  17. return;

  18. }

  19. if (Input.GetKeyUp(KeyCode.UpArrow))

  20. {

  21. Debug.Log("get GetKeyUp.UpArrow!");

  22. _heroine.SetHeroineState(new StandingState(_heroine));

  23. }

  24. }

  25. }

下斩状态实现:

 
  1. using UnityEngine;

  2.  
  3. public class DrivingState : HeroineBaseState

  4. {

  5. private Heroine _heroine;

  6. public DrivingState(Heroine heroine)

  7. {

  8. _heroine = heroine;

  9. Debug.Log("进入下斩状态!");

  10. }

  11.  
  12. public void HandleInput()

  13. {

  14. if (Input.GetKeyDown(KeyCode.UpArrow))

  15. {

  16. Debug.Log("get KeyCode.UpArrow!");

  17. _heroine.SetHeroineState(new StandingState(_heroine));

  18. }

  19. }

  20. }

女主角实现:

 
  1. public class Heroine

  2. {

  3. HeroineBaseState _state;

  4.  
  5. public Heroine()

  6. {

  7. _state = new StandingState(this);

  8. }

  9.  
  10. public void SetHeroineState(HeroineBaseState newState)

  11. {

  12. _state = newState;

  13. }

  14.  
  15. public void Update()

  16. {

  17. _state.HandleInput();

  18. }

  19.  
  20. }

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

 
  1. using UnityEngine;

  2.  
  3. public class TestHeroine : MonoBehaviour

  4. {

  5. private Heroine _heroine;

  6.  
  7. // 初始化调用,先执行

  8. void Start()

  9. {

  10. _heroine = new Heroine();

  11. }

  12.  
  13. // 每帧调用一次

  14. void Update()

  15. {

  16. _heroine.Update();

  17. }

  18. }

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

C#代码实现:

 
  1. using System;

  2.  
  3. namespace StructScript

  4. {

  5.  
  6. public class StateScript

  7. {

  8. static void Main(string[] args)

  9. {

  10. Account account = new Account();

  11. account.Add(500);

  12. account.Add(3000);

  13. account.Remove(1000);

  14. account.Remove(10000);

  15.  
  16. Console.ReadLine();

  17. }

  18. }

  19.  
  20. public class Account

  21. {

  22. private State state;

  23.  
  24. public Account()

  25. {

  26. state = new RedState(0.0, this);

  27. }

  28.  
  29. public State State

  30. {

  31. get { return state; }

  32. set { state = value; }

  33. }

  34.  
  35. public void Add(int amount)

  36. {

  37. Console.WriteLine("Add " + amount);

  38. state.Add(amount);

  39. Console.WriteLine("Balance: " + state.Balance);

  40. Console.WriteLine("State: " + state.GetType().Name);

  41. }

  42.  
  43. public void Remove(int amount)

  44. {

  45. Console.WriteLine("Remove " + amount);

  46. state.Remove(amount);

  47. Console.WriteLine("Balance: " + state.Balance);

  48. Console.WriteLine("State: " + state.GetType().Name);

  49. }

  50. }

  51.  
  52. /// <summary>

  53. /// 状态基类

  54. /// </summary>

  55. public abstract class State

  56. {

  57. protected Account account;

  58. protected double balance;

  59. protected double lowerLimit;

  60. protected double upperLimit;

  61.  
  62. public Account Account

  63. {

  64. get { return account; }

  65. set { account = value; }

  66. }

  67.  
  68. public double Balance

  69. {

  70. get { return balance; }

  71. set { balance = value; }

  72. }

  73.  
  74. public abstract void Add(int amount);

  75. public abstract void Remove(int amount);

  76. }

  77.  
  78. /// <summary>

  79. /// 红色账户状态

  80. /// </summary>

  81. public class RedState : State

  82. {

  83. public RedState(State state) : this(state.Balance, state.Account) { }

  84.  
  85. public RedState(double balance, Account account)

  86. {

  87. this.balance = balance;

  88. this.account = account;

  89. lowerLimit = -100.0;

  90. upperLimit = 0.0;

  91. }

  92.  
  93. public override void Add(int amount)

  94. {

  95. balance += amount;

  96. StateChangeCheck();

  97. }

  98.  
  99. public override void Remove(int amount)

  100. {

  101. Console.WriteLine("余额不足");

  102. }

  103.  
  104. private void StateChangeCheck()

  105. {

  106. if (balance > upperLimit)

  107. {

  108. account.State = new SilverState(this);

  109. }

  110. }

  111. }

  112.  
  113. /// <summary>

  114. /// 银色账户状态

  115. /// </summary>

  116. public class SilverState : State

  117. {

  118. public SilverState(State state) : this(state.Balance, state.Account) { }

  119.  
  120. public SilverState(double balance, Account account)

  121. {

  122. this.balance = balance;

  123. this.account = account;

  124. lowerLimit = 0.0;

  125. upperLimit = 1000.0;

  126. }

  127.  
  128. public override void Add(int amount)

  129. {

  130. balance += amount;

  131. StateChangeCheck();

  132. }

  133.  
  134. public override void Remove(int amount)

  135. {

  136. double remain = balance - amount;

  137. if (remain < -100)

  138. {

  139. Console.WriteLine("余额不足");

  140. }

  141. else

  142. {

  143. balance = remain;

  144. StateChangeCheck();

  145. }

  146. }

  147.  
  148. private void StateChangeCheck()

  149. {

  150. if (balance < lowerLimit)

  151. {

  152. account.State = new RedState(this);

  153. }

  154. else if (balance > upperLimit)

  155. {

  156. account.State = new GoldState(this);

  157. }

  158. }

  159. }

  160.  
  161. /// <summary>

  162. /// 金色账户状态

  163. /// </summary>

  164. public class GoldState : State

  165. {

  166. public GoldState(State state) : this(state.Balance, state.Account) { }

  167.  
  168. public GoldState(double balance, Account account)

  169. {

  170. this.balance = balance;

  171. this.account = account;

  172. lowerLimit = 1000.0;

  173. upperLimit = 10000000.0;

  174. }

  175.  
  176. public override void Add(int amount)

  177. {

  178. balance += amount;

  179. StateChangeCheck();

  180. }

  181.  
  182. public override void Remove(int amount)

  183. {

  184. double remain = balance - amount;

  185. if (remain < -100)

  186. {

  187. Console.WriteLine("余额不足");

  188. }

  189. else

  190. {

  191. balance = remain;

  192. StateChangeCheck();

  193. }

  194. }

  195.  
  196. private void StateChangeCheck()

  197. {

  198. if (balance < 0.0)

  199. {

  200. account.State = new RedState(this);

  201. }

  202. else if (balance < lowerLimit)

  203. {

  204. account.State = new SilverState(this);

  205. }

  206. }

  207. }

  208. }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437094.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python中if嵌套语句的作用_讲解Python中if语句的嵌套用法

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里技术人对外发布原创技术内容的最大平台&…

ffmpeg录屏鼠标闪烁问题解决方法

场景&#xff1a; 平台&#xff1a;win7 x64。显卡很差的电脑&#xff0c;使用ffmpeg录屏&#xff0c;鼠标闪烁的几乎看不到。录屏实现方法是使用ffmpeg&#xff0c;源采用的是gdigrab。 解决方法&#xff1a; 安装screen capture recorder安装ffmpeg&#xff0c;执行命令ff…

【转】VS2005 CTP 版本这个CTP是什么意思

CTP Community Technology Preview 社区技术预览版&#xff0c;这个其实是稳定性最差得一个版本,Build 之后基本上没有做过什么严格得测试. CTP基本上可以看作是Alpha版本…… RC是Release Candidate的缩写&#xff0c;直译是发行候选 RTM Release To Manufacturer&#xf…

python中decode函数在哪个库_python encode和decode函数说明

字符串编码常用类型&#xff1a;utf-8,gb2312,cp936,gbk等。Python中&#xff0c;我们使用decode()和encode()来进行解码和编码在python中&#xff0c;使用unicode类型作为编码的基础类型。即decode encodestr ---------> unicode --------->stru u中文 #显…

《线性代数的几何意义》笔记(1)

如何理解“线性代数”这四个字&#xff1f; 线性代数 线性 代数。 线性&#xff0c;是指线性代数这门学科研究的是线性问题。线性是理想化的&#xff0c;但是也是最基础的。实际工程中如果有非线性的问题&#xff0c;可以通过转化成线性问题来近似求解。 线性有两个特性&…

ipython jupyter区别_ipython jupyter notebook中显示图像和数学公式实例

1. # 可以使用LaTeX表示数学公式# 可以使用LaTeX表示数学公式from IPython.display import LatexLatex(r"$\sqrt{x^2y^2}$")2. # SymPy的表达式也可以显示为LaTex%load_ext sympyprintingfrom sympy import *x, y symbols("x,y")sqrt(x**2y**2)3. # 用Ima…

【转】[完全免费] 在线UML Sequence Diagram 时序图工具 - 教程第3部分

时序图教程 甲序列图描述了一组对象之间的相互作用参与协作&#xff08;或情况&#xff09;&#xff0c;布置成按时间顺序; 它通过它们的“生命线”和它们发送给对方的消息来显示参与交互的对象。 什么是UML中的序列图&#xff1f; UML序列图是详细说明如何执行操作的交互图。…

【转】[完全免费] 在线UML Class Diagram 类图工具 - 教程第1部分

在线Visual Paradigm - UML编辑器 使用在线UML编辑器轻松绘制UML图&#xff0c;其中包含功能强大的UML编辑工具&#xff0c;即时UML语法检查和整洁的用户界面。Visual Paradigm在线UML 图&#xff0c;如类&#xff0c;用例&#xff0c;序列&#xff0c;活动&#xff0c;部署&a…

python 定时器_python 线程之四:定时器(Timer),非阻塞

线程之一讲了线程&#xff0c;如果不熟悉&#xff0c;可以点击【线程之一&#xff1a;线程的创建、启动及运行方式】1、定时器实质&#xff1a;Timer 定时器源码实现&#xff0c;和我们自定义一个线程方式一样&#xff0c;都是继承了 Thread 类&#xff0c;重写了 run() 方法&a…

人如何认知事物?

自然界是连续的&#xff0c;人类将自然界离散化成一个个独立的概念&#xff0c;独立的概念相互关联&#xff0c;形成模型&#xff0c;随着模型的完善&#xff0c;模型会不断逼近真实事物。 比如人类创造了各种学科&#xff0c;就是从不同的方面深入研究世界的结果。 所以&…

域内定位个人PC的三种方式(1)

会话搜集 在cmd下调用query session命令可以获得当前环境下的windows会话 NetSessionEnum 这个函数不允许直接查询是谁登陆&#xff0c;但是它允许查询是谁在访问此工作站的网络资源时所创建的网络会话&#xff0c;从而知道来自何处&#xff0c;此函数不需要高权限即可查询 第…

python手机销售系统结论于心得_(工作心得体会)手机销售心得总结

手机销售心得总结为更方面广大消上手机销售系统应景产生。下面是为大家整理的手机销售心得总结&#xff0c;供你参考!手机销售心得总结篇1XX年销售工作基本结束了&#xff0c;在整个团队的全年努力奋斗下&#xff0c;比XX年销量增幅12.5%&#xff0c;但在市场占有率和全国a类分…

02.Teams组成概述及使用分享

在上一篇博客中介绍了Teams的前世今生&#xff0c;大家对Teams已经有了一个初步的认识&#xff0c;但是如上一篇文章中所说Teams是一个集成度很高的云协作平台&#xff0c;具体应该怎么去有效的利用起来呢&#xff1f;接下来这篇博客给大家全方位的分享一下Teams的组成部分以及…

【Qt】解决GDAL直接读取数据到QImage导致图像歪斜的问题

QRect intersect_rect; .... QImage img(intersect_rect.size(), QImage::Format_RGB888); uchar *pImageData (unsigned char *)img.constBits(); int img_width intersect_rect.width(); int img_height intersect_rect.height();// QImage每行是按照sizeof(int)对齐的&am…

高斯课堂数电讲义笔记_【法考经验贴】40岁三战主观题127分!他的笔记学习法助他逆袭!...

这位学员在考证界算是“高龄学员”&#xff0c;高分过关依赖于他的努力和正确的学习方法&#xff1b;本文中他有重点介绍自己是如何做笔记的&#xff0c;非常值得大家学习借鉴&#xff01;一、个人概况&#xff1a;三战法考我正值不惑之年&#xff0c;是一名在职基层人民警察&a…

【转】持续交付和DevOps的前世今生

作者/分享人&#xff1a;乔梁&#xff0c;20年IT老兵&#xff0c;腾讯公司高级管理顾问&#xff0c;敏捷和精益开发专家&#xff0c;持续交付领域先行者。曾就职于百度&#xff0c;国内多个知名互联网公司的企业教练。 历年QCon技术大会的讲师和专题出品人。 这是一个新概念风起…

关联规则挖掘算法_基于Apriori关联规则的协同过滤算法

Apriori 算法apriori关联规则算法的原理设计较为简单&#xff0c;著名的“啤酒和尿布”说的就是Apriori算法&#xff0c;通俗来讲apriori旨在寻找频繁项集&#xff0c;以帮助商家将消费者有可能一起搭配购买的物品放置在同一个地方&#xff0c;提高消费者的购物效率和良好的购物…

【转】RabbitMQ六种队列模式-1.简单队列模式

前言 RabbitMQ六种队列模式-简单队列 [本文]RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主题模式 在官网的教程中&#xff0c;描述了如上六类工作队列模式&#xff1a; 简单队列模式&#xff1a;最简单的…

词汇释义

原语&#xff1a;原子语言&#xff0c;执行过程中不能被打断。原&#xff0c;并不是指原来的&#xff0c;初始的&#xff0c;是指原子&#xff01;表示不可分割的意思。