1、制作csv文件,用excel制作另存为逗号分隔
Hero.csv
heroId | heroName | heroHp | heroAtk | heroDef | heroInfo |
1 | 亚瑟 | 500 | 10 | 30 | 血厚防高 |
2 | 后裔 | 300 | 30 | 15 | 功高血少 |
3 | 赵云 | 400 | 25 | 25 | 属性平衡 |
Monsters.csv
monsterId | monsterName | monsterAtk | monsterDef | monsterHp | |
1 | 史莱姆 | 5 | 10 | 50 | |
2 | 机枪兵 | 10 | 5 | 80 | |
3 | 石巨人 | 20 | 10 | 200 | |
4 | 地狱魔王 | 50 | 20 | 300 | |
5 | 黑龙 | 100 | 15 | 500 |
Weapons.csv
weapondId | weaponName | weaponAtk | weaponCritPlus | weaponCriteRate | weaponSuckPlus | weaponSuckRate | weaponFrozenRate |
1 | 小刀 | 5 | 0 | 0 | 0 | 0 | 0 |
2 | 大砍刀 | 10 | 2 | 30 | 0 | 0 | 0 |
3 | 屠龙刀 | 20 | 2 | 50 | 1 | 30 | 50 |
2、编程实现
2.1文件管理类实现 读取文件中信息
//FileManager.c
#include"FileManager.h"
void FileManager::loadCSVData(string filePath, map<string, map<string, string>>&m)
{
//读文件 ifstream
ifstream ifs(filePath);
if (!ifs.is_open())
{
cout<< filePath << "文件打开失败" << endl;
return;
}
string firstLine;
ifs >> firstLine;
//cout << firstLine << endl;
//将第一行数据解析到vector 容器
vector<string>v;
//将解析单行数据封装成一个函数
parseLinToVector(firstLine, v);
/*for (vector<string>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}*/
string data;//其他数据
while (ifs>>data)
{
//cout << data << endl;
vector<string>vOtherData;//其他数据 存放到 VOtherData容器中
parseLinToVector(data, vOtherData);
//准备出一个map小容器 为map大容器创建做铺垫 key值为第一行个英雄属性名称,value值为对应的各英雄属性
map<string, string>mSmall;
//拼接小容器中的数据
for (int i = 0; i < v.size(); i++)
{
mSmall.insert(make_pair(v[i], vOtherData[i]));
}
//将小容器放入到最大的容器中 key值为英雄编号
m.insert(make_pair(vOtherData[0], mSmall));
}
/*cout << "一号英雄姓名: " << m["1"]["heroName"]<<endl;
cout << "三号英雄Hp: " << m["3"]["heroHp"] << endl;*/
}
void FileManager::parseLinToVector(string line, vector<string>&v)
{
int pos = 0;
int start = 0;
while (true)
{
int pos = line.find(",", start);
if (pos == -1)
{
//最后一个单词截取
string tmp = line.substr(start, line.size() - start);
v.push_back(tmp);
break;
}
string tmp = line.substr(start, pos - start);
v.push_back(tmp);
start = pos + 1;
}
}
//FileManager.h
#pragma once
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<map>
using namespace std;
//文件的管理类
class FileManager
{
public:
ifstream ifs;
//解析单行数据
void parseLinToVector(string line, vector<string>&v);
//加载CSV文件格式的函数
void loadCSVData(string filePath,map<string,map<string,string>>&m);
};
2.2 武器类 采用虚基类 不同武器继承的方式
//wepon.h
#pragma once
#include<iostream>
using namespace std;
class Weapon
{
public:
//获取基础伤害
virtual int getBaseDamage() = 0;
//暴击效果 返回值大于0 触发暴击
virtual int getCrit() = 0;
//获取吸血 返回值大于0 触发吸血
virtual int getSuckBload() = 0;
//冰冻效果 返回true代表冰冻
virtual int getFrozen() = 0;
//触发概率
virtual bool isTrigger(int rate) = 0;
public:
int baseDamage; //基础攻击
string weaponName;//武器名称
int critPlus; //暴击系数
int critRate; //暴击率
int suckPlus; //吸血系数
int suckRate; //吸血率
int frozenRate; //冰冻率
};
//BroadSword.h 大砍刀类
#pragma once
#include"wepon.h"
using namespace std;
class BroadSword :public Weapon
{
public:
BroadSword();
//获取基础伤害
int getBaseDamage();
//暴击效果 返回值大于0 触发暴击
int getCrit();
//获取吸血 返回值大于0 触发吸血
int getSuckBload();
//冰冻效果 返回true代表冰冻
int getFrozen();
//触发概率
bool isTrigger(int rate);
};
//BroadSword.cpp 大砍刀类
#include"BroadSword.h"
#include"FileManager.h"
BroadSword::BroadSword()
{
FileManager fm;
map<string, map<string, string>>mWeponsFileData;
fm.loadCSVData("./Weapons.csv", mWeponsFileData);
string id = mWeponsFileData["2"]["weapondId"];
weaponName = mWeponsFileData[id]["weaponName"];
//string 转int
//string 转ctr atoi
baseDamage = atoi(mWeponsFileData[id]["weaponAtk"].c_str()); //基础攻击
critPlus = atoi(mWeponsFileData[id]["weaponCritPlus"].c_str()); //暴击系数
critRate = atoi(mWeponsFileData[id]["weaponCriteRate"].c_str()); //暴击率
suckPlus = atoi(mWeponsFileData[id]["weaponSuckPlus"].c_str()); //吸血系数
suckRate = atoi(mWeponsFileData[id]["weaponSuckRate"].c_str()); //吸血率
frozenRate = atoi(mWeponsFileData[id]["weaponFrozenRate"].c_str()); //冰冻率
}
//获取基础伤害
int BroadSword::getBaseDamage()
{
return baseDamage;
};
//暴击效果 返回值大于0 触发暴击
int BroadSword::getCrit()
{
if (isTrigger(critRate))
{
return critPlus * baseDamage;
}
else
{
return 0;
}
};
//获取吸血 返回值大于0 触发吸血
int BroadSword::getSuckBload()
{
if (isTrigger(suckRate))
{
return suckPlus * baseDamage;
}
else
{
return 0;
}
};
//冰冻效果 返回true代表冰冻
int BroadSword::getFrozen()
{
if (isTrigger(frozenRate))
{
return 1;
}
else
{
return 0;
}
};
//触发概率
bool BroadSword::isTrigger(int rate)
{
int num = rand() % 100 + 1;
if (num <rate)
{
return true;
}
else
{
return false;
}
};
//DragonSword.h 屠龙刀
#pragma once
#include"wepon.h"
class DragonSword:public Weapon
{
public:
DragonSword();
//获取基础伤害
int getBaseDamage();
//暴击效果 返回值大于0 触发暴击
int getCrit();
//获取吸血 返回值大于0 触发吸血
int getSuckBload();
//冰冻效果 返回true代表冰冻
int getFrozen();
//触发概率
bool isTrigger(int rate);
};
//DragonSword.cpp
#include"DragonSword.h"
#include"FileManager.h"
DragonSword::DragonSword()
{
FileManager fm;
string filePath = "./Weapons.csv";
map<string, map<string, string>>mWeponsFileData;
fm.loadCSVData(filePath, mWeponsFileData);
string id = mWeponsFileData["3"]["weapondId"];
weaponName = mWeponsFileData[id]["weaponName"];
baseDamage = atoi(mWeponsFileData[id]["weaponAtk"].c_str());
critPlus = atoi(mWeponsFileData[id]["weaponCritPlus"].c_str()); //暴击系数
critRate = atoi(mWeponsFileData[id]["weaponCriteRate"].c_str()); //暴击率
suckPlus = atoi(mWeponsFileData[id]["weaponSuckPlus"].c_str()); //吸血系数
suckRate = atoi(mWeponsFileData[id]["weaponSuckRate"].c_str()); //吸血率
frozenRate = atoi(mWeponsFileData[id]["weaponFrozenRate"].c_str()); //冰冻率
}
//获取基础伤害
int DragonSword::getBaseDamage()
{
return baseDamage;
};
//暴击效果 返回值大于0 触发暴击
int DragonSword::getCrit()
{
if (isTrigger(critRate))
{
return critPlus * baseDamage;
}
else
{
return 0;
}
};
//获取吸血 返回值大于0 触发吸血
int DragonSword::getSuckBload()
{
if (isTrigger(suckRate))
{
return suckPlus * baseDamage;
}
else
{
return 0;
}
};
//冰冻效果 返回true代表冰冻
int DragonSword::getFrozen()
{
if (isTrigger(frozenRate))
{
return 1;
}
else
{
return 0;
}
};
//触发概率
bool DragonSword::isTrigger(int rate)
{
int num = rand() % 100 + 1;
if (num < rate)
{
return true;
}
else
{
return false;
}
};
#pragma once
#include<iostream>
#include"wepon.h"
//Knife.h
using namespace std;
class Knife:public Weapon
{
public:
Knife();
//获取基础伤害
int getBaseDamage();
//暴击效果 返回值大于0 触发暴击
int getCrit();
//获取吸血 返回值大于0 触发吸血
int getSuckBload();
//冰冻效果 返回true代表冰冻
int getFrozen();
//触发概率
bool isTrigger(int rate);
};
2.3 英雄类
//Hero.h
#pragma once
#include"wepon.h"
class Monster;
class Hero
{
public:
Hero(int heroId);
void Attack(Monster *monster);
void EquipWeapon(Weapon *weapon);
public:
int heroHp;
int heroAtk;
int heroDef;
string heroName;
string haerInfo;
Weapon *pWeapon;
};
//Hero.cpp
#include"Hero.h"
#include"FileManager.h"
#include"Monster.h"
Hero::Hero(int heroId)
{
FileManager fm;
map<string, map<string, string>>mHeroFileData;
fm.loadCSVData("./Hero.csv", mHeroFileData);
//int 转 string
string tempId = std::to_string(heroId);
string id = mHeroFileData[tempId]["heroId"];
this->heroName=mHeroFileData[id]["heroName"];
this->haerInfo = mHeroFileData[id]["heroInfo"];
this->heroAtk=atoi(mHeroFileData[id]["heroAtk"].c_str());
this->heroDef = atoi(mHeroFileData[id]["heroDef"].c_str());
this->heroHp = atoi(mHeroFileData[id]["heroHp"].c_str());
this->pWeapon = NULL;
}
void Hero::Attack(Monster *monster)
{
int crit = 0;//暴击
int suck = 0;//吸血
int frozen = 0;//冰冻
int damage = 0;//英雄对怪物的伤害
if (this->pWeapon == NULL)
{
damage = this->heroAtk;//英雄没有装备武器 没有技能加成
}
else
{
//基础伤害(自身攻击力+武器攻击力)
damage = this->heroAtk + this->pWeapon->getBaseDamage();
//是否暴击
crit = this->pWeapon->getCrit();
//是否吸血
suck = this->pWeapon->getSuckBload();
//是否冰冻
frozen = this->pWeapon->getFrozen();
}
if (crit)//触发暴击
{
damage += crit;
cout << "英雄的武器触发暴击效果,怪物<" << monster->monsterName << ">受到暴击伤害" << endl;
}
if (suck)//触发吸血
{
damage += suck;
cout << "英雄的武器触发吸血效果,英雄<" <<this->heroName << ">增加血量:" << suck << endl;
}
if (frozen)//触发冰冻
{
damage += crit;
cout << "英雄的武器触发冰冻效果,怪物<" << monster->monsterName << ">停止攻击一回合" << endl;
}
//给怪物冰冻属性赋值
monster->isFrozen = frozen;
//计算对怪物真实伤害
int trueDamage = damage - monster->monsterDef > 0 ? damage - monster->monsterDef : 1;
//怪物受到攻击
monster->monsterHp -= trueDamage;
//英雄吸血
this->heroHp += suck;
cout << "英雄:" << this->heroName << "攻击了怪物:" << monster->monsterName << "造成的伤害为:" << trueDamage << endl;
}
void Hero::EquipWeapon(Weapon *weapon)
{
if (weapon == NULL)
{
return;
}
else
{
this->pWeapon = weapon;//维护用户选择的武器
cout << "英雄<" << heroName << ">装备了武器:" << weapon->weaponName << endl;
}
}
2.4 怪物类
//Monster.cpp
#include"Monster.h"
#include"FileManager.h"
#include"Hero.h"
Monster::Monster(int monsterId)
{
FileManager fm;
map<string, map<string, string>>mMonsterFileData;
fm.loadCSVData("./Monsters.csv", mMonsterFileData);
string tempId;
tempId = to_string(monsterId);
string id = mMonsterFileData[tempId]["monsterId"];
this->monsterName = mMonsterFileData[id]["monsterName"];//怪物姓名
this->monsterAtk= atoi(mMonsterFileData[id]["monsterAtk"].c_str());//怪物攻击力
this->monsterDef = atoi(mMonsterFileData[id]["monsterDef"].c_str());//怪物防御力
this->monsterHp = atoi(mMonsterFileData[id]["monsterHp"].c_str());//怪物血量
this->isFrozen = false;//是否被冰冻 默认未冰冻
}
void Monster::Attack(Hero*hero)
{
//判断 怪物 是否被冰冻 如果被冰冻 停止攻击一回合
if (this->isFrozen )
{
cout << "怪物: " << this->monsterName << "被冰冻,本回合无法攻击英雄!" << endl;
return;
}
//计算对英雄的伤害 判断英雄防御力
int damage = this->monsterAtk - hero->heroDef>0?this->monsterAtk-hero->heroDef:1;
//英雄掉血
hero->heroHp -= damage;
cout << "怪物" << this->monsterName << "攻击了英雄<" << hero->heroName
<<">,造成的伤害为:"<<damage<< endl;
}
//Monster.h
#pragma once
#include<string>
using namespace std;
class Hero;
class Monster
{
public:
string monsterName;
int monsterAtk;
int monsterDef;
int monsterHp;
bool isFrozen;
public:
Monster(int monsterId);
void Attack(Hero*hero);
};
3、 主函数 pk实现
//main.cpp
#include"FileManager.h"
#include<iostream>
#include<fstream>
#include"Knife.h "
#include"wepon.h"
#include"BroadSword.h"
#include"DragonSword.h"
#include"Hero.h"
#include"Monster.h"
#include<ctime>
void Fighting()
{
FileManager f1;
map<string, map<string, string>>mHeroFileData;
f1.loadCSVData("./Hero.csv", mHeroFileData);
cout << "欢迎来到力量大赛:" << endl;
cout << "请选择您的英雄: " << endl;
//数据拼接
char buf[1024];
sprintf(buf, "1、%s <%s>", mHeroFileData["1"]["heroName"].c_str(), mHeroFileData["1"]["heroInfo"].c_str());
cout << buf<<endl;
sprintf(buf, "2、%s <%s>", mHeroFileData["2"]["heroName"].c_str(), mHeroFileData["2"]["heroInfo"].c_str());
cout << buf<<endl;
sprintf(buf, "3、%s <%s>", mHeroFileData["3"]["heroName"].c_str(), mHeroFileData["3"]["heroInfo"].c_str());
cout << buf<<endl;
int select = 0;
cin >> select;
while (select<1|select>3)
{
cout << "请选择英雄(1-3)" << endl;
cin >> select;
};//1\n
getchar();//吸收换行符
//实例化英雄
Hero hero(select);
cout << "您选择的英雄是: " << hero.heroName << endl;
cout << "请选择您的武器: " << endl;
map<string, map<string, string>>mWeponsFileData;
f1.loadCSVData("./Weapons.csv", mWeponsFileData);
cout << "1、赤手空拳" << endl;
sprintf(buf, "2、%s", mWeponsFileData["1"]["weaponName"].c_str());
cout << buf << endl;
sprintf(buf, "3、%s", mWeponsFileData["2"]["weaponName"].c_str());
cout << buf << endl;
sprintf(buf, "4、%s", mWeponsFileData["3"]["weaponName"].c_str());
cout << buf << endl;
cin >> select;
while (select < 1 | select>4)
{
cout << "请选择英武器(1-4)" << endl;
cin >> select;
};//1\n
getchar();//吸收换行符
//创建武器
Weapon *weapon=NULL;
switch (select)
{
case 1:cout << "你未选择武器!" << endl;
break;
case 2: weapon = new Knife;
break;
case 3: weapon = new BroadSword;
break;
case 4: weapon = new DragonSword;
break;
default:
break;
}
//装备武器
hero.EquipWeapon(weapon);
//随机创建怪物
int id = rand() % 5 + 1;//1-5
Monster monster1(id);
int round = 1;//回合数
while (true)
{
getchar();
system("cls");//清屏
cout << "--------当前是第" << round << "回合--------" << endl;
//英雄攻击怪物
if (hero.heroHp <= 0)
{
cout << "英雄:" << hero.heroName << "已挂,游戏结束" << endl;
break;
}
hero.Attack(&monster1);
//怪物攻击英雄
if (monster1.monsterHp <= 0)
{
cout << "怪物:" << monster1.monsterName << "已挂,恭喜过关!" << endl;
break;
}
monster1.Attack(&hero);
cout << "英雄:" << hero.heroName << "剩余血量为: " << hero.heroHp << endl;
cout <<"怪物: "<< monster1.monsterName << "剩余血量为: " << monster1.monsterHp << endl;
//血量小于0时 退出 不进行下一个回合
if (hero.heroHp <= 0)
{
cout << "英雄:" << hero.heroName << "已挂,游戏结束" << endl;
break;
}
round++;
}
}
int main()
{
srand((unsigned int)time(NULL));
//FileManager f1;
//map<string, map<string, string>>mHeroFileData;
//f1.loadCSVData("./Hero.csv", mHeroFileData);
//map<string, map<string, string>>mMonsterFileData;
//f1.loadCSVData("./Monsters.csv", mMonsterFileData);
//map<string, map<string, string>>mWeponsFileData;
//f1.loadCSVData("./Weapons.csv", mWeponsFileData);
//cout << "一号英雄姓名: " << mHeroFileData["1"]["heroName"] << endl;
//cout << "三号英雄Hp: " << mHeroFileData["3"]["heroHp"] << endl;
//cout << "一号英雄名称: " << mMonsterFileData["1"]["monsterName"] << endl;
//cout << "三号英雄名称: " << mMonsterFileData["3"]["monsterName"] << endl;
//cout << "五号英雄名称: " << mMonsterFileData["5"]["monsterName"] << endl;
//cout << "一号武器名称: " << mWeponsFileData["1"]["weaponName"] << endl;
//cout << "二号武器冰冻率: " << mWeponsFileData["2"]["weaponFrozenRate"] << endl;
//cout << "三号武器吸血率: " << mWeponsFileData["3"]["weaponSuckRate"] << endl;
////小刀类测试
//Weapon *weapon = new Knife;
//cout << "武器名称:" << weapon->weaponName << endl;
//if (weapon->getCrit())
//{
// cout << "触发暴击" << endl;
//}
//else
//{
// cout << "未触发暴击" << endl;
//}
////大砍刀类测试
//delete weapon;
//weapon = new BroadSword;
//cout << "武器名称:" << weapon->weaponName << endl;
//if (weapon->getSuckBload())
//{
// cout << "触发吸血" << endl;
//}
//else
//{
// cout << "未触发吸血" << endl;
//}
//delete weapon;
//weapon = new DragonSword;
//cout << "武器名称:" << weapon->weaponName << endl;
//cout << "基础伤害:" << weapon->baseDamage<< endl;
Fighting();
system("pause");
}