C++Cmd仿修仙项目:灵石包类(class StoneBag)Version01

2024 年 2 月 15 日 更新


0.设计思路

类视图 

  • 类内维护一个map对象,map 对象的每一个元素是,key为string ,value为stone*的pair;
  • add操作需要3个参数,level、attr、count,有些对象(stone类)包含以上多个参数,因此可以使用函数重载使添加stone方式更加多样;
  • sub操作需要2个参数,key 和 count,而 key 这个概念又是由 attr 和 level 共同组成,所以这 2 个参数可以充当 key 使用(定义一个转换函数就很方便啦);
  • add 与 sub 操作的具体思路是这样的,如果 map 内存在 key 值相同的 元素(相同的灵石),将元素value中 m_count 增加或减少;不存在 新建(createStone() 将其储存在 堆区),或提示 不存在灵石 无法 消耗;
  • 上量两个操作也就利用到了 hasKey(存在这种灵石)和 findKey(返回 对应灵石 在 map 中的迭代器)这2个函数了;
  • initStone 的作用是 清空 map 中,所有 m_count(数量)为零的灵石,防止没有意义的输出;
  • 而 stonebag 的 << 重载,则是输出 stonebag 中大致的 灵石状况,为了方便,编写了 返回灵石种类 和 返回灵石总数的函数;
  • showStones的实现很简单,利用循环依次输出,毕竟 "<<" 的重载已经在每一个灵石类上都实现了,很方便;
  • 最后,不要忘了 析构函数 释放所有 申请到的 内存空间,防止 内存泄漏。

1. 错误回顾

  • 使用派生手法的类,因为重用代码太多,复制粘贴后,忘记修改,导致逻辑错误;
  • 有些算法编写时,因为思绪不畅,导致逻辑错误;

写代码是个慢活,慢慢来吧


2. 目标瞻仰

  • 将Stone类封装为抽象类,使代码结构更加清晰(参数添加:string m_name);
  • 完善修仙者类,将 灵石包 置入进去,且(设计渡劫,战斗,生死斗等);
  • 实现价值类(class ItemValues),将灵石序列(目前想法是vector<Stone*>>)作为返回值,cout输出vPointers(衡量 物品价值 的一种 新的指标);
  • 实现物品类(class Item),(有价值的)物品Monster类,将作为子类继承它;
  • 实现角色类(class Character),子类有(作为动物的)Monster,修仙者等;
  • 思考 ItemMonster 与 ChaMonster 的相互转化

感觉项目越写越多~


3. VS Studying (经验汇总)

  • 使用宏定义,可以将一些冗杂的 枚举、类名 进行精简, 提高效率 ,增加可读性(typedef 也可以)
  • map erase方法,有时删除内容会访问错误,解决方案:
    deleteStone(it++); // 随用随 +, 不用在 for 中递加
  • 注意科学编码,劳逸结合,在状态不佳的情况下,编出的代码可能需要全部重写(CC CV 也许可以补救)

思路不对,写什么都没用~


4. 源码展示

StoneBag.h

#pragma once
#include <map>
#include "DeriveStone.h"
#include "AttributeStone.h"
#define _map map<string, SpriteStone*>
#define _it map<string, SpriteStone*>::iterator
using std::map;
using std::pair;
using std::make_pair;

class StoneBag{
public:
	// creates //
	~StoneBag();
	// values //
	int getKinds() const;
	int getAllNums() const;
	_Key getKey(_Level level,
		_Attr attr = _Attr::NONE);
	bool hasKey(_Key key);
	_it findKey(_Key key);
	// actions //
	void initStones();
	_pSto createStone(_Level level,
		int count = 1,
		_Attr attr = _Attr::NONE) const;
	void deleteStone(_it it);
	void addStone(_cSto_ s);
	void addStone( _Level level, 
		int count = 1, 
		_Attr attr = _Attr::NONE);
	void subStone(_Key key, 
		int count = 1);
	void subStone(_Level level, 
		int count = 1, 
		_Attr attr = _Attr::NONE);
	void showStones() const;
	// friends //
	friend ostream& operator<<(ostream& cout,
		const StoneBag& sbag);
protected:
	map<string, _pSto> m_stones;
};

ostream& operator<<(ostream& cout, 
	const StoneBag& sbag);

StoneBag.cpp

#include "StoneBag.h"

StoneBag::~StoneBag(){
	// cout << "销毁 灵石包" << endl;
	for (auto it = m_stones.begin();
		it != m_stones.end();)
		deleteStone(it++);
}

int StoneBag::getKinds() const{
	return (int) m_stones.size();
}

int StoneBag::getAllNums() const{
	int sum = 0;
	for (auto it = m_stones.begin(); 
		it != m_stones.end(); 
		it++)
		sum += it->second->count();
	return sum;
}

string StoneBag::getKey(_Level level
	, _Attr attr){
	return getStoneName(level, attr);
}

bool StoneBag::hasKey(_Key key){
		for (auto it = this->m_stones.begin();
			it != this->m_stones.end();
			it++)
			if (it->first == key)
				return true;
		return false;
}

_it StoneBag::findKey(_Key key){
		for (auto it = this->m_stones.begin();
			it != this->m_stones.end();
			it++)
			if (it->first == key)
				return it;
		return m_stones.end();
}

void StoneBag::initStones()
{
	for (auto it = m_stones.begin(); 
		it != m_stones.end();)
		if (it->second->count() == 0)
			deleteStone(it++);
		else it++;
}

_pSto StoneBag::createStone(_Level level,
	int count, _Attr attr) const{
	SpriteStone* pstone = nullptr;
	switch (level){
	case _Level::PRIMARY_LEVEL:
		pstone = new PrimaryStone(count);
		break;
	case _Level::MIDDLE_LEVEL:
		pstone = new MiddleStone(count);
		break;
	case _Level::ADVANCE_LEVEL:
		pstone = new AdvanceStone(count);
		break;
	case _Level::MONSTER_LEVLE:
		pstone = new MonsterStone(count);
		break;
	case _Level::ATTRIBUTE_LEVEL:
		pstone = new AttributeStone(count, attr);
		break;
	default:
		break;
		return nullptr;
	} return pstone;
}

void StoneBag::deleteStone(_it it){
	if (it->second != NULL){
		delete it->second;
		it->second = NULL;
	} m_stones.erase(it);
}

void StoneBag::addStone(_cSto_ s){
	_Level level = s.level();
	_Attr attr = s.attr();
	string key = getKey(level, attr);
	if (this->hasKey(key)){
		auto it = findKey(key);
		it->second->addCount(s.count());
		cout << "灵石包:"
			<< " 添加灵石 " << s.str()
			<< " 共计: "
			<<it->second->str()
			<< endl;
	} else {
		_pSto pstone = 
			createStone(level, s.count(), s.attr());
		m_stones.insert(make_pair(key, pstone));
		cout << "灵石包:"
			<<" 新增灵石 "
			<< (*pstone)
			<< endl;
	}
}

void StoneBag::addStone(_Level level,
	int count, _Attr attr){
	string key = getKey(level, attr);
	if (this->hasKey(key)){
		auto it = findKey(key);
		_Key stoneName = 
			getStoneName(level, attr) + " ";
		it->second->addCount(count);		
		cout << "灵石包:"
			<< " 添加灵石 " << stoneName 
			<< count << " 枚 "
			<< " 共计: "
			<< it->second->str()
			<< endl;
	} else {
		_pSto pstone = 
			createStone(level, count, attr);
		m_stones.insert(make_pair(key, pstone));
		cout << "灵石包:"
			<< " 新增灵石 "
			<< (*pstone)
			<< endl;
	}
}

void StoneBag::subStone(_Key key, int count){
	if (!hasKey(key))
		cout << "消耗灵石: 灵石包 内 没有指定灵石哦" 
		<< endl;
	else{
		auto it = findKey(key);
		int m_count = it->second->count();
		if (m_count < count){
			cout << "消耗灵石: 灵石包 内 没有足够灵石哦" 
				<< endl;
			return;
		} 
		it->second->addCount(-count);
		cout << "消耗灵石: "
			<< key + " " << -count << " 枚 "
			<< "剩余: " << *(it->second)
			<< endl;
	} initStones();
}

void StoneBag::subStone(_Level level, 
	int count, _Attr attr){
	_Key key = getKey(level, attr);
	subStone(key, count);
}

void StoneBag::showStones() const{
	cout << "------ 灵石包 ------" << endl;
	for (auto it = m_stones.begin();
		it != m_stones.end();
		it++){
		cout << " - ";
		cout << *(it->second) << endl;
	} cout << string(20, '-') << endl;
}

ostream& operator<<(ostream& cout,
	const StoneBag& sbag){
	int kinds = sbag.getKinds();
	int allNums = sbag.getAllNums();
	cout << kinds << " 种 灵石 共计: " 
		<< allNums << " 枚";
	// TODO: 在此处插入 return 语句
	return cout;
}

main.cpp

#include "StoneBag.h"
using namespace std;


void addStone(StoneBag& sbag, const SpriteStone& stone)
{
	_Key key = getStoneName(stone);
	cout << "------ 添加:" << key << " -----" << endl;
	sbag.addStone(stone);
	sbag.addStone(stone);
	sbag.addStone(stone);

	cout << "------ 消耗:" << key << " -----" << endl;	
	sbag.subStone(key);
	sbag.subStone(key, 999);
}

void testStoneBag()
{
	cout << "灵石包测试:" << endl;
	cout << string(48, '-') << endl;

	StoneBag sbag;
	AttributeStone mstone(10, StoneAttr::METAL);
	AttributeStone wstone(10, StoneAttr::WOOD);
	AttributeStone wastone(10, StoneAttr::WATER);
	AttributeStone fstone(10, StoneAttr::FIRE);
	AttributeStone estone(10, StoneAttr::EARTH);

	PrimaryStone	ps(10);
	MiddleStone		ms(102);
	AdvanceStone	as(933);
	MonsterStone	mos(32);

	addStone(sbag, mstone);
	addStone(sbag, wstone);
	addStone(sbag, wastone);
	addStone(sbag, fstone);
	addStone(sbag, estone);

	addStone(sbag, ps);
	addStone(sbag, ms);
	addStone(sbag, as);
	addStone(sbag, mos);

	sbag.addStone(SpriteStoneLevel::MIDDLE_LEVEL, 100);
	sbag.addStone(_Level::ATTRIBUTE_LEVEL, 100, _Attr::EARTH);

	sbag.subStone("中品灵石", 10);
	sbag.subStone("火灵石", 30);
	sbag.subStone(_Level::MIDDLE_LEVEL, 100);

	sbag.showStones();
	cout << sbag << endl;

	cout << endl;
}

int main(void)
{
	testStoneBag();
	system("pause");
	return 0;
}

5. 效果展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值