C# 中的通用 FSM 来实现任何状态机. 并检查用户输入的任何下一个状态



可以更简单吗? 我希望它普遍适用于任何状态机,只需更改 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}";
}
}

最简单的FSM实现了State Next(Event e)方法,而你的方法不这样做。不应期望每个使用者都循环访问所有转换以找到下一个状态。

状态应该是值类型,如枚举,而不是引用类型,如字符串,你应该实现像Dictionary<ValueTuple<State current, Event transition>, State result>这样的转换表,而不是作为需要双重查找的Dictionary<State current, <Dictionary<Event transition, State result>>

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

最新更新