设计模式中的State模式是比较常用的模式之一,通常一个简单的AI系统会使用状态机模式.
这里我将详述简单AI系统中的状态机模式..
为此,这个简单的AI系统将会模拟一个苦逼的工人,这个工人每天要做4件事,睡觉,洗漱,吃饭,挖矿..为了做这4件事这个工人还要分别前往4个地点,分别对应的家(睡觉),,澡堂(洗漱),,餐厅(吃饭),矿场(挖矿)..
工人会在适当的条件下变换不同的状态,为此我们要准备一个状态表,描述各个状态之间转换的信息
//------------------------------------------------
//human类的状态变化表
//状态1 转换条件 状态2
//睡觉 体力恢复到100 挖矿
//洗漱 清醒恢复到100 挖矿
//吃饭 能量恢复到100 挖矿
//挖矿 体力减到10 睡觉
//挖矿 清醒减到50 洗漱
//挖矿 能量减到70 吃饭
//挖矿 赚了钱100 退休
//------------------------------------------------
工人会不停的干活直到他觉得饿了(能量减少到70)就去餐厅吃饭,或者体力减少到10就回家睡觉,或者清醒度减少的50就去洗澡,否则就继续挖矿
为此需要实现一个状态基类
class cState
{
public:
cState(void);
~cState(void);
virtual void Execute(cHuman* human)=0; //执行状态
virtual void Enter(cHuman* human)=0; //进入状态前的操作
virtual void Exit(cHuman* human)=0; //推出状态前的操作
};
接下来就是实现四个状态的类,他们都继承与上面这个基类
//sleep--------------------------------------------------
class cSleepState:public cState
{
cSleepState(void){}
public:
~cSleepState(void){}
virtual void Execute(cHuman* human);
virtual void Enter(cHuman* human);
virtual void Exit(cHuman* human);
static cSleepState* Instance();
};
//wash----------------------------------------------------
class cWashState:public cState
{
cWashState(void){}
public:
~cWashState(void){}
virtual void Execute(cHuman* human);
virtual void Enter(cHuman* human);
virtual void Exit(cHuman* human);
static cWashState* Instance();
};
//eat-----------------------------------------------------
class cEatState:public cState
{
cEatState(void){}
public:
~cEatState(void){}
virtual void Execute(cHuman* human);
virtual void Enter(cHuman* human);
virtual void Exit(cHuman* human);
static cEatState* Instance();
};
//make money----------------------------------------------
class cMakeMoneyState:public cState
{
cMakeMoneyState(void){}
public:
~cMakeMoneyState(void){}
virtual void Execute(cHuman* human);
virtual void Enter(cHuman* human);
virtual void Exit(cHuman* human);
static cMakeMoneyState* Instance();
};
#include "cState.h"
#include "cHuman.h"
#include <iostream>
using namespace std;
cState::cState(void)
{
}
cState::~cState(void)
{
}
//sleep------------------------------------------------
void cSleepState::Execute(cHuman* human)
{
if(!human)
return;
human->Sleep();
if(human->IsFullPower())
human->ChangeState(cMakeMoneyState::Instance());
}
void cSleepState::Enter(cHuman* human)
{
human->m_fMoney-=0;
human->ChangeLocal(human_local::home);
cout<<"回家睡觉去了.."<<endl;
}
void cSleepState::Exit(cHuman* human)
{
cout<<"离开家,工作去了.."<<endl;
}
cSleepState* cSleepState::Instance()
{
static cSleepState g_sleepState;
return &g_sleepState;
}
//wash-------------------------------------------------
void cWashState::Execute(cHuman* human)
{
if(!human)
return;
human->Wash();
if(human->IsFullWake())
human->ChangeState(cMakeMoneyState::Instance());
}
void cWashState::Enter(cHuman* human)
{
human->m_fMoney-=2;
human->ChangeLocal(human_local::shower);
cout<<"干了这么久,衣服都脏了,去澡堂洗个澡吧.."<<endl;
}
void cWashState::Exit(cHuman* human)
{
cout<<"洗完澡就是舒服,离开澡堂.."<<endl;
}
cWashState* cWashState::Instance()
{
static cWashState g_washState;
return &g_washState;
}
//eat--------------------------------------------------
void cEatState::Execute(cHuman* human)
{
if(!human)
return;
human->Eat();
if(human->IsFullEnerger())
human->ChangeState(cMakeMoneyState::Instance());
}
void cEatState::Enter(cHuman* human)
{
human->m_fMoney-=3;
human->ChangeLocal(human_local::restaurant);
cout<<"肚子饿了,吃饭去了,去餐厅.."<<endl;
}
void cEatState::Exit(cHuman* human)
{
cout<<"酒足饭饱,离开餐厅.."<<endl;
}
cEatState* cEatState::Instance()
{
static cEatState g_eatState;
return &g_eatState;
}
//make money---------------------------------------------
void cMakeMoneyState::Execute(cHuman* human)
{
if(!human)
return;
human->MakeMoney();
if(human->IsLowEnerger())
human->ChangeState(cEatState::Instance());
else if(human->IsLowPower())
human->ChangeState(cSleepState::Instance());
else if(human->IsLowWake())
human->ChangeState(cWashState::Instance());
}
void cMakeMoneyState::Enter(cHuman* human)
{
human->ChangeLocal(human_local::mine);
cout<<"又要去干活了,去矿场.."<<endl;
}
void cMakeMoneyState::Exit(cHuman* human)
{
cout<<"离开矿场.."<<endl;
}
cMakeMoneyState* cMakeMoneyState::Instance()
{
static cMakeMoneyState g_makeMoneyState;
return &g_makeMoneyState;
}
//以上是和状态相关的代码,接下来就实现一个工人类,代码都比较简单,一目了然
#pragma once
#include "GlobalDef.h"
#include "cState.h"
class cHuman
{
public:
cHuman(void);
~cHuman(void);
void Sleep();
void Wash();
void Eat();
void MakeMoney();
bool IsLowPower();
bool IsLowWake();
bool IsLowEnerger();
bool IsLowMoney();
bool IsFullPower();
bool IsFullWake();
bool IsFullEnerger();
bool IsFullMoney();
void Update();
void ChangeLocal(human_local local);
void ChangeState(cState* state);
//private:
//void GoHome();
//void GoShower();
//void GoRestaurant();
//void GoMine();
cState* m_curState;
float m_fPower; //体力
float m_fWake; //清醒度
float m_fEnerger; //能量
float m_fMoney; //钱
human_local m_eLocal;
};
#include "cHuman.h"
#include <iostream>
#include <stdio.h>
using namespace std;
cHuman::cHuman(void)
{
m_fPower=70;
m_fWake=100;
m_fEnerger=100;
m_fMoney=10;
m_eLocal=human_local::home;
m_curState=cSleepState::Instance();
}
cHuman::~cHuman(void)
{
}
void cHuman::Sleep()
{
cout<<"睡觉中ZZZZZzzz.. 体力="<<m_fPower<<endl;
m_fPower+=30;
}
void cHuman::Wash()
{
cout<<"洗澡.. 清醒="<<m_fWake<<endl;
m_fWake+=30;
}
void cHuman::Eat()
{
cout<<"吃饭.. 能量="<<m_fEnerger<<endl;
m_fEnerger+=30;
}
void cHuman::MakeMoney()
{
cout<<"赚钱.. 钱="<<m_fMoney<<endl;
m_fMoney++;
m_fPower-=5;
m_fWake-=5;
m_fEnerger-=5;
}
//void cHuman::GoHome()
//{
// cout<<"回家...;"<<endl;
//}
//void cHuman::GoShower()
//{
// cout<<"去澡堂...;"<<endl;
//}
//void cHuman::GoRestaurant()
//{
// cout<<"去饭店...;"<<endl;
//}
//void cHuman::GoMine()
//{
// cout<<"去矿场...;"<<endl;
//}
bool cHuman::IsLowPower()
{
return m_fPower>MIN_POWER?false:true;
}
bool cHuman::IsLowWake()
{
return m_fWake>MIN_WAKE?false:true;
}
bool cHuman::IsLowEnerger()
{
return m_fEnerger>MIN_ENERGER?false:true;
}
bool cHuman::IsLowMoney()
{
return m_fMoney>1?false:true;
}
//-------------------------------
bool cHuman::IsFullPower()
{
return m_fPower>100?true:false;
}
bool cHuman::IsFullWake()
{
return m_fWake>100?true:false;
}
bool cHuman::IsFullEnerger()
{
return m_fEnerger>100?true:false;
}
bool cHuman::IsFullMoney()
{
return m_fMoney>100?true:false;
}
void cHuman::ChangeLocal(human_local local)
{
m_eLocal=local;
}
void cHuman::ChangeState(cState* state)
{
if(!state)
return;
m_curState->Exit(this);
m_curState=state;
m_curState->Enter(this);
}
void cHuman::Update()
{
if(m_curState)
m_curState->Execute(this);
}