一个基本的状态转换范例
monster.h
#ifndef _MONSTER__ #define _MONSTER__ class MonsterStatus; //类前向声明 //怪物类 class Monster { public: Monster(int life); ~Monster(); public: int GetLife() //获取怪物血量 { return m_life; } void SetLife(int life) //设置怪物血量 { m_life = life; } MonsterStatus* getCurrentState() //获取怪物当前状态 { return m_pState; } void setCurrentState(MonsterStatus* pstate) //设置怪物当前状态 { m_pState = pstate; } public: void Attacked(int power); //怪物被攻击 private: int m_life; //血量(生命) MonsterStatus* m_pState; //持有状态对象 }; #endif
monster.cpp
#include <iostream> #include "Monster.h" #include "MonsterStatus.h" using namespace std; //构造函数,怪物的初始状态从 “凶悍”开始 Monster::Monster(int life) :m_life(life)/*, m_pState(nullptr)*/ { //m_pState = new MonsterStatus_Feroc(); m_pState = MonsterStatus_Feroc::getInstance(); } Monster::~Monster() { //delete m_pState; } //怪物被攻击 void Monster::Attacked(int power) { /*int orglife = m_life; //暂存原来的怪物血量值用于后续比较 m_life -= power; //怪物剩余血量 if (orglife > 400) //怪物原来处于凶悍状态 { if (m_life > 400) //状态未变 { m_pState->Attacked(power, this); //其他的逻辑代码被本Monster类委托给了具体状态类来处理 } else if (m_life > 100) //状态从凶悍改变到不安 { delete m_pState; //释放原有的状态对象 m_pState = new MonsterStatus_Worr(); //怪物转到不安状态 m_pState->Attacked(power, this); } else if (m_life > 0) //状态从凶悍状态改变到恐惧状态,主角的攻击太恐怖了 { delete m_pState; //释放原有的状态对象 m_pState = new MonsterStatus_Fear(); //怪物转到恐惧状态 m_pState->Attacked(power, this); } else //状态从凶悍改变到死亡 { delete m_pState; //释放原有的状态对象 m_pState = new MonsterStatus_Dead(); //怪物转到死亡状态 m_pState->Attacked(power, this); } } else if (orglife > 100) //怪物原来处于不安状态 { if (m_life > 100) //状态未变 { m_pState->Attacked(power, this); } else if (m_life > 0) //状态从不安改变到恐惧状态 { delete m_pState; //释放原有的状态对象 m_pState = new MonsterStatus_Fear(); //怪物转到恐惧状态 m_pState->Attacked(power, this); } else //状态从不安改变到死亡 { delete m_pState; //释放原有的状态对象 m_pState = new MonsterStatus_Dead(); //怪物转到死亡状态 m_pState->Attacked(power, this); } } else if (orglife > 0) //怪物原来处于恐惧状态 { if (m_life > 0) //状态未变 { m_pState->Attacked(power, this); } else //状态从恐惧改变到死亡 { delete m_pState; //释放原有的状态对象 m_pState = new MonsterStatus_Dead(); //怪物转到死亡状态 m_pState->Attacked(power, this); } } else { //已经死亡的怪物,状态不会继续发生改变 m_pState->Attacked(power, this); } */ m_pState->Attacked(power, this); }
monsterstatus.h
#ifndef _MONSTERSTATUS__ #define _MONSTERSTATUS__ class Monster; //类前向声明 //怪物状态类的父类 class MonsterStatus { public: virtual void Attacked(int power, Monster* mainobj) = 0; virtual ~MonsterStatus() {} }; //凶悍状态类 class MonsterStatus_Feroc :public MonsterStatus { public: virtual void Attacked(int power, Monster* mainobj); //virtual void Attacked(int power, Monster* mainobj) //{ // std::cout << "怪物处于凶悍状态中,对主角进行疯狂反击!" <<std::endl; // //...... //} public: static MonsterStatus_Feroc* getInstance() { static MonsterStatus_Feroc instance; return &instance; } }; //不安状态类 class MonsterStatus_Worr :public MonsterStatus { public: virtual void Attacked(int power, Monster* mainobj); //virtual void Attacked(int power, Monster* mainobj) //{ // std::cout << "怪物处于不安状态中,对主角进行反击并呼唤支援!" << std::endl; // //...... //} public: static MonsterStatus_Worr* getInstance() { static MonsterStatus_Worr instance; return &instance; } }; //恐惧状态类 class MonsterStatus_Fear :public MonsterStatus { public: virtual void Attacked(int power, Monster* mainobj); //virtual void Attacked(int power, Monster* mainobj) //{ // std::cout << "怪物处于恐惧状态中,处于逃跑之中!" << std::endl; // //...... //} public: static MonsterStatus_Fear* getInstance() { static MonsterStatus_Fear instance; return &instance; } }; //死亡状态类 class MonsterStatus_Dead :public MonsterStatus { public: virtual void Attacked(int power, Monster* mainobj); //virtual void Attacked(int power, Monster* mainobj) //{ // std::cout << "怪物死亡!" << std::endl; // //...... //} public: static MonsterStatus_Dead* getInstance() { static MonsterStatus_Dead instance; return &instance; } }; #endif
monsterstatus.cpp
#include <iostream> #include "Monster.h" #include "MonsterStatus.h" using namespace std; //各个状态子类的Attacked成员函数实现代码 void MonsterStatus_Feroc::Attacked(int power, Monster* mainobj) { int orglife = mainobj->GetLife(); //暂存怪物血量用于后续比较 if ((orglife - power) > 400) //怪物原来处于凶悍状态,现在 依然处于凶悍状态 { //状态未变 mainobj->SetLife(orglife - power); //怪物的剩余血量 std::cout << "怪物处于凶悍状态中,对主角进行疯狂反击!" << std::endl; //.....处理其他动作逻辑比如反击 } else { //不管下个状态是啥,总之不会是凶悍状态了,只可能是 不安,恐惧,死亡状态之一,先无条件的转到不安状态去(不安状态中会进行再次判断) /*delete mainobj->getCurrentState(); mainobj->setCurrentState(new MonsterStatus_Worr);*/ mainobj->setCurrentState(MonsterStatus_Worr::getInstance()); mainobj->getCurrentState()->Attacked(power, mainobj); } } void MonsterStatus_Worr::Attacked(int power, Monster* mainobj) { int orglife = mainobj->GetLife(); //暂存怪物血量用于后续比较 if ((orglife - power) > 100) //怪物原来处于不安状态,现在 依然处于不安状态 { //状态未变 mainobj->SetLife(orglife - power); //怪物的剩余血量 std::cout << "怪物处于不安状态中,对主角进行反击并呼唤支援!" << std::endl; //.....处理其他动作逻辑 } else { //不管下个状态是啥,总之不会是凶悍、不安 状态了,只可能是 恐惧,死亡状态之一,先无条件的转到恐惧状态去 /*delete mainobj->getCurrentState(); mainobj->setCurrentState(new MonsterStatus_Fear);*/ mainobj->setCurrentState(MonsterStatus_Fear::getInstance()); mainobj->getCurrentState()->Attacked(power, mainobj); } } void MonsterStatus_Fear::Attacked(int power, Monster* mainobj) { int orglife = mainobj->GetLife(); //暂存怪物血量用于后续比较 if ((orglife - power) > 0) //怪物原来处于恐惧状态,现在 依然处于恐惧状态 { //状态未变 mainobj->SetLife(orglife - power); //怪物的剩余血量 std::cout << "怪物处于恐惧状态中,处于逃跑之中!" << std::endl; //.....处理其他动作逻辑 } else { //不管下个状态是啥,总之不会是凶悍、不安、恐惧 状态了,只可能是 死亡状态 /*delete mainobj->getCurrentState(); mainobj->setCurrentState(new MonsterStatus_Dead);*/ mainobj->setCurrentState(MonsterStatus_Dead::getInstance()); mainobj->getCurrentState()->Attacked(power, mainobj); } } void MonsterStatus_Dead::Attacked(int power, Monster* mainobj) { int orglife = mainobj->GetLife(); if (orglife > 0) { //还要把怪物生命值减掉 mainobj->SetLife(orglife - power); //.... } cout << "怪物死亡!" << endl; }
myproject.cpp
#include <iostream> #include "Monster.h" #ifdef _DEBUG //只在Debug(调试)模式下 #ifndef DEBUG_NEW #define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符 #define new DEBUG_NEW #endif #endif //#include <boost/type_index.hpp> using namespace std; //#pragma warning(disable : 4996) namespace _nmsp1 { /* //怪物状态枚举值 enum MonsterState { MonS_Fer, //凶悍 MonS_Worr, //不安 MonS_Fear, //恐惧 MonS_Dead //死亡 }; //怪物类 class Monster { public: //构造函数,怪物的初始状态从 凶悍 开始 Monster(int life) :m_life(life), m_status(MonS_Fer) {} public: void Attacked(int power) //怪物被攻击,power表示主角对怪物的攻击力(怪物丢失的血量) { m_life -= power; //怪物剩余的血量 if (m_status == MonS_Fer) //凶悍 { if (m_life > 400) { cout << "怪物受到" << power << "点伤害并对主角进行疯狂的反击!" << endl; //处理其他动作逻辑 } else if (m_life > 100) { cout << "怪物受到" << power << "点伤害并对主角进行反击,怪物变得焦躁不安并开始呼唤支援!" << endl; m_status = MonS_Worr; //处理其他动作逻辑 } else if (m_life > 0) { cout << "怪物受到" << power << "点伤害,怪物变得恐惧并开始逃跑!" << endl; m_status = MonS_Fear; //处理其他动作逻辑 } else { cout << "怪物受到" << power << "点伤害,已经死亡!" << endl; m_status = MonS_Dead; //处理其他动作逻辑 } } else if (m_status == MonS_Worr) //不安 ,血量 <= 400,> 100 { if (m_life > 100) { cout << "怪物受到" << power << "点伤害并对主角进行反击,并继续急促的呼唤支援!" << endl; //处理其他动作逻辑 } else if (m_life > 0) { cout << "怪物受到" << power << "点伤害,怪物变得恐惧并开始逃跑!" << endl; m_status = MonS_Fear; //处理其他动作逻辑 } else { cout << "怪物受到" << power << "点伤害,已经死亡!" << endl; m_status = MonS_Dead; //处理其他动作逻辑 } } else if (m_status == MonS_Fear) //恐惧 { if (m_life > 0) { cout << "怪物受到" << power << "点伤害,怪物继续逃跑!" << endl; //处理其他动作逻辑 } else { cout << "怪物受到" << power << "点伤害,已经死亡!" << endl; m_status = MonS_Dead; //处理其他动作逻辑 } } else //怪物已经处于死亡状态 { cout << "怪物已死亡,不能再被攻击!" << endl; } } private: int m_life; //血量(生命) MonsterState m_status; //初始状态 }; */ } int main() { /* _nmsp1::Monster monster(500); cout << "怪物出生,当前处于凶悍状态,500点血!" << endl; monster.Attacked(20); monster.Attacked(100); monster.Attacked(200); monster.Attacked(170); monster.Attacked(100); monster.Attacked(100); */ Monster monster(500); cout << "怪物出生,当前处于凶悍状态,500点血!" << endl; monster.Attacked(20); monster.Attacked(100); monster.Attacked(200); monster.Attacked(170); monster.Attacked(100); monster.Attacked(100); return 0; }状态(State)模式:行为型,有限状态机 //状态模式的突出特点:用类来表示状态——策略模式(用类来表示策略) //(1)一个基本的状态转换范例 //有限状态机(Finite State Mache,所写:FSM),简称状态机。 //当某个事件(转移条件)发生时,会根据当前状态决定你执行哪种动作,然后进入下一种状态。 //约定:怪物生命 500。 //a) 怪物血量 > 400 ,怪物->凶悍,反击 //b) 怪物血量 <= 400, > 100,怪物->不安,反击并呼唤附近其他怪物支援 //c) 怪物血量 <= 100,怪物->恐惧,逃跑 //d) 怪物血量 <= 0,怪物->死亡,不能再被主角攻击 //状态类的存在价值:使业务逻辑代码更加清晰和易于维护。
//(2)引入状态(Status)模式 //定义:允许一个对象(怪物)在其内部状态改变(比如从凶悍状态改变为不安状态)时改变它的行为(比如从疯狂反击变为反击并互换支援), //对象看起来似乎修改了它的类。 //UML图中的三种角色 //a)Context(环境类):指Monster类。 //b)State(抽象状态类):指MonsterStatus子类。 //c)ConcreteState(具体状态类):指MonsterStatus_Feroc、MonsterStatus_Worr、MonsterStatus_Fear、MonsterStatus_Dead
//如下两种情况下,可以考虑使用状态模式: //a)对象行为取决于其状态,该对象需要根据其状态来改变行为。 //b)一个操作中含有庞大的条件分支语句,而这些分支语句的执行依赖于对象的当前状态。
//当项目中某对象的状态特别时,考虑 查表法——对象状态转换
//(3)状态类的单件实现方式如上 标签:状态,MonsterStatus,power,pState,c++,---,mainobj,怪物,设计模式 From: https://www.cnblogs.com/bwbfight/p/18241779