任何人都知道在C#中实现一个简单的算法来检测2D游戏中的怪物群。
EX: 100范围内的焦炭有怪物。我想检测哪些怪物在彼此的范围2内,如果至少有5个怪物,则在该位置使用效果区域技能。否则使用单目标技能。
实现的链接很棒,C#最好。我只是迷路阅读维基百科的文章。
编辑: “你的问题是不完整的。你想要做什么?你想找到所有团体吗?最大的团体?任何团体,如果有团体,否则没有?请更具体。” -gilad hoch
我想找到主角周围100个单位范围内的所有群组。如果至少有5个或更多的怪物都在彼此的2个范围内,或者可能在距离中心怪物10个范围内,则应该形成这些组。
因此,结果可能是新的组列表或潜在目标位置列表。
答案 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.