【发布时间】:2018-08-04 22:40:14
【问题描述】:
我正在尝试对项目向量进行排序。如代码cmets中所述,排序应为:
行动点数较多的参与者 (mAp) 先行。当出现平局时,与战斗发起者(mBattleInitiator)具有相同性格(mDisposition)的参与者先行。
以下代码(简化示例)在 macOS 上崩溃,可能是由于我的排序实现不正确:
#include <QtCore>
class AiComponent
{
public:
enum Disposition {
Friendly,
Hostile
};
AiComponent(Disposition disposition) : mDisposition(disposition) {}
~AiComponent() { qDebug() << "Destroying AiComponent"; }
Disposition mDisposition;
};
class BattleManager
{
public:
BattleManager() : mBattleInitiator(AiComponent::Hostile) {}
class Turn {
public:
Turn() : mAp(1) {}
Turn(QSharedPointer<AiComponent> aiComponent) :
mAiComponent(aiComponent),
mAp(1)
{
}
Turn(const Turn &rhs) :
mAiComponent(rhs.mAiComponent),
mAp(1)
{
}
QSharedPointer<AiComponent> mAiComponent;
int mAp;
};
void addToTurnQueue(QSet<QSharedPointer<AiComponent>> aiComponents);
AiComponent::Disposition mBattleInitiator;
QVector<Turn> mTurnQueue;
Turn mActive;
};
void BattleManager::addToTurnQueue(QSet<QSharedPointer<AiComponent> > aiComponents)
{
foreach (auto aiComponent, aiComponents) {
mTurnQueue.append(Turn(aiComponent));
}
// Sort the participants so that ones with more action points (mAp) go first.
// When there is a tie, participants with the same disposition (mDisposition)
// as the initiator of the battle (mBattleInitiator) go first.
std::sort(mTurnQueue.begin(), mTurnQueue.end(), [=](const Turn &a, const Turn &b) {
if (a.mAp > b.mAp)
return true;
if (a.mAp < b.mAp)
return false;
// At this point, a.mAp is equal to b.mAp, so we must resolve the tie
// based on mDisposition.
if (a.mAiComponent->mDisposition == mBattleInitiator)
return true;
if (b.mAiComponent->mDisposition == mBattleInitiator)
return false;
return false;
});
}
int main(int /*argc*/, char */*argv*/[])
{
BattleManager battleManager;
for (int i = 0; i < 20; ++i) {
qDebug() << "iteration" << i;
QSet<QSharedPointer<AiComponent>> participants;
AiComponent::Disposition disposition = i % 2 == 0 ? AiComponent::Hostile : AiComponent::Friendly;
QSharedPointer<AiComponent> ai(new AiComponent(disposition));
participants.insert(ai);
battleManager.addToTurnQueue(participants);
}
// This should print (1 1), (1 1), ... (1 0), (1 0)
foreach (auto turn, battleManager.mTurnQueue) {
qDebug() << "(" << turn.mAp << turn.mAiComponent->mDisposition << ")";
}
return 0;
}
我已经查看了有关该主题的其他答案。他们中的大多数人只是说“将其实现为 a > b”,这在我的情况下不起作用。有一些看起来相关但对我没有帮助:
- https://stackoverflow.com/a/16824720/904422 - 表示可以使用其他标准算法,但没有提及任何具体示例
- https://stackoverflow.com/a/33508373/904422 - 令人困惑,似乎有点矫枉过正
实现我所追求的最简单的方法是什么?
【问题讨论】:
-
你需要实现严格的弱排序。没有办法解决这个问题。如何做到这一点取决于您。
-
据我了解,严格的弱排序意味着我无法解决关系。如果我的理解是正确的,那么这对我来说不是一个选择。如果我的理解不正确,请提供一个说明这一点的答案,以及一个解决平局的简单代码示例。
-
如果 tie 解析器也遵循严格的弱排序,您可以解析 tie。参见例如对字典排序做了什么(例如按字母顺序排序字符串)
-
您需要对 2 元组执行严格的弱排序。见stackoverflow.com/q/979759/72178。
-
正确解决关系意味着他们必须自己实施严格的弱排序。如果你有特殊元素应该放在非特殊元素之前,那么
if (element a is special and element b is not special) return true; else return false;
标签: c++ sorting strict-weak-ordering