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

一.引言言

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

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

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

1 控制城門的狀態(tài)機(jī)

在描述有限狀態(tài)機(jī)時,狀態(tài)、事件、轉(zhuǎn)換和動作是經(jīng)常會碰到的幾個基本概念。

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

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

轉(zhuǎn)換(Transition指的是兩個狀態(tài)之間的一種關(guān)系,表明對象將在第一個狀態(tài)中執(zhí)行一定的動作,并將在某個事件發(fā)生同時某個特定條件滿足時進(jìn)入第二個狀態(tài)。

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

二、基于傳統(tǒng)C語言的FSM實(shí)現(xiàn)技術(shù)

2.1、基于switch(狀態(tài))的實(shí)現(xiàn)

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

 

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

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

 

 
switch (state)  {
 
  // 處理狀態(tài)Opened的分支
  case (Opened): {
    // 執(zhí)行動作Open
    open();
    // 檢查是否有激發(fā)狀態(tài)轉(zhuǎn)換的事件產(chǎn)生
    if (checkStateChange()) {
      // 對狀態(tài)機(jī)的狀態(tài)進(jìn)行轉(zhuǎn)換
      performStateChange();
    }
    break;
  } 
  // 處理狀態(tài)Closed的分支
  case (Closed): {
    // 執(zhí)行動作Close
    close();
    // 檢查是否有激發(fā)狀態(tài)轉(zhuǎn)換的事件產(chǎn)生
    if (checkStateChange()) {
      // 對狀態(tài)機(jī)的狀態(tài)進(jìn)行轉(zhuǎn)換
      performStateChange();
    }
    break;
  }
 
  // 處理狀態(tài)Locked的分支
  case (Locked): {
    // 執(zhí)行動作Lock
    lock();
    // 檢查是否有激發(fā)狀態(tài)轉(zhuǎn)換的事件產(chǎn)生
    if (checkStateChange()) {
      // 對狀態(tài)機(jī)的狀態(tài)進(jìn)行轉(zhuǎn)換
      performStateChange();
    }
    break;
  }
 
  // 處理狀態(tài)Unlocked的分支
  case (Unlocked): {
    // 執(zhí)行動作Lock
    unlock();
    // 檢查是否有激發(fā)狀態(tài)轉(zhuǎn)換的事件產(chǎn)生
    if (checkStateChange()) {
      // 對狀態(tài)機(jī)的狀態(tài)進(jìn)行轉(zhuǎn)換
      performStateChange();
    }
    break;
  } 
}

checkStateChange()performStateChange()這兩個函數(shù)本身依然會在面對很復(fù)雜的狀態(tài)機(jī)時,內(nèi)部邏輯變得異常臃腫,甚至可能是難以實(shí)現(xiàn)。

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

三、基于面向?qū)ο蟮?/span>FSM實(shí)現(xiàn)技術(shù)

3.1、用一個類實(shí)現(xiàn)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);

}

  
-關(guān)于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>
            在线观看亚洲视频| 久久亚洲精品伦理| 欧美一区影院| 亚洲一区二区久久| 亚洲第一精品夜夜躁人人躁| 国产精品麻豆欧美日韩ww | 久久不射中文字幕| 欧美亚洲三区| 久久aⅴ国产欧美74aaa| 久久精彩视频| 久久久久久9| 欧美成人一区二区三区在线观看 | 欧美国产丝袜视频| 亚洲国产清纯| 欧美国产日韩一区| 一区二区激情视频| 久久av红桃一区二区小说| 久久综合影音| 国产精品久久福利| 一区二区视频免费在线观看| 亚洲国产精品999| 亚洲永久视频| 久久国产日韩欧美| 欧美激情第4页| 宅男噜噜噜66一区二区| 久久久九九九九| 欧美三级网址| 国产在线精品一区二区夜色| 亚洲精品裸体| 午夜视频久久久| 91久久久久久久久久久久久| 欧美一区二区视频在线| 久久本道综合色狠狠五月| 欧美黑人多人双交| 国产真实乱偷精品视频免| 亚洲精品一区二区三区在线观看| 亚洲欧美激情视频| 亚洲大片av| 久久精品99| 欧美亚洲动漫精品| 亚洲三级性片| 噜噜噜躁狠狠躁狠狠精品视频| 国产日韩欧美亚洲一区| 亚洲精品视频在线观看免费| 久久久久久网站| 日韩一级不卡| 久久久精品国产一区二区三区| 99精品99| 久久五月天婷婷| 亚洲午夜精品国产| 欧美日韩国产精品| 亚洲黄色尤物视频| 美女日韩欧美| 久久国产精品久久久久久久久久 | 海角社区69精品视频| 亚洲在线国产日韩欧美| 欧美国产日本高清在线| 久久久欧美精品| 一区精品久久| 美女被久久久| 久久一区免费| 亚洲国产精品va在线看黑人动漫 | 蜜臀久久99精品久久久画质超高清| 亚洲色图自拍| 国产精品久久久久久久久婷婷| 亚洲无线观看| 夜夜夜久久久| 久久亚洲国产精品日日av夜夜| 亚洲综合清纯丝袜自拍| 国产精品狼人久久影院观看方式| 亚洲天堂视频在线观看| 一本久久综合亚洲鲁鲁| 国产精品久久久久一区二区三区共| 一区二区三区日韩欧美| 一本久道久久综合婷婷鲸鱼| 欧美日韩第一页| 亚洲免费在线| 午夜精品一区二区三区在线视| 国产午夜精品全部视频播放| 久久久久久黄| 久久一区激情| 亚洲私人影院| 亚洲一区国产| 经典三级久久| 亚洲精品黄色| 欧美日韩视频免费播放| 欧美sm视频| 日韩亚洲成人av在线| 亚洲精品视频一区| 国产麻豆综合| 免费毛片一区二区三区久久久| 欧美电影打屁股sp| 午夜视频久久久| 久久免费精品视频| 亚洲视频1区2区| 午夜国产精品视频免费体验区| 娇妻被交换粗又大又硬视频欧美| 亚洲日本中文字幕| 99精品国产福利在线观看免费 | 欧美日韩国产综合新一区| 亚洲伊人第一页| 久久精品国产一区二区电影| 亚洲乱亚洲高清| 久久国产高清| 亚洲性线免费观看视频成熟| 久久米奇亚洲| 午夜精品福利在线| 欧美国产欧美亚州国产日韩mv天天看完整 | 亚洲人成亚洲人成在线观看图片 | 国产精品一区二区在线观看网站 | 欧美在线播放一区| 亚洲视频999| 欧美成人免费va影院高清| 午夜精彩视频在线观看不卡| 欧美a级理论片| 久久久亚洲影院你懂的| 欧美视频在线免费| 亚洲激情网址| 在线精品国产成人综合| 亚洲专区欧美专区| 亚洲午夜黄色| 欧美69wwwcom| 欧美一区二区三区四区在线观看地址 | 欧美影院一区| 欧美日韩三级电影在线| 免费欧美视频| 国产伦精品一区二区三区视频孕妇 | 久久久久久穴| 亚洲免费中文| 好吊色欧美一区二区三区四区 | 亚洲视频一起| 9i看片成人免费高清| 麻豆成人在线| 免费观看不卡av| 黄色一区二区在线观看| 欧美一区二区三区男人的天堂 | 久久精品30| 国产欧美短视频| 亚洲女同精品视频| 久久www免费人成看片高清| 国产精品一区二区三区四区五区| 99国产精品私拍| 亚洲欧美国产制服动漫| 国产精品久久久久久久电影| 这里是久久伊人| 午夜伦欧美伦电影理论片| 国产精品乱码一区二三区小蝌蚪 | 国外成人性视频| 久久精品噜噜噜成人av农村| 久久女同互慰一区二区三区| 韩日成人av| 久久久亚洲国产天美传媒修理工| 久久综合九色综合久99| 亚洲国产精品久久精品怡红院| 欧美成人一区二区三区| 亚洲精品一级| 亚洲一区三区电影在线观看| 国产精品视频九色porn| 欧美一区二区三区日韩视频| 久久久蜜桃精品| 亚洲成人在线网| 欧美另类女人| 午夜欧美大尺度福利影院在线看 | 国产亚洲精品久久久久久| 久久精品一区二区三区不卡| 欧美激情一区二区三区在线视频| 亚洲精品资源美女情侣酒店| 国产精品福利av| 久久成人精品视频| 亚洲人体影院| 久久久久高清| 亚洲剧情一区二区| 国产欧美日韩精品丝袜高跟鞋| 久久夜色精品国产噜噜av| 99视频一区二区| 可以看av的网站久久看| 欧美系列一区| 久久中文字幕一区二区三区| 99精品视频网| 欧美高清视频| 欧美一区1区三区3区公司| 亚洲日本成人网| 国产亚洲欧美aaaa| 欧美激情二区三区| 久久精品亚洲一区二区三区浴池| 91久久久一线二线三线品牌| 久久久久国产精品厨房| 亚洲欧美日韩一区在线| 亚洲精品裸体| 极品少妇一区二区三区精品视频| 欧美日韩一区二区在线| 麻豆久久婷婷| 久久精品人人做人人爽| 一区二区三区视频在线观看| 欧美成人首页| 久久性色av| 久久久久久久尹人综合网亚洲| 这里只有精品视频| 亚洲裸体在线观看| 亚洲国产精品va在看黑人|