首页 > 编程语言 >c/c++设计模式---状态模式

c/c++设计模式---状态模式

时间:2024-06-11 11:45:38浏览次数:15  
标签:状态 MonsterStatus power pState c++ --- mainobj 怪物 设计模式

一个基本的状态转换范例

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

相关文章

  • C++11 运算符的优先级分组和结合性
    本文汇总了C++11中的运算符的含义、优先级分组及其结合性。如果两个运算符用于同一个操作数,首先应用优先极高的。如果两个运算符优先级相同,按结合性规则决定应用那个运算符。同一组中的运算符优先级和结合性相同,无论先左后右(L-R),还是先右后左(R-L)。运算符含义优先级分组......
  • Zgo - maps
     packagemainimport("fmt""maps")funcdelete(kstring,vint)bool{returnv%2!=0}funcequal(v1int,v2float64)bool{returnfloat64(v1)==v2}funcmain(){m:=map[string]int{"one......
  • Zgo - slices
     packagemainimport("fmt""slices")funcmain(){s1:=[]int{1,2,-1,-2}s2:=slices.Clone(s1)fmt.Printf("%p\n",s1)fmt.Printf("%p\n",s2)s1[2]=0s1[3]=0s1......
  • 代理设计模式之JDK动态代理&CGLIB动态代理原理与源码剖析
    代理设计模式代理模式(Proxy),为其它对象提供一种代理以控制对这个对象的访问。如下图从上面的类图可以看出,通过代理模式,客户端访问接口时的实例实际上是Proxy对象,Proxy对象持有RealSubject的引用,这样一来Proxy在可以在实际执行RealSubject前后做一些操作,相当于是对RealSubject......
  • Vitis HLS 学习笔记--接口存储器布局模型
    目录1.简介2.详解2.1数据对齐2.2 数据结构填充3.总结1.简介软件开发者写的程序会在CPU处理器上运行,而硬件开发者设计的“内核”则会在FPGA上运行。这两部分需要通过一个精心设计的接口来沟通,就像两个人用对讲机来交流一样。为了确保这种沟通顺畅,数据必须以......
  • Vision-Language Models are Zero-Shot Reward Models for Reinforcement Learning
    发表时间:2024(ICLR2024)文章要点:文章提出用预训练的视觉语言模型作为zero-shot的rewardmodel(VLM-RMs)。好处在于可以通过自然语言来给定一个具体的任务,通过VLM-RMs让强化学习基于reward学习这个任务(usingpretrainedvision-languagemodels(VLMs)aszeroshotrewardmodels......
  • DreamJudge-1240-首字母大写
    1.题目介绍TimeLimit:1000msMemoryLimit:256mb对一个字符串中的所有单词,如果单词的首字母不是大写字母,则把单词的首字母变成大写字母。在字符串中,单词之间通过空白符分隔,空白符包括:空格('')、制表符('\t')、回车符('\r')、换行符('\n')。输入输出格式输入描述:输......
  • Linux-应用编程学习笔记(字符串处理)
    一、字符串输入/输出1、字符串输出//C库函数,向标准输出设备(屏幕、显示器)输出字符串并自行换行#include<stdio.h>intputs(constchar*s);s:需要进行输出的字符串。返回值:成功返回一个非负数;失败将返回EOF,EOF其实就是-1。//C库函数,既可以是标准输出、标准错误设备......
  • C++进阶教程
    一、引言C++是一种高效、强大且灵活的编程语言,广泛应用于系统软件开发、游戏开发、科学计算等领域。对于已经掌握C++基础知识的开发者来说,进阶学习C++将帮助他们更深入地理解这门语言,并提升编程能力。本教程将介绍C++中的一些高级特性和技术,包括面向对象编程、模板编程、ST......
  • Astra-sim 1.0_ns3编译问题
    目前github上的Astra-sim1.0_ns3的子模块地址出错了,修改.gitmodules,应为:[submodule"extern/googletest"]path=extern/googletesturl=https://github.com/google/googletest.git[submodule"extern/network_backend/analytical"]path=extern/network_backe......