如何简化并通用化自动售货机的有限状态机(FSM)?
通用自动售货机支付流程有限状态自动机设计方案
核心思路:用抽象状态+累计金额参数替代枚举所有数值状态
你一开始想为每个具体金额单独创建状态的思路虽然正确,但完全没必要——老师提示的核心是让状态承载「当前累计支付金额」的抽象逻辑,而非每个金额对应一个独立状态,这样就能适配任意货币体系,哪怕是日元这种大额目标价格也不用画上万状态。
具体设计方案
1. 定义自动机核心要素
- 目标价格:记为
T(比如$80、¥10000) - 硬币面额集合:记为
C(比如{$1,$2,...,$50}、{¥1,¥5,...¥10000}) - 状态集合:
未完成状态:所有当前累计支付金额current < T的情况都归为这个抽象状态,用变量current记录具体已支付金额完成状态:当累计金额current ≥ T时进入的接受状态,一旦进入不再转移
- 初始状态:
未完成状态,且current=0 - 转移规则:
- 从
未完成状态出发,输入任意硬币面额c ∈ C:- 若
current + c ≥ T:直接转移到完成状态 - 若
current + c < T:更新current为current + c,保持在未完成状态
- 若
- 从
完成状态出发,无论输入任何硬币,都维持在完成状态
- 从
2. 针对大额目标的优化(比如日元¥10000)
这种设计天生不需要为每个金额绘制独立状态:所有current <10000的场景都属于同一个未完成状态,只需要通过current变量跟踪具体金额即可。转移时只需要做简单的数值计算,完全不用枚举1到9999的所有状态节点。
3. 适配特殊货币体系(比如虚构的{$3,$16,$47,$64})
这套逻辑同样适用:
- 初始
current=0,处于未完成状态 - 输入$47:
current=47 < T(假设目标价格是$80),保持未完成状态 - 输入$47:
current=94 ≥80,进入完成状态 - 哪怕硬币面额没有1元这种小面额,只要按累计金额的数值判断转移即可,无需调整状态结构
为什么这个方案符合老师的提示
老师说“结合硬币面额,使当前状态能体现累计金额”,这里的「体现累计金额」不是指每个金额对应一个状态,而是通过未完成状态中的current变量,结合硬币面额的数值来驱动状态转移——既保留了累计金额的核心信息,又避免了枚举所有可能金额的繁琐。
内容的提问来源于stack exchange,提问作者user19921500
相关产品推荐
相关产品推荐

