有限状态机的实现

有限状态机(Finite State Machine或者Finite State Automata)是软件领域中一种重要的工具,很多东西的模型实际上就是有限状态机。

最近看了一些游戏编程AI的材料,感觉游戏中的AI,第一要说的就是有限状态机来实现精灵的AI,然后才是A*寻路,其他学术界讨论比较多的神经网络、模糊控制等问题还不是很热。

FSM的实现方式:
1) switch/case或者if/else
这无意是最直观的方式,使用一堆条件判断,会编程的人都可以做到,对简单小巧的状态机来说最合适,但是毫无疑问,这样的方式比较原始,对庞大的状态机难以维护。

2) 状态表
维护一个二维状态表,横坐标表示当前状态,纵坐标表示输入,表中一个元素存储下一个状态和对应的操作。这一招易于维护,但是运行时间和存储空间的代价较大。

3) 使用State Pattern
使用State Pattern使得代码的维护比switch/case方式稍好,性能上也不会有很多的影响,但是也不是100%完美。不过Robert C. Martin做了两个自动产生FSM代码的工具,for java和for C++各一个,在http://www.objectmentor.com/resources/index上有免费下载,这个工具的输入是纯文本的状态机描述,自动产生符合State Pattern的代码,这样developer的工作只需要维护状态机的文本描述,每必要冒引入bug的风险去维护code。

4) 使用宏定义描述状态机
一般来说,C++编程中应该避免使用#define,但是这主要是因为如果用宏来定义函数的话,很容易产生这样那样的问题,但是巧妙的使用,还是能够产生奇妙的效果。MFC就是使用宏定义来实现大的架构的。
在实现FSM的时候,可以把一些繁琐无比的if/else还有花括号的组合放在宏中,这样,在代码中可以3)中状态机描述文本一样写,通过编译器的预编译处理产生1)一样的效果,我见过产生C代码的宏,如果要产生C++代码,己软MFC可以,那么理论上也是可行的。













  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为你介绍一下如何使用有限状态机实现电子售卖机。 首先,我们需要确定电子售卖机的状态,输入和输出。根据电子售卖机的工作原理,我们可以将其状态分为以下几个: - 等待状态(Waiting):等待用户选择商品。 - 选择商品状态(Selecting):用户选择商品。 - 支付状态(Paying):用户进行支付。 - 出货状态(Dispensing):出货并找零。 接下来,我们需要确定电子售卖机的输入和输出。根据电子售卖机的操作流程,我们可以将其输入和输出分为以下几个: - 选择商品(Select_Item):用户选择商品。 - 投入货币(Insert_Coin):用户投入货币。 - 取出货币(Return_Change):用户取出找零。 - 出货(Dispense_Item):出货并找零。 - 显示(Display):显示用户当前状态和余额。 有了状态,输入和输出之后,我们就可以开始设计电子售卖机的有限状态机。以下是一个简单的电子售卖机状态机的状态转移图: ``` +---------+ +-------------+ | Waiting +------------> Selecting | +---------+ +-------------+ ^ | | | | v +---------+ +-------------+ | Paying +------------> Dispensing | +---------+ +-------------+ ``` 在等待状态下,用户可以选择商品,这将使状态机从等待状态转移到选择商品状态。在选择商品状态下,用户可以选择要购买的商品,并投入货币。如果用户投入的货币足够支付商品的价格,则状态机会从选择商品状态转移到支付状态。在支付状态下,电子售卖机会显示用户当前的余额,并等待用户投入足够的货币。如果用户投入的货币超过了商品的价格,那么状态机会从支付状态转移到出货状态,并出货并找零。 接下来,我们可以使用Verilog语言来实现电子售卖机的状态机。以下是一个简单的Verilog代码实现: ``` // 定义状态 typedef enum logic [1:0] { Waiting, Selecting, Paying, Dispensing } state; // 定义输入 input Select_Item; input Insert_Coin; input Return_Change; input Dispense_Item; // 定义输出 output reg [7:0] Display; output reg Dispense_Item; // 定义状态寄存器和下一个状态变量 reg [1:0] current_state; reg [1:0] next_state; // 确定状态转移条件 always @(*) begin case(current_state) Waiting: begin if (Select_Item) next_state = Selecting; else next_state = Waiting; end Selecting: begin if (Insert_Coin >= Item_Price) next_state = Paying; else next_state = Selecting; end Paying: begin if (Insert_Coin >= Item_Price) next_state = Paying; else if (Insert_Coin < Item_Price) next_state = Dispensing; end Dispensing: begin next_state = Waiting; end default: next_state = Waiting; endcase end // 实现状态机 always @(posedge clk) begin current_state <= next_state; case(current_state) Waiting: begin Display <= "Please select an item"; end Selecting: begin Display <= "Insert coin"; end Paying: begin Display <= "Balance: " + (Insert_Coin - Item_Price); end Dispensing: begin Display <= "Thank you!"; Dispense_Item <= 1; end default: begin Display <= "Please select an item"; end endcase end ``` 在这个例子,我们使用了一个状态寄存器和一个下一个状态变量来实现状态转移。同时,我们还使用了一个时钟信号(clk)来控制状态机的运行。在状态机运行的过程,我们可以根据当前状态和输入来确定下一个状态,并根据当前状态来实现相应的输出。 以上就是使用有限状态机实现电子售卖机的基本步骤和代码实现。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值