來來來,用 C 寫個有限狀態機(一)

2021-10-06 06:56:23 字數 3106 閱讀 4217

一年前寫的文章了,之前更新在 github pages 上,疏於管理,現在覺得還是把這些文件放在 csdn 好了,自己看起來也方便。

2020.5.18 十元

有限狀態機是乙個很常用的技術,在流程控制和遊戲ai中都比較實用,因為狀態機程式設計簡單又很符合直覺。本文是參考《programming game ai by example》從零開始使用c++搭乙個狀態機的輪子,主要有以下幾個點:

我會在搭建的過程中穿插一些c++知識的介紹,適合不甚了解c++或是狀態機的小夥伴,手把手的程式設計教程。

遊戲框架的實現

狀態類以及遊戲物件的狀態轉換

狀態機實現

訊息機制的實現

完整的**在 github 中給出。

記得最開始工作時候也接觸過有限狀態機,當時是乙個長長的用switch寫成的狀態機,理解它的時候真的很困難。

所以現在使用一套內建規則到狀態內部去,來控制狀態的轉換。

現在就來製作乙個有限狀態機。

作為乙個關於使用狀態機建立乙個智慧型體的實際案例,我們先模擬這樣乙個場景。想象乙個我們控制的角色「我」,在上海延安西路附近工作學習和玩耍,「我」相當的佛系,有錢不愁吃喝就去上學,自由自在地給技能樹加點,沒錢了就去實習賺外塊,渴了累了就近「啤酒阿姨」兩瓶啤酒……

但是,這個例子要全靠想象力了,因為這是在控制台中的文字演示。

[圖1 這個狀態機的示意圖,su***ce畫一下,忍一忍買pro7吧]

因此,這個例子中有四個位置:乙個學校,可以讓「我」提高能力;乙個實習公司,根據「我」的能力,給我發實習津貼;乙個啤酒阿姨酒吧,讓「我」可以解除壓力;最後還有乙個溫馨的家吼,能夠解除疲勞。

而這些位置每乙個都代表了乙個狀態,因為我們是使用內建規則來控制狀態機的轉換,「我」在到達乙個位置之後要幹什麼,都會由當前所處的狀態和一些屬性值來決定。

&&&&逐個介紹一下,要點的擴充套件寫成補充的blog放到前面,加鏈結。

basegameentity類,用來作為所有遊戲物件的基類,主要為遊戲物件提供了乙個id,以及每一幀更新時呼叫的純虛函式update。

class

basegameentity

virtual

~basegameentity()

virtual

void

update()

=0;intid(

)const

}

使用乙個列舉型別管理所有可能到達的地點,sweethome、school、company、beerlady 分別代表家、學校、實習公司、啤酒阿姨這四個地點。在 me 類中,對「我」所特有的屬性進行了定義,如心情值( m_imoodfordoingstuffs ),金錢數( m_imoneyincard ),能力( m_iabilitylevel ),疲勞( m_ifatigue ),以及這些屬性的閾值,用來在狀態轉移中起作用。隨後定義的方法表明了這些屬性如何變化,並為其他類檢視這些屬性暴露了介面。

enum location_type

;classme:

public basegameentity

void

changelocation

(const location_type goal)

intability()

const

void

setabilitylevel

(const

int val)

void

addtoability

(const

int val)

;int

moneyincard()

const

void

setmoneyincard

(const

int val)

void

thepayday

(const

int val)

;bool

fatigued()

const

;bool

rested()

const

;void

decreasefatigue

(const

int val)

void

increasefatigue

(const

int val)

bool

lowmood()

const

;void

decreasemood

(const

int val)

void

increasemood

(const

int val)

bool

feelpoor()

const

;void

buythebeer()

};

接下來是狀態 state 類,這是乙個純虛類(抽象類),作為狀態物件的乙個通用介面。類中所有方法都是虛函式,需要在繼承自 state 的類中實現具體邏輯。enter() 方法在進入狀態時呼叫一次,隨後執行 execute() 方法處理狀態的主要邏輯,在狀態退出時,會執行 exit() 方法。

class

state

virtual

void

enter

(me*)=

0;virtual

void

execute

(me*)=

0;virtual

void

exit

(me*)=

0;};

在這裡使用單例模式實現每乙個狀態,一切從簡,不考慮執行緒安全。分別針對不同的地點,定義在每個地點的狀態類,**如下:

// my states

class

goworkandearnmoney

:public state

;class

goschoolandstudy

:public state

;class

gohomeandsleep

:public state

;class

gobar

:public state

;

C 有限狀態機

用乙個類定義事件和狀態 檔案 globalautodcl.h const int nbmaxaction 10 const int nbmaxstate 5 const int nbmaxevent 6 class globalautodcl typedef enum 用乙個抽象類定義一些陣列,ac...

C語言實現有限狀態機

在實際工作中,經常遇到狀態機的應用,尤其在網路協議部分,最為經典的就是tcp協議的狀態機 實際上,很多網路協議都是有工作狀態的,不同階段所處不同的狀態,例如dhcp協議,路由協議,sip協議等等。這些協議在實現的時候多多少少會用到狀態機的原理,可能在實現上有較大的差別。我原來只是聽說過有這個原理,但...

《遊戲程式設計模式》一7 2 救星 有限狀態機

為了消除你心中的疑惑,你可以準備一張紙和一支筆,讓我們一起來畫一張流程圖。對於女主角能夠進行的動作畫乙個 矩形 站立 跳躍 躲避和俯衝。當你可以按下乙個鍵讓主角從乙個狀態切換到另乙個狀態的時候,我們畫乙個箭頭,讓它從乙個矩形指向另乙個矩形。同時在箭頭上面新增文字,表示我們按下的按鈕。恭喜,你剛剛已經...