简单聚类算法2D。检测点数

时间:2012-10-04 21:37:19

标签: c# algorithm

任何人都知道在C#中实现一个简单的算法来检测2D游戏中的怪物群。

EX:   100范围内的焦炭有怪物。我想检测哪些怪物在彼此的范围2内,如果至少有5个怪物,则在该位置使用效果区域技能。否则使用单目标技能。

实现的链接很棒,C#最好。我只是迷路阅读维基百科的文章。

编辑: “你的问题是不完整的。你想要做什么?你想找到所有团体吗?最大的团体?任何团体,如果有团体,否则没有?请更具体。” -gilad hoch

我想找到主角周围100个单位范围内的所有群组。如果至少有5个或更多的怪物都在彼此的2个范围内,或者可能在距离中心怪物10个范围内,则应该形成这些组。

因此,结果可能是新的组列表或潜在目标位置列表。

2 个答案:

答案 0 :(得分:2)

一种非常简单的聚类算法是k均值算法。就像

  • 创建随机点
  • 将所有点分配到最近的点,并创建组
  • 将原始点重新定位到组的中间
  • 多次执行最后两步。

您可以在此处找到的实现,或者只是谷歌“kmean c#”

http://kunuk.wordpress.com/2011/09/20/markerclusterer-with-c-example-and-html-canvas-part-3/

答案 1 :(得分:1)

我最近实现了Efraty在this paper中给出的算法,它通过考虑以每个给定点为中心的半径2的圆的交点来解决问题。简单来说,如果您按顺时针顺序排列两个圆相交的点,那么您可以执行类似于线扫描的操作,以找出炸弹(或AoE咒语)需要启动以达到最大点的点敌人。实施是这样的:

#include <stdio.h>
#include <cmath>
#include <algorithm>

using namespace std;

#define INF 1e16
#define eps 1e-8
#define MAXN 210
#define RADIUS 2

struct point {
    double x,y;

    point() {}
    point(double xx, double yy) : x(xx), y(yy) {}

    point operator*(double ot) {
        return point(x*ot, y*ot);
    }

    point operator+(point ot) {
        return point(x+ot.x, y+ot.y);
    }

    point operator-(point ot) {
        return point(x-ot.x, y-ot.y);
    }

    point operator/(double ot) {
        return point(x/ot, y/ot);
    }
};

struct inter {
    double x,y;
    bool entry;
    double comp;

    bool operator< (inter ot) const {
        return comp < ot.comp;
    }
};

double dist(point a, point b) {
    double dx = a.x-b.x;
    double dy = a.y-b.y;
    return sqrt(dx*dx+dy*dy);
}

int N,K;
point p[MAXN];
inter it[2*MAXN];


struct distst {
    int id, dst;
    bool operator<(distst ot) const {return dst<ot.dst;}
};

distst dst[200][200];
point best_point;

double calc_depth(double r, int i) {
    int left_inter = 0;

    point left = p[i];
    left.y -= r;
    best_point = left;

    int tam = 0;

    for (int k = 0; k < N; k++) {
        int j = dst[i][k].id;
        if (i==j) continue;

        double d = dist(p[i], p[j]);

        if (d > 2*r + eps) break;
        if (fabs(d)<eps) {
            left_inter++;
            continue;
        }

        bool is_left = dist(p[j], left) < r+eps;
        if (is_left) {
            left_inter++;
        }

        double a = (d*d) / (2*d);

        point diff = p[j] - p[i];
        point p2 = p[i] + (diff * a) / d;

        double h = sqrt(r*r - a*a);

        it[tam].x = p2.x + h*( p[j].y - p[i].y ) / d;
        it[tam].y = p2.y - h*( p[j].x - p[i].x ) / d;  

        it[tam+1].x = p2.x - h*( p[j].y - p[i].y ) / d;
        it[tam+1].y = p2.y + h*( p[j].x - p[i].x ) / d; 

        it[tam].x -= p[i].x;
        it[tam].y -= p[i].y;
        it[tam+1].x -= p[i].x;
        it[tam+1].y -= p[i].y;

        it[tam].comp = atan2(it[tam].x, it[tam].y);
        it[tam+1].comp = atan2(it[tam+1].x, it[tam+1].y);

        if (it[tam] < it[tam+1]) {
            it[tam].entry = true;
            it[tam+1].entry = false;
        }
        else {
            it[tam].entry = false;
            it[tam+1].entry = true;
        }

        if (is_left) {
            swap(it[tam].entry, it[tam+1].entry);
        }

        tam+=2;
    }

    int curr,best;
    curr = best = left_inter;

    sort(it,it+tam);

    for (int j = 0; j < tam; j++) {
        if (it[j].entry) curr++;
        else curr--;

        if (curr > best) {
            best = curr;
            best_point = point(it[j].x, it[j].y);
        }
    }

    return best;
}

int main() {
    scanf("%d", &N);
    for (int i = 0; i < N; i++) {
        scanf("%lf %lf", &p[i].x, &p[i].y);
    }

    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            dst[i][j].id = j;
            dst[i][j].dst = dist(p[i],p[j]);
        }
        sort(dst[i],dst[i]+N);
    }

    int best = 0;
    point target = p[0];
    for (int i = 0; i < N; i++) {
        int depth = calc_depth(RADIUS, i);
        if (depth > best) {
            best = depth;
            target = best_point;
        }
    }

    printf("A bomb at (%lf, %lf) will hit %d target(s).\n", target.x, target.y, best+1);
}

样本用法:

2 (number of points) 
0 0
3 0
A bomb at (1.500000, 1.322876) will hit 2 targets.