具有大量纸牌和复杂动作的纸牌游戏
Card game with huge amount of cards and complex actions
我正在尝试编写一些未来派的纸牌游戏模拟器。游戏本身有复杂的规则和很多卡牌(~1000 总共)。卡牌的类型很少(<10,类型如法术,治疗,移动,攻击,防御等)。每张卡都属于一种类型,但它们所做的动作可以是多种多样的,例如:卡1属于治疗类型,其作用是治疗1点生命值,卡2也属于治疗类型,但它的动作是治疗,例如掉落另一张牌。
另一件事是,这张卡可以做一些基于条件的长操作链的硬复杂动作(可选或强制),例如:抽一张牌,如果它是X色的,则握住它,如果它没有掉落它并吸收Y法力值,如果你愿意,也是一种祝福
问题是如何设计类的结构来制作卡片类型并为游戏中的每一张卡片定义动作,并将它们全部存储在某个数组中以供以后在游戏中使用?
我唯一想到的是某种类型的继承,例如:
class CardBase
{
public:
virtual bool use(int action) = 0; // Every card should implement this
private:
std::string _name;
// type ?
}
// Split into types maybe ?
class CardOne: public CardBase
{
bool use(int action) { /*do whatever card should do on given action ID ex. heal*/ }
}
class CardTwo: public CardBase
...
// 1000 cards later... is this still a good idea... ?
后来存储和使用如下:
std::vector<CardBase*> cards; // build card deck
if (cards.at(0)->use())
std::cout << "Card used !";
else
std::cout << "You cannot do that !";
我也有马斯开关的情况,但光是想想就恶心......
如果您在卡中创建一个嵌套接口,则可以使用从该接口派生的完全不同的行为类填充它。
编写一个算法来添加类型的卡片,当这些卡片缺少您需要的百分比时。这样,如果您有 52 张或 123456789.0f
张卡就无关紧要了
在 IType 十进器中添加一个静态 int,以便在每次添加卡时添加 1。当您处理大量卡片时,这将节省大量处理时间。
您可以考虑更改:
virtual bool CSpell::use( int action )
自
virtual bool CSpell::use( void* action )
这样,您就可以传入所有新内容,特别是每种类型所需的内容。不仅可以传递整数,还可以传递整个结构和类。
例如:
class IType { public: virtual bool use( int action ) = 0; };
class ISpell : public IType { }; class CSpell : public ISpell { public: bool use( int action ){ return false; } };
class IAbillity {};
class CAbillity : public IAbillity { };
class CSpecialAbillity : public IAbillity { };
class CCard
{
public:
enum{ Spell, Trap, Monster, Wizard };
CCard( std::string name, IType* type, bool gc = false ) : _name( name ), _type( type ) { }
~CCard(){ if( _type /* && _gc_responsible */ ) delete _type; }
virtual bool use( int action ){ return _type ? _type->use( action ) : false; }
private:
std::string _name;
// Whatever type you have: call use()
IType* _type = 0;
// An abillity espacially for a monster, or a wizard, can be set here
IAbillity* _abillity = 0;
};
class CDeck : std::vector<CCard*>
{
public:
int load( std::string filename ){}
int save( std::string filename ){}
int addCards( int amount )
{
// Make your algorithm
// Run it each time you want to add cards
// loop
// Check how many cards you have from each type
// the one that lacks the most (percentage wise), add it
}
private:
};
int main()
{
CDeck deck;
deck.addCards( 10 );
// play, eat, sleep, invite people
deck.addCards( 10 );
// play, eat, sleep, invite people
deck.addCards( 20 );
// cool, aparty, invite people
deck.addCards( 1000 );
}
相似的卡牌(例如治疗卡)可以由同一类表示。然后,您可以使用特定值创建实例。
class HealerCard: public CardBase
{
int amount;
HealerCard(int amount) {this->amount = amount;}
bool use(int action) { /*heal by this->amount*/ }
}
使用上述类,您可以创建不同的治疗卡实例:
//... Let's create 10 of each amount of healer cards from 1 to 10
int amount, i, cnt = 0;
for (amount=1; amount <= 10; amount++) {
cards[cnt++] = new HealerCard(amount);
}
注意:语法可能有点不对劲,我的c ++有点生疏:)
你不能硬编码任何东西,并使用lua这样的东西动态执行你的卡片操作(从来没有用过它,只是听说过它)。这有几个优点:
- 您无需重新编译即可更改卡
- 不太可能出现错误
- 您可以非常轻松地制作新卡
- 您可以从文件中加载不同的卡组
- 用户可以轻松制作自己的卡片
也有一些缺点:
- 这更难
- 会慢一点
你可以像你说的那样设计类:一个baseCard类,然后是10个左右的类来扩展它,代表你的多种类型。然后,您可以拥有一个 csv* 文件,其中包含有关 1000 张不同卡片中每张卡的信息,格式如下:[类型] 、[值]、[实例数]、[其他属性]。然后,您可以读取文本文件,并通过对文件进行一些基本解析,使用给定的信息初始化必要类的各种实例。这样,您可以将类的设计与实例分开。实际上,您可以创建一个执行所有这些初始化的 deck 类,然后在程序中使用一个 deck 类的单个实例。
Healer , 1 , 10, ? ,
Healer , 3 , 5 , ? ,
Healer , 5 , 2 , ? ,
Healer , 10 , 1 , ? ,
Spell , 1 , 20, ? ,
Spell , 3 , 10 , ? ,
Defense , 1 , 7, ? ,
Defense , 3 , 4, ? ,
...
*csv 代表逗号分隔值,是一个基本文本文件,其值以逗号分隔。
- 函数复杂度分析
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- while循环中while循环的时间复杂度是多少
- 在C++游戏中与库存系统作斗争
- 换位表导致测试失败(但在游戏中运行良好)
- Craps游戏问题,忽略if语句
- 矢量下标超出SFML游戏中的范围
- 我可以创建一个包含两个变量的 for 循环,但时间复杂度仍然为 O(n) 吗?
- 函数的时间复杂度是多少?
- 如何在纸牌游戏中实现花色?
- 在纸牌游戏中检测到C++的堆栈粉碎
- C ++ txt 文件成数组逐行字符串和 int 用于纸牌游戏
- 在此过程中的纸牌游戏程序.不知道为什么我会得到一个随机数-858993460
- 在纸牌游戏中回合
- 我需要哪种语言/课程来制作简单的纸牌游戏
- 具有大量纸牌和复杂动作的纸牌游戏
- TCP vs Enet 与大厅的在线纸牌游戏
- c++纸牌游戏,当新一轮牌组创建/新一轮开始时,手牌被发不止一次
- 我偷了纸牌游戏 c++ 标头代码,它无法编译...呜
- 为纸牌游戏正确地播种RNG