ImageVerifierCode 换一换
格式:DOCX , 页数:15 ,大小:21.12KB ,
资源ID:23664305      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/23664305.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(状态机编程.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

状态机编程.docx

1、状态机编程状态机编程 (转)【转载1】有限状态机的实现 有限状态机(Finite State Machine或者Finite State Automata)是软件领域中一种重要的工具,很多东西的模型实际上就是有限状态机。最近看了一些游戏编程AI的材料,感觉游戏中的AI,第一要说的就是有限状态机来实现精灵的AI,然后才是A*寻路,其他学术界讨论比较多的神经网络、模糊控制等问题还不是很热。FSM的实现方式:1) switch/case或者if/else这无意是最直观的方式,使用一堆条件判断,会编程的人都可以做到,对简单小巧的状态机来说最合适,但是毫无疑问,这样的方式比较原始,对庞大的状态机难以维护

2、。2) 状态表维护一个二维状态表,横坐标表示当前状态,纵坐标表示输入,表中一个元素存储下一个状态和对应的操作。这一招易于维护,但是运行时间和存储空间的代价较大。3) 使用State Pattern使用State Pattern使得代码的维护比switch/case方式稍好,性能上也不会有很多的影响,但是也不是100完美。不过Robert C. Martin做了两个自动产生FSM代码的工具,for java和for C+各一个,在 Pattern的代码,这样developer的工作只需要维护状态机的文本描述,每必要冒引入bug的风险去维护code。4) 使用宏定义描述状态机一般来说,C+编程中应

3、该避免使用#define,但是这主要是因为如果用宏来定义函数的话,很容易产生这样那样的问题,但是巧妙的使用,还是能够产生奇妙的效果。MFC就是使用宏定义来实现大的架构的。在实现FSM的时候,可以把一些繁琐无比的if/else还有花括号的组合放在宏中,这样,在代码中可以3)中状态机描述文本一样写,通过编译器的预编译处理产生1)一样的效果,我见过产生C代码的宏,如果要产生C+代码,己软MFC可以,那么理论上也是可行的。 【评】:状态表的实现方法,C专家编程第8章有具体说明,转载【6】传说中的分隔符 来源2:【转载2】有限状态机的c实现2007-05-11 15:12網絡上可以搜索到很多有限狀態機的

4、代碼和理論分析,這兒僅僅是做一個簡單的例子,僅供入門參考。这儿以四位密码校验作为状态机的例子,连续输入2479就可以通过密码测试。一个非常简单的例子,在实际的状态机实例中,状态转移表要更復雜一些,不過方式非常類似。在狀態查詢的地方可以做優化,同時對于輸入量也可以做有效性優化。具體代碼如下:view plaincopy to clipboardprint?c.h typedef enum STATE1 = 1, STATE2, STATE3, STATE4, STATE5,/password pass /.ADD here STATE; typedef enum INPUT1 = 2, INPU

5、T2 = 4, INPUT3 = 7, INPUT4 = 9, INPUT; typedef struct STATE cur_state; INPUT input; STATE next_state; STATE_TRANS; c.htypedef enumSTATE1 = 1,STATE2,STATE3,STATE4,STATE5,/password pass/.ADD hereSTATE;typedef enumINPUT1 = 2,INPUT2 = 4,INPUT3 = 7,INPUT4 = 9,INPUT;typedef structSTATE cur_state;INPUT inp

6、ut;STATE next_state;STATE_TRANS;c.c #include #include c.h STATE_TRANS state_trans_arry = STATE1,INPUT1,STATE2, STATE2,INPUT2,STATE3, STATE3,INPUT3,STATE4, STATE4,INPUT4,STATE5, ; #define STATE_TRANS_CNT (sizeof(state_trans_arry)/sizeof(state_trans_arry0) int main() int i; char ch; STATE state_machin

7、e = STATE1; while(ch != e) ch = getchar(); if(ch = 0) & (ch = 9)/for digit password input only for(i = 0;i STATE_TRANS_CNT;i+) if(ch = state_trans_arryi.input) & (state_machine = state_trans_arryi.cur_state) state_machine = state_trans_arryi.next_state; continue; else if(i = (STATE_TRANS_CNT - 1)/no

8、 transfer match,reset state state_machine = STATE1; if(state_machine = STATE5) printf(Password correct,state transfer machine pass!n); return 0; c.c#include #include c.hSTATE_TRANS state_trans_arry = STATE1,INPUT1,STATE2,STATE2,INPUT2,STATE3,STATE3,INPUT3,STATE4,STATE4,INPUT4,STATE5,;#define STATE_T

9、RANS_CNT (sizeof(state_trans_arry)/sizeof(state_trans_arry0)int main() int i;char ch;STATE state_machine = STATE1;while(ch != e) ch = getchar(); if(ch = 0) & (ch = 9)/for digit password input only for(i = 0;i STATE_TRANS_CNT;i+) if(ch = state_trans_arryi.input) & (state_machine = state_trans_arryi.c

10、ur_state) state_machine = state_trans_arryi.next_state; / continue; break; /做了修改在vc上可以实现 else if(i = (STATE_TRANS_CNT - 1)/no transfer match,reset state state_machine = STATE1; if(state_machine = STATE5) printf(Password correct,state transfer machine pass!n); return 0;传说中的分隔符 来源3:【转载3】有限状态机自动机状态图一个图

11、的数据结构!1.while + switch;2.状态机:就是指定系统的所有可能的状态及状态间跳转的条件,然后设一个初始状态输入给这台机器,机器就会自动运转,或最后处于终止状态,或在某一个状态不断循环。游戏中状态切换是很频繁的。 可能以前要切换状态就是ifelse,或者设标志,但这些都不太结构化, 如果把它严格的设为一种标准的状态机,会清楚的多。比如控制一扇门的运动, 初始时门是关的, 当有力作用在门上时, 门开始慢慢打开,力的作用完后,门渐渐停止不动, 当有反向的力时,门又渐渐关上, 知道回到初始关的状态。 这个你会怎么来编程实现呢。 似乎很麻烦, 的确,没有状态机的思想时会很烦,设很多标志

12、,一堆if条件。用状态机的话,不只是代码更清晰, 关键是更符合逻辑和自然规律, 不同状态不同处理, 满足条件则跳转到相关状态。伪码如下: enum CLOSED, / 关上状态 CLOSING, / 正在关状态 OPENED, / 打开状态 OPENING, / 正在开的状态 doorState = CLOSED; / 初始为关 Update() switch(doorState) case CLOSED: if (有人推门) doorState = OPENING; / 跳转到正在开状态 break; case OPENING: door.Rotation += DeltaAngle; /

13、门的旋转量递增 if (门的速度为零) / / 力的作用已去 doorState = OPENED; / 跳转到开状态 break; case OPENED: if (有人关门) doorState = CLOSING; break; case CLOSING: door.Rotation -= DeltaAngle; / 门的旋转量递减 if (门的旋转角度减为零) doorState = CLOSED; / 门已关上 break; / 而绘制代码几乎不用怎么变, 门就是会严格按照状态机的指示去运动, 该停就会停 Render() RotateView(door.Rotation); Dra

14、wDoor(door.Position); enumCLOSED, / 关上状态CLOSING, / 正在关状态OPENED, / 打开状态OPENING, / 正在开的状态doorState = CLOSED; / 初始为关Update() switch(doorState) case CLOSED: if (有人推门) doorState = OPENING; / 跳转到正在开状态 break; case OPENING: door.Rotation += DeltaAngle; / 门的旋转量递增 if (门的速度为零) / / 力的作用已去 doorState = OPENED; /

15、跳转到开状态 break; case OPENED: if (有人关门) doorState = CLOSING; break; case CLOSING: door.Rotation -= DeltaAngle; / 门的旋转量递减 if (门的旋转角度减为零) doorState = CLOSED; / 门已关上 break; / 而绘制代码几乎不用怎么变, 门就是会严格按照状态机的指示去运动, 该停就会停Render() RotateView(door.Rotation); DrawDoor(door.Position);这是一个简单但很典型的例子, 状态机的应用太多了。就说一个基本游戏

16、的运转: (用到了一个状态然后还有子状态)UpdateGame() BEGIN; switch(gameState) case 等待选择菜单: /它有三个子状态。 if (选择菜单项 开始) 游戏初始; gameState = 开始游戏 if (选择菜单项 选项) gameState = 设置 if (选择菜单项 退出) gameState = 退出 case 开始: 游戏运行; if (用户按退出键) gameState = 等待选择菜单 ; .其他的状态跳转处理; case 退出: 释放资源; 退出; case 设置: 分别处理不同的选项, 跳转不同的子状态; case . / 其他状态的

17、处理 END; UpdateGame()BEGIN; switch(gameState) case 等待选择菜单: /它有三个子状态。 if (选择菜单项 开始) 游戏初始; gameState = 开始游戏 if (选择菜单项 选项) gameState = 设置 if (选择菜单项 退出) gameState = 退出case 开始:游戏运行;if (用户按退出键)gameState = 等待选择菜单 ;.其他的状态跳转处理;case 退出:释放资源;退出;case 设置:分别处理不同的选项, 跳转不同的子状态;case . / 其他状态的处理END;某一个状态可以包含更多的子状态, 这样

18、最好是同一层次的状态设为一个枚举, 并分到另一个switch处理如 enum STATESstate1, state2, state3; state2又包含若干状态则再定义enum SUB_STATE2sub_state2_1, sub_state2_2, sub_state2_3,;想很多基本的渲染效果, 如淡入淡出, 闪烁等等, 用状态的思想会事半功倍, 思路也更清晰。其实像Opengl, Direct3D这样的渲染引擎本身就是状态机, 当你设置渲染的状态, 这台机器就保持这个状态进行渲染工作,如保持光照位置,保持片元颜色, 直到你再次改变它的状态。状态机的应用实在太广, 相关理论也很多,

19、 最近上课学的随机过程里也讲到一些, 数字电路里的时序逻辑器件也是用状态机来描述。 这些不必多说了。总之, 用状态机的角度去看待问题, 往往能把比较复杂的系统分解为能单独处理的众多子状态, 处理也会得心应手。希望大家多用它, 很好的东西。二、推荐这个:程序员杂志2004.8月刊_state模式和composite模式实现的状态机引擎个人感觉状态机的几个不同实现阶段:1、switch/case 最原始的实现方式,是很多的c程序员习惯采用的方式。2、查找表状态、事件、动作,稍微做了一点改进。有点类似MFC的雏形。3、在以上基础上做的一些改进或者变体。比如用一个栈结构,激活的状态位于栈顶,自动的映射

20、事件和动作的对应,再或者通过一些巧妙的宏等手段进行包装。但是线性结构在实际中使用比较受限、过于技巧性的宏比较难于理解.4、面向对象的设计下、灵活运用模式。如上面给出的链接。重用性和灵活性方面都有不错的表现。沿袭类似的设计思路、根据实际开发内容进行改造后利用。【评】:伪代码部分,可以帮助很好的理解【转载1】文章中叙述的FSM的实现方法1;查找表状态、事件、动作,稍微做了一点改进。有点类似MFC的雏形类似于【转载1】文章中叙述的FSM的实现方法2(状态表)传说中的分隔符 【转载4】fsm implemented in C code(FSM状态机用C实现)用C语言实现一个状态机,很简单,和大家分享这

21、是我做毕业设计时,用nRF24L01组建了一个简单的网络,做的一个小的状态机,网络中三个节点,开始拓扑为网状,后来为星型。#include #include #include /Finite state machine declaration /state declaration #define IDLE 0 /idle state in rx mode #define M_BROADCAST 1 /broadcast state in tx mode,broadcast to be a master point #define M_WAIT_BROADCAST_ACK 2 /wait for

22、 broadcast ack state in rx mode,wait for the point ack in a specific time window #define M_WAIT_COMMAND 3 /wait for command state,wait for PC command via UART #define M_BROADCAST_CANCEL 4 /broadcast cancel state,broadcast to cancel master point #define S_BROADCAST_ACK 5 /slave mode,send back self ph

23、ysical address #define S_WAIT_COMMAND 6 /slave mode, wait for command from the master point /state transition trig /used in master mode int isReqBeMaster = 0; /Is PC request the point to be master? int isTimeout = 0; /Is time out? int isReqCancelMaster = 0; /Is request to cancel master? /used in sla

24、ve mode int isRxBroadcast = 0; /Is there a point broadcast to be master? int isRxBroadcastCancel = 0; /Is receive broadcast cancel master? typedef struct fsmtag int state; /state int timeouttime; /time out time in milliseconds fsm; /function prototype int main() fsm f; f.state = IDLE; f.timeouttime = 0; while(1) switch(f.state) case IDLE: puts(IDLEnWait for isReqBeMaster(1/0) isRxBroadcast(1/0):); scanf(%d %d,&isReqBeMaster,&isRxBroadcast); if(isR

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1