青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

基于C++有限狀態機的實現技術(調查報告)

Posted on 2008-06-13 15:01 RichardHe 閱讀(1846) 評論(0)  編輯 收藏 引用 所屬分類: [轉]
一.引言言

有 限狀態機是一種用來進行對象行為建模的工具,其作用主要是描述對象在它的生命周期內所經歷的狀態序列,以及如何響應來自外界的各種事件。在面向對象的軟件 系統中,一個對象無論多么簡單或者多么復雜,都必然會經歷一個從開始創建到最終消亡的完整過程,這通常被稱為對象的生命周期。一般說來,對象在其生命期內 是不可能完全孤立的,它必須通過發送消息來影響其它對象,或者通過接受消息來改變自身。在大多數情況下,這些消息都只不過是些簡單的、同步的方法調用而 已。例如,在銀行客戶管理系統中,客戶類(Customer)的實例在需要的時候,可能會調用帳戶(Account)類中定義的getBalance()方法。在這種簡單的情況下,類Customer并不需要一個有限狀態機來描述自己的行為,主要原因在于它當前的行為并不依賴于過去的某個狀態。[1]

遺憾的是并不是所有情況都會如此簡單,事實上許多實用的軟件系統都必須維護一兩個非常關鍵的對象,它們通常具有非常復雜的狀態轉換關系,而且需要對來自外部的各種異步事件進行響應。例如,在VoIP電話系統中,電話類(Telephone)的實例必須能夠響應來自對方的隨機呼叫,來自用戶的按鍵事件,以及來自網絡的信令等。在處理這些消息時,類Telephone所要采取的行為完全依賴于它當前所處的狀態,因而此時使用狀態機就將是一個不錯的選擇。[1]

游戲引擎是有限狀態機最為成功的應用領域之一,由于設計良好的狀態機能夠被用來取代部分的人工智能算法,因此游戲中的每個角色或者器件都有可能內嵌一個狀態機。考慮RPG游戲中城門這樣一個簡單的對象,它具有打開(Opened)、關閉(Closed)、上鎖(Locked)、解鎖(Unlocked)四種狀態,如圖1所示。當玩家到達一個處于狀態Locked的門時,如果此時他已經找到了用來開門的鑰匙,那么他就可以利用它將門的當前狀態轉變為Unlocked,進一步還可以通過旋轉門上的把手將其狀態轉變為Opened,從而成功地進入城內。[1]

1 控制城門的狀態機

在描述有限狀態機時,狀態、事件、轉換和動作是經常會碰到的幾個基本概念。

狀態(State指的是對象在其生命周期中的一種狀況,處于某個特定狀態中的對象必然會滿足某些條件、執行某些動作或者是等待某些事件。

事件(Event指的是在時間和空間上占有一定位置,并且對狀態機來講是有意義的那些事情。事件通常會引起狀態的變遷,促使狀態機從一種狀態切換到另一種狀態。

轉換(Transition指的是兩個狀態之間的一種關系,表明對象將在第一個狀態中執行一定的動作,并將在某個事件發生同時某個特定條件滿足時進入第二個狀態。

   動作(Action指的是狀態機中可以執行的那些原子操作,所謂原子操作指的是它們在運行的過程中不能被其他消息所中斷,必須一直執行下去。

二、基于傳統C語言的FSM實現技術

2.1、基于switch(狀態)的實現

在實現有限狀態機時,使用switch語句是最簡單也是最直接的一種方式,其基本思路是為狀態機中的每一種狀態都設置一個case分支,專門用于對該狀態進行控制。下面的代碼示范了如何運用switch語句,來實現圖1中所示的狀態機:

 

 
switch (state)  {
  // 處理狀態Opened的分支
  case (Opened): {
    // 執行動作Open
    open();
    // 檢查是否有CloseDoor事件
    if (closeDoor()) { 
      // 當前狀態轉換為Closed
      changeState(Closed)
    }
    break;
  } 
  // 處理狀態Closed的分支
  case (Closed): {
    // 執行動作Close
    close();
    // 檢查是否有OpenDoor事件
    if (openDoor()) {
      // 當前狀態轉換為Opened
      changeState(Opened);
    }
    // 檢查是否有LockDoor事件
    if (lockDoor()) {
      // 當前狀態轉換為Locked
      changeState(Locked);
    }
    break;
  }
 
  // 處理狀態Locked的分支
  case (Locked): {
    // 執行動作Lock
    lock();
    // 檢查是否有UnlockDoor事件
    if (unlockDoor()) {
      // 當前狀態轉換為Unlocked
      changeState(Unlocked);
    }
    break;
  }
 
  // 處理狀態Unlocked的分支
  case (Unlocked): {
    // 執行動作Unlock
    unlock();
    // 檢查是否有LockDoor事件
    if (lockDoor()) {
      // 當前狀態轉換為Locked    
      changeState(Locked)
    }
    // 檢查是否有OpenDoor事件    
    if (openDoor()) {
      // 當前狀態轉換為Opened
      changeSate(Opened);
    }
    break;
  } 
}

使用switch語句實現的有限狀態機的確能夠很好地工作,但代碼的可讀性并不十分理想,主要原因是在實現狀態之間的轉換時,檢查轉換條件和進行狀態轉換都是混雜在當前狀態中來完成的。例如,當城門處于Opened狀態時,需要在相應的case中調用closeDoor()函數來檢查是否有必要進行狀態轉換,如果是的話則還需要調用changeState()函數將當前狀態切換到Closed。顯然,如果在每種狀態下都需要分別檢查多個不同的轉換條件,并且需要根據檢查結果讓狀態機切換到不同的狀態,那么這樣的代碼將是枯燥而難懂的。從代碼重構的角度來講,此時更好的做法是引入checkStateChange()performStateChange()兩個函數,專門用來對轉換條件進行檢查,以及激活轉換時所需要執行的各種動作。這樣一來,程序結構將變得更加清晰:

 

 
switch (state)  {
 
  // 處理狀態Opened的分支
  case (Opened): {
    // 執行動作Open
    open();
    // 檢查是否有激發狀態轉換的事件產生
    if (checkStateChange()) {
      // 對狀態機的狀態進行轉換
      performStateChange();
    }
    break;
  } 
  // 處理狀態Closed的分支
  case (Closed): {
    // 執行動作Close
    close();
    // 檢查是否有激發狀態轉換的事件產生
    if (checkStateChange()) {
      // 對狀態機的狀態進行轉換
      performStateChange();
    }
    break;
  }
 
  // 處理狀態Locked的分支
  case (Locked): {
    // 執行動作Lock
    lock();
    // 檢查是否有激發狀態轉換的事件產生
    if (checkStateChange()) {
      // 對狀態機的狀態進行轉換
      performStateChange();
    }
    break;
  }
 
  // 處理狀態Unlocked的分支
  case (Unlocked): {
    // 執行動作Lock
    unlock();
    // 檢查是否有激發狀態轉換的事件產生
    if (checkStateChange()) {
      // 對狀態機的狀態進行轉換
      performStateChange();
    }
    break;
  } 
}

checkStateChange()performStateChange()這兩個函數本身依然會在面對很復雜的狀態機時,內部邏輯變得異常臃腫,甚至可能是難以實現。

在很長一段時期內,使用switch語 句一直是實現有限狀態機的唯一方法,甚至像編譯器這樣復雜的軟件系統,大部分也都直接采用這種實現方式。但之后隨著狀態機應用的逐漸深入,構造出來的狀態 機越來越復雜,這種方法也開始面臨各種嚴峻的考驗,其中最令人頭痛的是如果狀態機中的狀態非常多,或者狀態之間的轉換關系異常復雜,那么簡單地使用switch語句構造出來的狀態機將是不可維護的。

三、基于面向對象的FSM實現技術

3.1、用一個類實現FSM

 

class DoorFSM {

private:

   States __Y;

   std::queue<Event> __events;

   void __processEvent( Event e );

 

protected:

   virtual void enterOpened() = 0;

   virtual void enterLocked() = 0;

   virtual void enterUnlocked() = 0;

   virtual void enterClosed() = 0;

public:

/* States */

   enum States { Closed, Unlocked, Locked, Opened   }; // states

/*Events*/

   enum Event { Lock, Unlock, Open, Close   };

   /// Constructor

   DoorFSM() { __Y = Opened; }

   /// Destructor

   virtual ~DoorFSM() {}

 

   /** Get current FSM state

       @returns current FSM state

    */

   States currentState() { return __Y; }

 

   /** Send event to FSM

       Use this function to send event to DoorFSM After you call it given event will be handled, and, if some of transition conditions match, appropriate transition will be triggered, and currentState() will be changed. If this function is called during existing event handling process, given event will be added to pending event queue, and will be handled after current transition. See examples for details.

   */

   void A( Event e );

};

void DoorFSM::__processEvent( Event e )

{

   States yOld = __Y;

   bool pass = false;

   switch( __Y ) { //transitions

   case Closed:

      if( e == Open ) {

         //outcome actions

         __Y = Opened;

         pass = true;

      }

      else if( e == Lock ) {

         //outcome actions

         __Y = Locked;

         pass = true;

      }

      break;

   case Unlocked:

      if( e == Lock ) {

         //outcome actions

         __Y = Locked;

         pass = true;

      }

      else if( e == Open ) {

         //outcome actions

         __Y = Opened;

         pass = true;

      }

      break;

   case Locked:

      if( e == Unlock ) {

         //outcome actions

         __Y = Unlocked;

         pass = true;

      }

      break;

   case Opened:

      if( e == Close ) {

         //outcome actions

         __Y = Closed;

         pass = true;

      }

      break;

   }

 

   if( yOld == __Y && !pass ) { return; }

 

   switch( __Y ) { // income actions

   case Closed:

         enterClosed();

      break;

   case Unlocked:

         enterUnlocked();

      break;

   case Locked:

         enterLocked();

      break;

   case Opened:

         enterOpened();

      break;

   }

}

 

void DoorFSM::A( Event e )

{

   bool __empty = __events.empty();

   __events.push( e );

   if( __empty ) {

      while( !__events.empty() ) {

         __processEvent( __events.front() );

         __events.pop();

      }

   }

}

 

 

class DoorFSMLogic : public DoorFSM

{

 protected:

  virtual void enterOpened(){std::cout << "Enter Opened state." << std::endl;}

  virtual void enterLocked() {std::cout << "Enter Closed state." << std::endl;}

  virtual void enterUnlocked() {std::cout << "Enter Locked state." << std::endl;}

  virtual void enterClosed() {std::cout << "Enter Unlocked state." << std::endl;}

};

測試程序

int main()

{

  DoorFSMLogic door;

  door.A(DoorFSM::Close);

  door.A(DoorFSM::Lock);

  door.A(DoorFSM::Unlock);

  door.A(DoorFSM::Open);

}

  
-關于FSM

posts - 94, comments - 138, trackbacks - 0, articles - 94

Copyright © RichardHe

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲第一黄色| 亚洲人成毛片在线播放| 久久爱www| 亚洲激情视频网站| 狂野欧美激情性xxxx| 国产日本欧美一区二区三区| 一本一本a久久| 亚洲激情视频在线| 久久视频在线看| 久久久精品日韩| 新狼窝色av性久久久久久| 欧美高清免费| 99精品国产福利在线观看免费| 免费国产自线拍一欧美视频| 久久大综合网| 精品999久久久| 欧美成人蜜桃| 欧美a级片一区| 99日韩精品| 亚洲午夜视频在线观看| 国产欧美日韩视频一区二区| 久久成年人视频| 久久精品成人一区二区三区蜜臀| 国产综合久久久久影院| 久久中文字幕一区| 麻豆精品精品国产自在97香蕉| 亚洲国产影院| 夜夜嗨av一区二区三区中文字幕| 国产精品久久久久一区二区三区 | 欧美另类综合| 亚洲一区二区三区在线播放| 亚洲女同精品视频| 韩国av一区| 欧美激情一区三区| 国产精品h在线观看| 欧美在线观看日本一区| 久久久精品国产免费观看同学| 一区二区三区无毛| 亚洲精品视频免费观看| 国产精品久久久久毛片大屁完整版| 欧美一区二区三区日韩| 久久午夜精品| 亚洲一区欧美激情| 久久婷婷影院| 亚洲自拍高清| 麻豆久久精品| 午夜精品福利视频| 久久久久久亚洲精品中文字幕| 亚洲精品视频一区| 亚洲欧美视频在线观看视频| 亚洲韩国日本中文字幕| 亚洲视频在线视频| 亚洲国产成人av| 亚洲免费在线| 亚洲免费av观看| 欧美在线观看你懂的| 在线亚洲自拍| 麻豆av福利av久久av| 欧美亚洲三级| 欧美日本韩国在线| 女人香蕉久久**毛片精品| 国产精品久久久久免费a∨| 女女同性精品视频| 国产一区二区三区高清| 亚洲视频二区| 99综合精品| 免费欧美电影| 噜噜噜噜噜久久久久久91| 国产精品美女久久久久av超清| 欧美日韩免费在线视频| 99热这里只有精品8| 久久久亚洲综合| 欧美伊人久久久久久午夜久久久久| 欧美激情一区二区三级高清视频| 久久久国产一区二区| 国产精品国产三级国产aⅴ浪潮| 欧美国产亚洲另类动漫| 国内精品视频一区| 欧美一区二区三区免费看| 亚洲一区二区三区在线| 欧美久久婷婷综合色| 欧美国产视频一区二区| 国内视频一区| 久久精品二区| 久久亚洲精品欧美| 激情欧美一区二区三区在线观看| 欧美在线高清视频| 久久视频在线免费观看| 国产综合色在线| 久久精品国产成人| 久久婷婷亚洲| 在线免费观看视频一区| 久久久在线视频| 欧美成人第一页| 亚洲人成在线播放| 欧美精品偷拍| 一区二区三区精品视频| 亚洲欧美三级在线| 国产色产综合产在线视频| 午夜精品婷婷| 蜜乳av另类精品一区二区| 亚洲国产精品一区二区www在线| 久久在线视频在线| 亚洲国产小视频| 亚洲视频在线视频| 欧美日韩中文字幕在线视频| 国产精品99久久不卡二区| 欧美一区二区三区视频| 国内精品视频久久| 欧美www视频| 在线午夜精品| 久久久久一区| 亚洲精品乱码久久久久| 欧美色123| 久久爱www久久做| 亚洲第一福利在线观看| 亚洲一区二区三区视频| 国产亚洲精品综合一区91| 久久婷婷蜜乳一本欲蜜臀| 亚洲精品一区二区三区四区高清| 香蕉乱码成人久久天堂爱免费| 狠狠干狠狠久久| 欧美精品国产精品| 午夜精品久久久久99热蜜桃导演| 欧美1区2区| 亚洲一区二区三区在线播放| 黑人一区二区| 欧美色123| 老司机精品导航| 在线亚洲一区二区| 暖暖成人免费视频| 性刺激综合网| 99国产精品私拍| 国产综合欧美| 国产精品久久久久久一区二区三区| 久久久亚洲精品一区二区三区 | 国产精品男gay被猛男狂揉视频| 中文精品视频| 暖暖成人免费视频| 欧美亚洲一区二区在线观看| 亚洲经典在线| 国产一区二区三区久久| 欧美日本一区二区三区| 久久se精品一区精品二区| 99成人精品| 亚洲第一福利社区| 久久久精品一品道一区| 亚洲视频一区二区| 亚洲人体一区| 狠狠色丁香久久婷婷综合丁香| 激情成人亚洲| 国产精品亚洲综合| 欧美日韩一视频区二区| 久久综合久久综合九色| 欧美一区二区三区久久精品茉莉花 | 久久噜噜亚洲综合| 亚洲在线免费视频| 日韩一区二区精品在线观看| 亚洲电影免费在线观看| 狠狠色狠狠色综合系列| 国产视频亚洲精品| 国产麻豆综合| 国产精品天天看| 国产精品久久九九| 欧美体内she精视频在线观看| 欧美国内亚洲| 欧美国产精品| 欧美精品色网| 欧美日韩高清在线一区| 欧美精品九九99久久| 免费高清在线一区| 另类激情亚洲| 免费成人在线视频网站| 蜜臀av性久久久久蜜臀aⅴ四虎| 久久久久久久网| 久久视频一区二区| 免费人成精品欧美精品| 男人的天堂成人在线| 欧美第一黄网免费网站| 欧美精品一区二区三区蜜臀| 欧美精品久久久久久久免费观看 | 久久久久久久精| 欧美一区亚洲| 久久久欧美一区二区| 噜噜噜久久亚洲精品国产品小说| 久久久久久亚洲精品不卡4k岛国| 久久亚洲二区| 亚洲国产岛国毛片在线| 91久久久久| 一区二区三区四区五区精品| 亚洲性人人天天夜夜摸| 欧美一区二区三区免费看| 久久亚洲影院| 欧美劲爆第一页| 国产精品人人做人人爽| 国模私拍一区二区三区| 91久久久亚洲精品| 亚洲专区在线| 男女av一区三区二区色多| 亚洲精品国产精品国产自|