1

アイテムのベクトルを並べ替えようとしています。コードのコメントで述べたように、順序は次のようにする必要があります。

アクションポイント ( mAp) が多い参加者が先に進みます。同点の場合はmDisposition、バトルの開始者 ( ) と同じ性質 ( )の参加者がmBattleInitiator先に進みます。

次のコード (簡略化された例) は、おそらく私の並べ替えの実装が正しくないために、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として実装する」と言っているだけですが、私の場合はうまくいきません。関連しているように見えるが、私には役に立たないものがいくつかあります。

私が求めているものを達成する最も簡単な方法は何ですか?

4

2 に答える 2

2

私はあなたのコードのコメントから離れて、何が問題なのか (もしあれば)、そしてそれをどのように修正するのかを説明します。

// 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.

両方の参加者が開始者と同じ性質を持っている場合はどうなりますか? 2 つの要素がこの条件を満たさないことを保証できたとしても、ソート アルゴリズムは要素をそれ自体と比較することができます。その場合、このテストは返さtrueれ、strict-weak 順序付けの条件の 1 つに違反します。つまり、要素はそれ自体と等しい (つまり、compare(a,a)常に false でなければならない) 必要があります。

aおそらく代わりに、イニシエーターと同じ性質を持っていて、そうでbない場合は、aよりも小さいと見なされるべきであると言いたいでしょうb。これは次のようにエンコードできます。

return dispositionOfA == mBattleInitiator && dispsitionOfB != mBattleInitiator;

したがって、完全なテストは次のようになります。

if (a.mAp > b.mAp)
    return true;
if (a.mAp < b.mAp)
    return false;

return a.mAiComponent->mDisposition == mBattleInitiator &&
       b.mAiComponent->mDisposition != mBattleInitiator;
于 2018-02-25T10:23:32.873 に答える