如何基于关系矩阵实现逻辑

时间:2012-04-27 19:28:55

标签: c++ logic relationship

考虑到我有一个对称关系矩阵,类似于:

除了每个“结果”都是一小段代码。

我的场景:我有一堆Entity个对象“互相碰撞”。每个实体都有CollisionType值(枚举)。在设计中,存在关系矩阵,其描述了当不同的CollisionTypes彼此相遇时实体的行为。

我想知道:我如何以干净和高性能的方式表示关系,并在其上实现逻辑,这很容易添加新的CollisionTypes?在我看来,它看起来像2D Switch语句。

示例(差)解决方案:

void CollideEntities( Entity e1, Entity e2 ) {
    CollisionType t1 = e1.GetCollisionType();
    CollisionType t2 = e2.GetCollisionType();

    // perform basic logic based on t1 & t2
    if ( (t1 == COL_SOLID && t2 == COL_SQUISHY) || (t1 == COL_SQUISHY && t2 == COL_SOLID) ) {
        // do stuff..
    } else if ( (t1 == COL_SOLID && t2 == COL_DAMAGE) || (t1 == COL_DAMAGE && t2 == COL_SOLID) ) {
        // do other stuff..
    } // and so on...

}

很多潜在的解决方案对我来说都是显而易见的,但是没有一个能让我觉得特别干净或高效或者很容易添加新的类型...

2 个答案:

答案 0 :(得分:2)

我不这样做。我有一个Map,其中键将查找包含所需行为的Command对象。

另一种可能性是访客模式(又名“双重调度”)。

答案 1 :(得分:1)

试试这个:

#include <vector>
#include <iostream>

class Symmetric_matrix {
  private:
    size_t size1;
    // The next should be <bool> rather than <int>,
    // but the writer's compiler objects.
    std::vector<int> outcomes;
  public:
    size_t size() const { return size1; }
    int &operator()(const size_t i, const size_t j) {
        const size_t a = i <= j ? i : j;
        const size_t b = i <= j ? j : i;
        return outcomes[(b*(b-1))/2 + a];
    }
    Symmetric_matrix(const size_t size0)
      : size1(size0), outcomes((size()*(size()-1))/2, false) {}
};

// Here is a test driver.
int main() {
    Symmetric_matrix sm(5);
    sm(0, 1) = true;
    sm(0, 3) = true;
    sm(1, 3) = true;
    sm(2, 3) = true;
    sm(3, 4) = true;
    std::cout << "buyer-approver      : " << sm(0, 2) << "\n";
    std::cout << "approver-buyer      : " << sm(2, 0) << "\n";
    std::cout << "approver-requisition: " << sm(2, 3) << "\n";
    std::cout << "requisition-approver: " << sm(3, 2) << "\n";
    return 0;
}

你的问题很有意思。正如您所观察到的,只需存储矩阵的上三角或下三角,而不是两者。

但你问的问题是(b*(b-1))/2是什么?答案:它来自于奇怪的算术事实,0 + 1 + 2 + ... +(b-1)==(b *(b-1))/ 2(试一试)。

当然,我的示例代码可以有所改进。首先,出于某种原因(请求建议),我的代码在使用std::vector<bool>时失败,因此我使用std::vector<int>作为解决方法。另一方面,它不包括案例i == j的正确处理。然而,它所做的是传达必要的技术。您可以自行决定填写详细信息。

更新:后来发生了std::vector<bool>失败的原因。它失败了,因为std::vector<bool>是作为一个位数组实现的,而一个位不能是一个左值,因为它没有自己的地址。通过巧妙的编码,让operator()()返回一个特殊定义类型的操纵符,人们可以在不改变{{1}的情况下解决问题。但是,如果main()是我们想要使用的,那么定义和使用set()成员函数可能最简单。)