我有一个作品的基类

 class piece;

和一个包含派生对象的数组

piece* board[8][8];

通过虚拟功能的优势,简洁的设计。 缺点,如果我必须在板上找到一块或比较一块,我必须恢复到动态转换(或 typeid)。 这很丑陋,并且在发出数百万个请求时可能会影响性能。

另一方面,如果我制作一个单片类的数组,它有一个用于识别片的类型字段,我没有这个问题(它应该更快)但我必须制作超级丑陋的 switch 语句。 我想,由于件数是有限的,而且我认为自己不会制作那么多开关,这最终可能是一个更好的选择,你怎么看?

这是为了好玩(所以没有位板)。

阅读一些答案,我认为仅将类型字段用于运算符重载( == , != , ...)可以带来两个词的最佳效果。

boost::variant看起来也很有趣。

#1楼 票数:5

或者,如果您的课程集有限 - 即您知道数量,请使用变体和访问者。 例如boost::variant<king, queen, bishop, knight ...>而棋盘就是由这种类型的二维数组组成的。 现在要审问,你可以使用访问者...

#2楼 票数:3 已采纳

我会使用类层次结构。

为了找到一件作品,您可以为每种作品类型保留一个单独的列表。 所以你知道在哪里寻找每种类型的作品。

为了进行比较,您也可以依赖虚拟方法。

另一种方法是使用组件架构(如此处所述: http : //cowboyprogramming.com/2007/01/05/evolve-your-heirachy/ ),但我认为这对于您清楚知道的国际象棋游戏来说太过分了类型并知道这些类型不会很快改变:)。

#3楼 票数:1

我会使用层次结构,如果我想知道类型(为什么?)有一个识别类型的虚拟方法。

#4楼 票数:1

我从来没有写过国际象棋程序,但我猜最常见的操作是这样的:

  • 显示/打印板
  • 获得每件可能的动作集
  • 总结一块棋盘上所有棋子的值,也许总结出某种取决于棋子的“位置值”(车在空旷的线上,类似的东西)

此外,有些棋子有“状态”(一个国王只有在它之前没有移动过的情况下才能城堡,如果另一个棋子移动了两个格子,一个棋子可以通过攻击)只适用于一种棋子。

这一切都在向我尖叫阶级层次结构。 (假设您不需要位板性能)

另一方面,您不太可能需要添加新的工件类型,也不太可能在分离时重新使用其中一种工件类型。 即可扩展性和模块化并不是真正的问题。 因此,如果您发现算法中应该真正放在一个地方的某些重要部分分散在多个部分类中 - 使用 switch 语句。 只需添加一个抽象方法 tp 返回PieceType枚举的Piece类并打开它。

#5楼 票数:1

你不能同时担心性能和代码的乐趣:)

考虑使用“nibbleboard”(或至少是byteboard)而不是bitboard,其中每个nibble 代表一种类型。 每个半字节也是对该片类型进行操作的单例对象表中的索引。

class Empty : public Piece {};
class Rook : public Piece {};
...

const int wrook = 1;
...
const int bpawn = 12;

Piece* Operator[13] = {new Empty(), new Rook(), ..., new Pawn()};

byte table[64] = {
    wrook, wbishop, wknight, wking, wqueen, wknight, wbishop, wrook,
    wpawn, wpawn, wpawn, wpawn, wpawn, wpawn, wpawn, wpawn, 
    0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 
    bpawn, bpawn, bpawn, bpawn, bpawn, bpawn, bpawn, bpawn, 
    brook, bbishop, bknight, bking, bqueen, bknight, bbishop, brook};

// Given some position and some operation DoSomething we would have this:
Operator[table[position]]->DoSomething(table, position, <other parameters>);

// Possible return value of DoSomething might be new table

#6楼 票数:0

“超级丑陋的 switch 语句”是正确的技术 它不丑。 这叫做函数式编程。

继承是完全错误的技术。 每个部分都以不同的方式移动,具有不同的图形和其他属性。 没有什么共同点。 棋子不是抽象的。 它们是离散对象的具体集合。

您必须通过统一来使某些东西变得通用:创建所谓的 sum 类型。 在 Ocaml 中:

type shape = Pawn | Rook | Knight | Bishop | Queen | King
type color = Black | White
type piece = shape * color
type pos = { row:int;  col:int }

let check_white_move piece board from to = match piece with
| Pawn -> on_board to && (from.row = 2 && to.row = 4 or to.row = from.row + 1)
| ....

在 C++ 中没有正确的 sum 类型,您可以使用:

enum shape { pawn, rook, knight, bishop, queen, king};
..
bool check_white_move (..) { switch piece {
 case pawn: ...

它更笨拙。 向 C 和 C++ 委员会投诉。 但是使用正确的概念。 点心类(可识别联合,变体)来统一一组离散的具体类型方式。 类和继承用于表示抽象并提供其实现。

国际象棋没有什么抽象的。 这都是关于组合的。 这不是不同技术的优缺点的问题:而是关于使用正确的技术。

[顺便说一句:是的,您可以尝试 boost 变体,尽管我不能为这个应用程序推荐它,因为这些部分没有关联数据,枚举是完美的]

  ask by joey_89 translate from so

未解决问题?本站智能推荐:

3回复

类继承层次结构设计问题

我有以下图的类层次结构: 现在,在该类中,我还有许多其他函数,大部分是虚函数,因此当我在使用基类指针时调用适当的函数时。 例如,我有一个函数sssp(int node) ,它实现了单个源最短路径。 对于class matGraph和class listGraph class matGr
2回复

C++-有一种方法只能继承一些函数一次,而其他函数多次继承多次吗?

我的问题如下: 我正在用C ++创建一个国际象棋游戏,并且有一个基类Figure包含所有数字共享的功能,虚拟函数checkMove为每个图形单独重新定义(当然,每个图形在不同的规则下移动)。 国际象棋棋盘是指向Figure s的二维指针数组(空方块只是空指针)。 问题是,我希望Quee
1回复

节点层次结构和继承

我制作了一个场景图层次结构,其中每个节点都有一个父级,也可能有一个子级。 我创建了这个BaseNode类 我有一个从BaseNode继承的SceneNode类 现在,我的问题是关于所有包含BaseNode *参数的成员函数。 目前,当使用SceneNode对象时,我必须按照以下方式
1回复

C++类层次结构设计选择

在我的模拟中,我可以通过三种方式感知不同的对象:可以看到和/或听到和/或闻到对象。 例如,可以看到,听到和闻到动物。 可以看到并闻到一块肉在地上,但闻不到,只能看到墙。 然后,我有收集此信息的不同传感器EyeSensor , EarSensor , NoseSensor 。 之前状态:
5回复

继承层次结构与多重继承(C++)

好吧,我在考虑过去几天的设计决定,因为我仍然不能偏爱另一个,我想也许别人有个主意。 情况如下:我有几个不同的接口类抽象几个通信设备。 由于这些设备的性质不同,因此界面也不同,因此并不真正相关。 让我们称它们为IFooDevice和IBarDevice 。 随着时间的推移可能会添加更多设
1回复

动态广播是通过继承层次结构糟糕的做法吗?

我有以下数据结构: 数据结构用于产生非循环有向图。 C类充当包含代数任务的实际数据的“叶子”。 A和B保存其他信息,如姓名,类型,规则,我最喜欢的颜色和天气预报。 我想编写一个功能,弹出一个窗口,您可以浏览已有的结构。 在途中我想用一些漂亮的流程图显示用户使用的路径,可以点击它返回
2回复

可以在C++中隐藏继承层次结构的一部分吗?

考虑以下: B类从A类公开继承。 两者都在库中提供,我无法修改它们。 我想实现一个派生自B的类Foo ,但我希望允许Foo用户只使用A和Foo公共函数(不是来自B )。 对于他们来说, Foo从B继承是不相关的,这原则上是我无法避免的实现细节。 因此,原则上我希望Foo从A公开继
1回复

具有函数调用运算符和私有继承的类层次结构中的C++“使用”关键字

我偶然发现了一些我不太明白的东西。 我有一个使用私有继承的类层次结构,其中每个struct定义了不同的函数调用运算符。 奇怪的是,从最上面的函数调用操作struct是最获得的可用struct ,尽管一个事实using指令在第一推出仅用于struct 。 但是,正如预期的那样,在那里无法访问常规函数f