《凡人修仙传》中打斗场景(c++多态实现)

在这里插入图片描述

  1. 我们 要实现打斗场景,第一,我们需要有打斗的双方,一个是英雄,一个是怪物,他们都有自己的属性,比如攻击,防御,血量。其次我们的英雄还会有武器。武器上有一些加成属性,可以帮英雄更好的打怪物,武器也有多种武器可以让英雄进行选择。

  2. 首先我们做武器类的声明,一个武器要有名称,还基础伤害,其次一些武器可能会有暴击,吸血,定身的效果,我们要对此进行判断。由于我们并不实现武器这个类,我们仅仅希望,后面的实现的武器继承他的属性并实现,所以我们武器类的属性都用纯虚函数来写。

    #pragma once
    #include<iostream> 
    #include<string>
    using namespace std;//抽象类
    class Weapon
    {
    public://获取基础伤害virtual int getBaseDamage() = 0;//获取吸血virtual int getSuckBlood() = 0;//获取是否定身virtual bool getHold()=0;//获取是否暴击virtual bool getCrit() = 0;string m_WeaponName; //武器名称int m_BaseDamage;//基础伤害};
    
  3. 我们有了武器类,就可以细化做武器了,我们这里就做两个武器,一个是普通的小刀,另外一个是比较厉害的屠龙刀,我们先做小刀类的声明。小刀是武器,所以它要继承武器类的属性,并拥有自己的构造函数。虚函数可以实现动态多态

     #pragma once#include<iostream>#include"Weapon.h"#include<string>using namespace std;class Knife :public Weapon{public:Knife();//获取基础伤害virtual int getBaseDamage() ;//获取吸血virtual int getSuckBlood() ;//获取是否定身virtual bool getHold();//获取是否暴击virtual bool getCrit();};
    
  4. 有了小刀类的声明后,我们可以在类外实现小刀这个类,小刀没有别的属性,所以,我们只用在构造中,把"小刀"这个名字和基础攻击力赋值,然后获取攻击力的函数中,返回基础攻击力就可以。

     #include"Knife.h"Knife::Knife(){this->m_BaseDamage = 10;this->m_WeaponName = "小刀";}int Knife::getBaseDamage(){return this->m_BaseDamage;}int Knife::getSuckBlood(){return 0;}bool Knife::getHold(){return false;}bool Knife::  getCrit(){return false;}
    
  5. 我们声明屠龙刀类,屠龙刀依旧是继承武器类,此外,作为一个强大的武器,它还必须具有其他的属性,它还有吸血,暴击,和可以让怪物定身的能力,但是它的这些能力,并不是一定会触发,需要一些属性也就是概率来触发。

     #pragma once  //防止头文件重复编译#include<iostream>#include"Weapon.h"#include<string>using namespace std;class DragonSword :public Weapon{public:DragonSword();//获取基础伤害virtual int getBaseDamage();//获取吸血virtual int getSuckBlood();//获取是否定身virtual bool getHold();//获取是否暴击virtual bool getCrit();//吸血率,暴击率,定身率int SuckRate;int holdRate;int critRate;//传入概率 判断是否触发bool isTrigger(int rate);};
    
  6. 屠龙刀的实现:再构造中,把它的基本属性赋值,其他的属性,我们通过一个成员函数来判断是否触发特效,我们在构造中把触发特效的概率写出来,然后在判断概率函数中,设置一个随机数,如果这个随机数比概率小,则触发特效。

     #include"DragonSword.h"DragonSword::DragonSword(){this->m_BaseDamage = 20;this->m_WeaponName = "屠龙宝刀";this->SuckRate = 20;this->holdRate = 30;this->critRate = 35;}int DragonSword::getBaseDamage(){return this->m_BaseDamage;}int DragonSword::getSuckBlood(){if (isTrigger(SuckRate)){return  this->m_BaseDamage*0.5;    //按照武器基础伤害一半吸血}return 0;}bool DragonSword::getHold(){if (isTrigger(holdRate)){return true;}return false;}bool DragonSword::getCrit(){if (isTrigger(critRate)){return true;}return false;}bool DragonSword::isTrigger(int rate){//通过isTrigger判断是否触发特效//随机一个0~100的数字//rand()%100 是0~99之间的随机数 +1后是1~100之间的一个随机数//如果产生的随机数比设定的概率值小则发生,否则不发生int num = rand() % 100 + 1;if (num < rate){return true;}return false;}
    
  7. 有了武器后,我们声明英雄类,英雄除了基本属性外,还要判断是否有武器,有什么样的武器

     #pragma once#include<iostream>#include"Weapon.h"#include<string>#include"Monster.h"using namespace std;class Monster;class Hero{public:Hero();string m_Name;//人名int m_Atk;//攻击力int m_Def;//防御力int m_Hp;//血量Weapon * weapon;//武器void EquipWeapon(Weapon * weapon);void Attack(Monster * monster);};
    
  8. 英雄类的实现。

     #include"Hero.h"Hero::Hero(){this->m_Hp = 500;this->m_Atk = 45;this->m_Def = 50;this->m_Name = "刘法师";this->weapon = NULL;}//装备武器void  Hero::EquipWeapon(Weapon * weapon){this->weapon = weapon;cout << "英雄:" << this->m_Name << "装备了武器" <<  this->weapon->m_WeaponName  << endl;}void  Hero::Attack(Monster * monster){int damage = 0;int addHp = 0;bool isHold = false;bool isCrit = false;if (this->weapon == NULL) //武器为空,没有加成{damage = this->m_Atk;}else{//基础伤害damage = this->m_Atk + this->weapon->m_BaseDamage;//计算吸血addHp = this->weapon->getSuckBlood();//计算定身isHold = this->weapon->getHold();//计算暴击isCrit = this->weapon->getCrit();if (isCrit) //暴击 伤害加成{damage = damage * 1.5;cout << "英雄的武器触发了暴击效果,怪物受到了高额伤害,伤害值:" << damage << endl;}if (isHold){cout << "英雄的武器触发了定身效果,怪物停止攻击一回合" << endl;}if (addHp){cout << "英雄的武器触发了吸血效果,英雄" << this->m_Name << "的血量增加了" << addHp << endl;}}//设置怪物定身monster->m_Hold = isHold;//计算真实伤害int trueDamage = (damage - monster->m_Def) > 0 ? damage - monster->m_Def : 1;monster->m_Hp -= trueDamage;this->m_Hp += addHp;cout << "英雄" << this->m_Name << "攻击了敌人" << monster->m_Name << "造成了伤害" << trueDamage << endl;}
    
  9. 接下来我们就要声明怪物类,怪物里除了基本属性外,还有一些特殊属性,比如是否被定身。

     #pragma once#include<iostream>#include"Weapon.h"#include<string>#include"Hero.h"using namespace std;class Hero;class Monster{public:Monster();string m_Name;int m_Hp;int m_Atk;int m_Def;bool m_Hold;void Attack(Hero * hero);}; 
    
  10. 怪物类的实现

    #include"Monster.h"Monster::Monster()
    {this->m_Hp = 300;this->m_Atk = 70;this->m_Def = 40;this->m_Hold = false;this->m_Name = "比克大魔王";
    }void  Monster::Attack(Hero* hero)
    {if (this->m_Hold){cout << "怪物" << this->m_Name << "被定身了,本回合无法攻击" << endl;return;}//计算攻击的伤害int damage = (this->m_Atk - hero->m_Def ) > 0 ? this->m_Atk - hero->m_Def : 1;hero->m_Hp -= damage;cout << "怪物" << this->m_Name << "攻击了英雄" << hero->m_Name << "造成了伤害" << damage << endl;
    }
    
  11. 最后就是一个打斗的实现了

    #include<iostream>
    #include"Hero.h"
    #include"Monster.h"
    #include"Weapon.h"
    #include"Knife.h"
    #include"DragonSword.h"
    using namespace std;void play()
    {//创建怪物Monster * monster = new Monster;//创建英雄Hero *hero = new Hero;//创建武器Weapon * kinfe = new Knife;Weapon * dragon =new DragonSword;//让用户选择武器cout << "请选择武器:" << endl;cout << "1. 赤手空拳" << endl;cout << "2. 小刀" << endl;cout << "3. 屠龙刀" << endl;int oper;cin >> oper;switch (oper){case 1:cout << "你真牛X,你还是太年轻了" << endl;break;case 2:hero->EquipWeapon(kinfe);break;case 3:hero->EquipWeapon(dragon);break;default:cout << "没有你要选择的武器" << endl;break;}getchar();//输入缓冲区里有个回车,多获取一次值int round = 1;while (true){getchar();system("cls");cout << "--当前第" << round << "回合开始-----" << endl;if (hero->m_Hp <= 0){cout << "英雄" << hero->m_Name << "已挂,游戏结束" << endl;break;}hero->Attack(monster);if (monster->m_Hp <= 0){cout << "怪物" << monster->m_Name << "已挂,顺利通关" << endl;break;}monster->Attack(hero);if (hero->m_Hp <= 0){cout << "英雄" << hero->m_Name << "已挂,游戏结束" << endl;break;}cout << "英雄" << hero->m_Name << "剩余血量" << hero->m_Hp << endl;cout << "怪物" << monster->m_Name << "剩余血量" << monster->m_Hp << endl;round++;}delete monster;delete hero;delete kinfe;delete dragon;}
    

运行结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383299.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++中的文件读写的操作

写文件 ofstreamopen指定打开方式isopen判断是否打开成功ifs<<“数据”ofs.close&#xff08;&#xff09; 读文件 ifstream ifs 指定打开方式ios::in isopen判断是否打开成功 读取有三种方式 #include<iostream>using namespace std;//文件读写头文件#incl…

c++的STL--1概念通述

STL的概念 什么是STL? STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且 是一个包罗数据结构与算法的软件框架。 STL从广义上分为&#xff1a;容器(container)&#xff0c;算法(algorit…

c++的vector容器

vector容器概念 vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而且它…

新一代数据库技术

新一代非关系型数据库有以下5个主要类型&#xff1a; 面向文件存储&#xff1a;适用于存储海量文件&#xff0c;代表产品MongoDb 列存储(wide column store/column-family)数据库&#xff1a;快速查找相关数据&#xff0c;相关数据被放在同一列中&#xff0c;代表产品Cassandra…

c++中stack容器

Stack 简介 stack 是堆栈容器&#xff0c;是一种“先进后出”的容器。stack 是简单地装饰 deque 容器而成为另外的一种容器。#include stack没有迭代器 Stack所有元素的进出都必须符合“先进后出”的条件&#xff0c;只有stack顶端的元素&#xff0c;才有机会被外界取用&am…

c++中的queue容器

queue容器 队列是一种容器适配器&#xff0c;专门用于在FIFO上下文(先进先出)中操作&#xff0c;其中从容器一端插入元素&#xff0c;另一端 提取元素。 队列作为容器适配器实现&#xff0c;容器适配器即将特定容器类封装作为其底层容器类&#xff0c;queue提供一组特定的 成员…

c++中list容器

list概念 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向 其前一个元素和后一个元素。list与for…

c++中容器(STL)的共性与使用的时机

容器的共通能力 C模板是容器的概念 理论提高&#xff1a;所有容器提供的都是值&#xff08;value&#xff09;语意&#xff0c;而非引用&#xff08;reference&#xff09;语意。容器执 行插入元素的操作时&#xff0c;内部实施拷贝动作。所以 STL 容器内存储的元素必须能够被…

Qt Creator 窗体控件自适应窗口大小布局

常见的软件窗口大小改变&#xff08;最大化、手动改变时&#xff09;需要窗口的部件能够自适应布局&#xff0c;而在Qt的应用程序界面设计中&#xff0c;对于像我一样的初学者如何实现窗口自适应调整还是要绕点弯路的。网上百度了很多&#xff0c;多数说的很含糊&#xff0c;还…

QT子线程与主线程的信号槽通信

最近用QT做一个服务器&#xff0c;众所周知&#xff0c;QT的主线程必须保持畅通&#xff0c;才能刷新UI。所以&#xff0c;网络通信端采用新开线程的方式。在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦。网上提供了很多同一线程不同类间采用信号槽通信的方式&#xff0c;…

c++中的函数适配器

函数适配器 函数适配器概念 STL中定义了大量的函数对象&#xff0c;但是有时候需要对函数返回值进行进一步的简单计算&#xff0c;或者填上多余的参数&#xff0c;不能直接代入算法&#xff0c;函数适配器实现了这一功能&#xff0c;将一种函数对象转化为另一种符合要求的函数…

c++中STL实现演讲比赛流程

演讲比赛流程 1&#xff09;某市举行一场演讲比赛&#xff0c;共有 24 个人参加&#xff0c;按参加顺序设置参赛号。比赛共三轮&#xff0c;前两 轮为淘汰赛&#xff0c;第三轮为决赛。 2&#xff09;比赛方式&#xff1a;分组比赛 第一轮分为 4 个小组&#xff0c;根据参赛号…

c++实现贪吃蛇

游戏中的实现元素 游戏中元素分为&#xff1a;墙壁&#xff0c;蛇&#xff0c;事物以及蛇的可行区域和右侧的版本号和游戏玩法提示 墙壁 *号表示&#xff0c;代表一个区域范围&#xff0c;也就是蛇的可移动区域&#xff0c;蛇如果碰到墙壁视为死亡&#xff0c; 蛇 分为蛇头&a…

Linux系统编程--1(进程和程序,CPU和MMU,PCB,进程状态)

进程相关概念 程序和进程 程序&#xff1a;是指编译好的二进制文件&#xff0c;在磁盘上&#xff0c;不占用系统资源(cpu、内存、打开的文件、设备、锁…) 进程&#xff1a;是一个抽象的概念&#xff0c;与操作系统原理联系紧密。进程是活跃的程序&#xff08;程序员角度&…

Linux系统编程--2(环境变量,进程控制)

环境变量 环境变量 是指在操作系统中用来指定操作系统运行环境的一些参数 每个人用电脑的习惯不一样&#xff0c;比如一般把文件放到磁盘&#xff0c;怎么管理文件&#xff0c;用什么编译器&#xff0c;所以&#xff0c;环境变量就是根据每个人使用操作系统的习惯来规定一些参…

套接字编程--1(UDP协议编程,端口号,传输层协议,网络字节序)

传输层的协议&#xff1a; ip地址&#xff1a; 在网络中唯一标识一台主机 IPV4&#xff1a;uint32_t DHCP NATIPV6 : uint8_t addr[16] —向前并不兼容IPV4 每一条数据都必须包含源地址和目的地址&#xff1a;因为每条网络中的数据都必须确定是从那个主机来到那个主机去 端…

Linux系统编程--3(exec 函数族,僵尸进程和孤儿进程,wait和wait_pid回收子进程)

exec 函数族 fork 创建子进程后执行的是和父进程相同的程序&#xff08;但有可能执行不同的代码分支&#xff09; &#xff0c;子进程往往要调用一种 exec 函数以执行另一个程序。当进程调用一种 exec 函数时&#xff0c;该进程的用户空间代码和数据完全被新程序替换&#xff…

交换机MAC地址学习和转发数据帧的原理

1 &#xff1a;交换机 MAC 地址学习在交换机初始化的&#xff0c;也就是刚启动的时候&#xff0c;交换机的MAC地址表是没有任何MAC地址和端口的映射条目的 当PCA要想和PCC&#xff0c;PCB,PCD进行通信时&#xff0c;当该二层数据帧通过端口E1/0/1发送到交换机上时&#xff0c…

Linux系统编程---4(进程间通信IPC,管道)

进程间通信目的 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程资源共享&#xff1a;多个进程之间共享同样的资源。通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它&#xff08;它们&#xff09;发生了某种事件&#xff08;如进…