PK案例

本文详细介绍了一款游戏PK系统的架构与实现过程,包括CSV文件数据管理、武器类的继承与多态、英雄与怪物类的交互设计,以及主函数中的战斗逻辑实现。通过具体的代码示例,展示了如何读取和解析CSV文件来获取游戏数据,如何设计武器类以实现不同的攻击效果,以及英雄和怪物之间的战斗机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、制作csv文件,用excel制作另存为逗号分隔

     Hero.csv

heroIdheroNameheroHpheroAtkheroDefheroInfo
1亚瑟5001030血厚防高
2后裔3003015功高血少
3赵云4002525属性平衡

Monsters.csv

monsterIdmonsterNamemonsterAtkmonsterDefmonsterHp 
1史莱姆51050 
2机枪兵10580 
3石巨人2010200 
4地狱魔王5020300 
5黑龙10015500 

Weapons.csv

weapondIdweaponNameweaponAtkweaponCritPlusweaponCriteRateweaponSuckPlusweaponSuckRateweaponFrozenRate
1小刀500000
2大砍刀10230000
3屠龙刀2025013050

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");
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值