亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

一個狀態(tài)機的實現(xiàn)

 更新時間:2017年02月03日 09:13:08   作者:諾貝爾  
本文主要介紹了C#實現(xiàn)一個狀態(tài)機的思路與方法,具有很好的參考價值,下面跟著小編一起來看下吧

話不多說,先看代碼:

interface IState
 {
  string Name { get; set; }
  //后件處理
  IList<IState> Nexts { get; set; }
  Func<IState /*this*/, IState /*next*/> Selector { get; set; }
  
 }
 class State : IState
 {
  public string Name { get; set; } = "State";

  IList<IState> IState.Nexts { get; set; } = new List<IState>();
  public Func<IState, IState> Selector { get; set; }
 }

狀態(tài)比較簡單,一個Name標識,一個后件狀態(tài)列表,然后一個狀態(tài)選擇器。

比如狀態(tài)a,可以轉(zhuǎn)移到狀態(tài)b,c,d,那么選擇器就是其中一個。至于怎么選,就讓用戶來定義實際的選擇器了。

delegate bool HandleType<T>(IState current, IState previous,ref T value);
 interface IContext<T> : IEnumerator<T>, IEnumerable<T>
 {
  //data
  T Value { get; set; }
  //前件處理
  IDictionary<Tuple<IState/*this*/, IState/*previous*/>, HandleType<T>> Handles { get; set; }
  IState CurrentState { get; set; }
  bool transition(IState next);
 }

和狀態(tài)類State關(guān)注后件狀態(tài)不同,上下文類Context關(guān)注前件狀態(tài)。當跳轉(zhuǎn)到一個新的狀態(tài),這個過程中就要根據(jù)當前狀態(tài)來實施不同的策略。比如想進入狀態(tài)c,根據(jù)當前狀態(tài)是a, b,d 有不同的處理程序。這種轉(zhuǎn)移處理程序,是一一對應(yīng)的,所以用了 Tuple<進入的狀態(tài),當前狀態(tài)> 來描述一個跳轉(zhuǎn)鏈。然后用Dictionary 捆綁相關(guān)的處理程序。

上下文會攜帶 T Value 數(shù)據(jù),要怎么處理這種數(shù)據(jù)?我是通過ref 參數(shù)來傳遞給處理程序。因為我不想IState 關(guān)心上下文的構(gòu)造,它只需要關(guān)注實際的數(shù)據(jù) T value;

上下文保存數(shù)據(jù)和當前狀態(tài),然后通過transiton 讓用戶控制狀態(tài)的轉(zhuǎn)移。這里面有一個重復(fù),因為IState有選擇器來控制狀態(tài)轉(zhuǎn)移了。為什么要這么處理?我是為了構(gòu)造一個跳轉(zhuǎn)序列。引入IEnumerator和IEnumerable接口,然狀態(tài)可以在選擇器的作用下自動跳轉(zhuǎn),然后用foreach 讀取結(jié)果序列(只是不知道有什么用)。

class Context<T> : IContext<T>
 {
  T data;
  T IContext<T>.Value { get=>data ; set=>data = value; }
  IDictionary<Tuple<IState, IState>, HandleType<T>> IContext<T>.Handles { get; set; } 
   = new Dictionary<Tuple<IState, IState>, HandleType<T>>();
  public IState CurrentState { get; set;}
  T IEnumerator<T>.Current => (this as IContext<T>).Value ;
  object IEnumerator.Current => (this as IContext<T>).Value;
  bool IContext<T>.transition(IState next)
  {
   IContext<T> context= this as IContext<T>;
   if (context.CurrentState == null || context.CurrentState.Nexts.Contains(next))
   {
    //前件處理
    var key = Tuple.Create(next, context.CurrentState);
    if (context.Handles.ContainsKey(key) && context.Handles[key] !=null)
     if (!context.Handles[key](next, context.CurrentState,ref this.data))
      return false;

    context.CurrentState = next;
    return true;
   }
   return false;
  }
  bool IEnumerator.MoveNext()
  {
   //后件處理
   IContext<T> context = this as IContext<T>;
   IState current = context.CurrentState; 
   if (current == null)
    throw new Exception("必須設(shè)置初始狀態(tài)");
   if (context.CurrentState.Selector != null)
   {
    IState next= context.CurrentState.Selector(context.CurrentState);
    return context.transition(next);
   }
   return false;
  }
  void IEnumerator.Reset()
  {
   throw new NotImplementedException();
  }
  #region IDisposable Support
  private bool disposedValue = false; // 要檢測冗余調(diào)用
  protected virtual void Dispose(bool disposing)
  {
   if (!disposedValue)
   {
    if (disposing)
    {
     // TODO: 釋放托管狀態(tài)(托管對象)。
    }
    // TODO: 釋放未托管的資源(未托管的對象)并在以下內(nèi)容中替代終結(jié)器。
    // TODO: 將大型字段設(shè)置為 null。
    disposedValue = true;
   }
  }
  // TODO: 僅當以上 Dispose(bool disposing) 擁有用于釋放未托管資源的代碼時才替代終結(jié)器。
  // ~Context() {
  // // 請勿更改此代碼。將清理代碼放入以上 Dispose(bool disposing) 中。
  // Dispose(false);
  // }
  // 添加此代碼以正確實現(xiàn)可處置模式。
  void IDisposable.Dispose()
  {
   // 請勿更改此代碼。將清理代碼放入以上 Dispose(bool disposing) 中。
   Dispose(true);
   // TODO: 如果在以上內(nèi)容中替代了終結(jié)器,則取消注釋以下行。
   // GC.SuppressFinalize(this);
  }
  IEnumerator<T> IEnumerable<T>.GetEnumerator()
  {
   return this;
  }
  IEnumerator IEnumerable.GetEnumerator()
  {
   return this;
  }
  #endregion
 }

重點關(guān)注transition函數(shù)和MoveNext函數(shù)。

bool IContext<T>.transition(IState next)
  {
   IContext<T> context= this as IContext<T>;
   if (context.CurrentState == null || context.CurrentState.Nexts.Contains(next))
   {
    //前件處理
    var key = Tuple.Create(next, context.CurrentState);
    if (context.Handles.ContainsKey(key) && context.Handles[key] !=null)
     if (!context.Handles[key](next, context.CurrentState,ref this.data))
      return false;
    context.CurrentState = next;
    return true;
   }
   return false;
  }

做的事也很簡單,就是調(diào)用前件處理程序,處理成功就轉(zhuǎn)移狀態(tài),否則退出。

bool IEnumerator.MoveNext()
  {
   //后件處理
   IContext<T> context = this as IContext<T>;
   IState current = context.CurrentState; 
   if (current == null)
    throw new Exception("必須設(shè)置初始狀態(tài)");
   if (context.CurrentState.Selector != null)
   {
    IState next= context.CurrentState.Selector(context.CurrentState);
    return context.transition(next);
   }
   return false;
  }

MoveNext通過選擇器來選擇下一個狀態(tài)。

總的來說,我這個狀態(tài)機的實現(xiàn)只是一個框架,沒有什么功能,但是我感覺是比較容易編寫狀態(tài)轉(zhuǎn)移目錄樹的。

用戶首先要創(chuàng)建一組狀態(tài),然后建立目錄樹結(jié)構(gòu)。我的實現(xiàn)比較粗糙,因為用戶要分別構(gòu)建目錄樹,前件處理器,還有后件選擇器這三個部分。編寫測試代碼的時候,我寫了9個狀態(tài)的網(wǎng)狀結(jié)構(gòu),結(jié)果有點眼花繚亂。要是能統(tǒng)一起來估計會更好一些。

要關(guān)注的是第一個狀態(tài),和最后的狀態(tài)的構(gòu)造,否則無法停機,嵌入死循環(huán)。

//測試代碼
//---------創(chuàng)建部分---------
string mess = "";//3   
IState s3 = new State() { Name = "s3" };
//2   
IState s2 = new State() { Name = "s2" };
//1   
IState s1 = new State() { Name = "s1" };
//---------組合起來---------   
s1.Nexts = new List<IState> { s2, s3 };   
s2.Nexts = new List<IState> { s1, s3 };   
s3.Nexts = new List<IState> { }; //注意end寫法
//---------上下文---------    
//transition   
IContext<int> cont = new Context<int> { CurrentState=s1};//begin   
cont.Value = 0;
//---------狀態(tài)處理器--------- 
HandleType<int> funcLaji = (IState current, IState previous, ref int v) => { mess += $"{current.Name}:垃圾{previous.Name}\n"; v++; return true; };
//1   
cont.Handles.Add(Tuple.Create(s1 , default(IState)), funcLaji);   
cont.Handles.Add(Tuple.Create(s1, s2), funcLaji);
//2   
cont.Handles.Add(Tuple.Create(s2, s1), funcLaji);
//3   
cont.Handles.Add(Tuple.Create(s3, s1), funcLaji); 
cont.Handles.Add(Tuple.Create(s3, s2), funcLaji);
//---------狀態(tài)選擇器---------    
var rval = new Random();   
Func<int,int> round = x => rval.Next(x);   
s1.Selector = st => round(2)==0? s2:s3;   
s2.Selector = st => round(2)==0? s1:s3;

構(gòu)造完畢后,就可以使用這個狀態(tài)機了。

//選擇器跳轉(zhuǎn)   
mess += "選擇器跳轉(zhuǎn):\n------------------------\n";
foreach (var stor in cont)
    mess+=$"狀態(tài)轉(zhuǎn)變次數(shù):{stor}\n";
//直接控制跳轉(zhuǎn)
mess += "\n直接控制狀態(tài)跳轉(zhuǎn):\n------------------------\n";
cont.transition(s1);
cont.transition(s2);
cont.transition(s3);

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關(guān)文章

  • C#學(xué)習(xí)基礎(chǔ)概念二十五問

    C#學(xué)習(xí)基礎(chǔ)概念二十五問

    C#學(xué)習(xí)基礎(chǔ)概念二十五問...
    2007-04-04
  • C#數(shù)據(jù)適配器DataAdapter

    C#數(shù)據(jù)適配器DataAdapter

    這篇文章介紹了C#中的數(shù)據(jù)適配器DataAdapter,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • c#預(yù)處理指令分析

    c#預(yù)處理指令分析

    這篇文章主要介紹了c#預(yù)處理指令的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c#,感興趣的朋友可以了解下
    2020-08-08
  • c#實現(xiàn)winform屏幕截圖并保存的示例

    c#實現(xiàn)winform屏幕截圖并保存的示例

    這篇文章主要介紹了c#實現(xiàn)winform屏幕截圖并保存的示例,需要的朋友可以參考下
    2014-02-02
  • C#中OpenCvSharp 通過特征點匹配圖片的方法

    C#中OpenCvSharp 通過特征點匹配圖片的方法

    這篇文章主要介紹了OpenCvSharp 通過特征點匹配圖片的方法,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • C#文件上傳的簡單實現(xiàn)

    C#文件上傳的簡單實現(xiàn)

    這篇文章主要為大家詳細介紹了C#文件上傳的簡單實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • C#中的lock()如何使用

    C#中的lock()如何使用

    在C#中,lock?關(guān)鍵字用于確保某個代碼塊在任何時刻只被一個線程訪問,本文主要介紹了C#中的lock()如何使用,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Unity3D中腳本的執(zhí)行順序和編譯順序

    Unity3D中腳本的執(zhí)行順序和編譯順序

    在Unity中可以同時創(chuàng)建很多腳本,并且可以分別綁定到不同的游戲?qū)ο笊希鼈兏髯远荚谧约旱纳芷谥羞\行。與腳本有關(guān)的也就是編譯和執(zhí)行啦,本文就來研究一下Unity中腳本的編譯和執(zhí)行順序的問題。
    2014-11-11
  • C#預(yù)處理器指令的用法實例分析

    C#預(yù)處理器指令的用法實例分析

    這篇文章主要介紹了C#預(yù)處理器指令的用法,以實例形式較為詳細的分析了預(yù)處理器指令的原理與相應(yīng)的用法,有助于深入理解C#程序的運行原理,需要的朋友可以參考下
    2014-11-11
  • C#自定義的字符串操作增強類實例

    C#自定義的字符串操作增強類實例

    這篇文章主要介紹了C#自定義的字符串操作增強類,涉及C#操作字符串實現(xiàn)分割、轉(zhuǎn)換、去重等常用技巧,非常具有實用價值,需要的朋友可以參考下
    2015-03-03

最新評論