【问题标题】:Universal FSM in c# to implement any state machine.. and to check any next state on user inputc# 中的通用 FSM 实现任何状态机.. 并检查用户输入的任何下一个状态
【发布时间】:2020-01-20 18:47:03
【问题描述】:

可以更简单吗?我希望它适用于任何状态机,只需更改 main()...转换表我怎么能 从用户那里获得输入以选择任何状态并显示下一个可能的状态 状态作为循环中的输出。 如何使其适用于所有机器?如何从用户那里获得输入以选择机器的下一个可能状态?

    using System; 
    using System.Activities.Statements; 
    using System.Collections; 
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;     
    namespace FSM_PACMAN
     {
    class Program
    {
        static async Task Main(string[] args)
        {
            StateMachine<string> machine = new StateMachine<string>("Sets","Spawned", "SuperPac","Lvlcomplete","Dead","Successfullgameover")
        {
            { "Spawned", "Spawned","Eatcheese" },
            { "Spawned", "Dead", "EatenbyGost" },
            { "Spawned", "Superpac", "EatTablet" },
            { "Spawned", "Lvlcomplete", "Eatlastcheese" },
            { "SuperPac", "SuperPac", "EATcheese" },
            { "SuperPac", "SuperPac", "EATTablet" },
            { "SuperPac", "Spawned", "Timeout" },
            { "SuperPac", "Lvlcomplete", "Eatlastcheese" },
            { "SuperPac", "SuperPac", "EATghost" },
            { "SuperPac", "Dead", "EatenbySpawnedGhost" },
            { "Lvlcomplete", "Spawned", "Lvlleft" },
            { "Lvlcomplete", "Spawned", "NewGame" },
            { "Lvlcomplete", "Successfullgameover", "Nomorelevels" },
            { "Dead", "Spawned", "Lifeleft"},
            { "Dead", "Spawned", "NewGame" },
            { "Successfullgameover", "Spawned", "NewGame" },

        };

            for (int i = 1; i <= 100; i++) {
                Console.WriteLine(machine);

                Console.WriteLine("current state = " + machine.start);
                Console.WriteLine("Enter State");
                string input = Console.ReadLine();
                machine.start = input;
                    }
           //Console.WriteLine(StateMachine.Equals());
            //  Console.WriteLine("Nomorelevels -> NewGame " + machine.Accepts(""));
            //  Console.WriteLine("NewGame --> Nomorelevels " + machine.Accepts("NewGameNomorelevels"));
            Console.ReadLine();
            await Task.Delay(100000);
        }
    }

    class StateMachine<T> : IEnumerable<Transition<T>>
    {
        public string start { get; set; }
        HashSet<string> ends = new HashSet<string>();
        Dictionary<string, Dictionary<T, string>> transitions = new Dictionary<string, Dictionary<T, string>>();

        public string name { get; set; }

        public StateMachine(string name, string start, params string[] ends)
        {
            this.name = name;
            this.start = start;
            this.ends.UnionWith(ends);
        }

        public void Add(string from, string to, T value)
        {
            if (transitions.ContainsKey(from) == false)
                transitions[from] = new Dictionary<T, string>();

            transitions[from][value] = to;
        }


        public override string ToString()
        {
            string nodes = string.Join(", ", this.transitions.Keys);
            string values = string.Join(", ", this.transitions[start].Keys);
            string ends = string.Join(", ", this.ends);
            string transitions = string.Join("\n   ", this);

            return $"{name} = (\n{{{nodes}}}, \n{{{values}}}, \nQ,\n Start = {start},\n {{{ends}}})\nQ: {transitions}";
            //return $"{start} = (\n{{{nodes}}}, \n{{{values}}}, \nQ,\n Start = {start},\n {{{ends}}})\nQ: {transitions}";

        }

        public IEnumerator<Transition<T>> GetEnumerator()
        {
            return transitions.SelectMany(
                node => node.Value.Select(to => new Transition<T>(node.Key, to.Value, to.Key))).GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

       /* public bool Accepts(IEnumerable<T> @string)
        {
            string state = start;

            foreach (T value in @string)
                state = transitions[state][value];

            return ends.Contains(state);
        }
        */

    }

class Transition<T>
    {
        public string From { get; }
        public string To { get; }
        public T Value { get; }

        public Transition(string from, string to, T value)
        {
            From = from;
            To = to;
            Value = value;
        }

        public override string ToString() => $"q({From}, {Value}) = {To}";
    }
}

【问题讨论】:

    标签: c# unity3d state state-machine fsm


    【解决方案1】:

    最简单的 FSM 实现了一个 State Next(Event e) 方法,而你的并没有这样做。您不应期望每个消费者都遍历所有转换以找到下一个状态。

    状态应该是值类型,例如枚举,而不是引用类型,例如字符串,并且您应该实现转换表,例如 Dictionary&lt;ValueTuple&lt;State current, Event transition&gt;, State result&gt;,而不是需要双重查找的 Dictionary&lt;State current, &lt;Dictionary&lt;Event transition, State result&gt;&gt;

    有限状态机是计算机科学中的一个基本概念,你应该学习一些理论和现有的实现。

    【讨论】:

    • 我是新的状态机和转换表..你可以参考一些通用状态机的来源和更简单的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 2012-04-02
    • 2012-02-20
    • 2022-10-15
    • 2015-01-18
    • 2020-01-27
    相关资源
    最近更新 更多