【发布时间】:2016-08-24 22:49:14
【问题描述】:
我有一个使用元组的坐标列表,因为我无权访问绘图库来使用“点”。
List<Tuple<int,int>> coords = new List<Tuple<int,int>>();
string[] movement = new string[temp.Count];
for(int i=1000; i<=8000; i=i+2300)
for(int j=1000; j<=15000; j=j+2000)
coords.Add(Tuple.Create(j,i));
coords.RemoveAll(x=> 3500>= getDist(0,0,x.Item1,x.Item2) );
coords.RemoveAll(x=> 3500>= getDist(16000,9000,x.Item1,x.Item2) );
我的列表中有玩家棋子,下面有两个例子。
List<int[]> player = new List<int[]>() {new int[]{0,726,1084,0,0,5},new int[]{2,1481,2208,0,0,-1} };
//piece numb, loc_X, loc_Y, teamID, state, value
必须计算基于回合的动作,并且当棋子的状态指示侦察时,我想为每个侦察棋子找到最小的坐标点集,而不是两个棋子进入同一组坐标。如果我尝试使用这样的 foreach 循环:
foreach(var myBust in temp) {
int minDist = coords.Select(x => getDist( x.Item1,x.Item2,myBust[1],myBust[2]) ).OrderBy(x => x).Distinct().First();
coords.RemoveAll(x => getDist(16000,9000,x.Item1,x.Item2) == minDist); }
然后我遇到了一个问题,即与另一个侦察片相比,配置的第一片可能不是最接近点集的,这就是为什么 foreach 循环不起作用或我。因此,我想要某种类型的 linq/lambda 语句,它可以将坐标列表中的所述“不同”最小坐标点返回给所有玩家片段(通过 getDist 和 Min)。
//Not sure why this doesn't give me what I am looking for
int minDist= coords.Zip(player, (x,y) => getDist(x.Item1,x.Item2,y[1],y[2])).Min();
我的 dist 方法。
static int getDist(int x1, int y1, int x2, int y2)
{ return Convert.ToInt32( Math.Sqrt(Math.Pow(x1-x2,2) + Math.Pow(y1-y2,2) );}
因此,对于答案,我正在寻找一种在两个列表上运行函数的方法,该函数运行一个函数(但不会将任何内容聚合在一起),并且可以从其中一个或两个列表中返回我想要的任何内容。
根据@Jacob 的回答,到目前为止,我得出了以下结论:
string[] movement = new string[player.Count];
List<int[]> temp = player;
while(temp.Any()){
HashSet<int> dists = new HashSet<int>();
foreach(var myBust in temp)
{ dists.UnionWith(coords.Select(x => getDist(x.Item1,x.Item2,myBust[1],myBust[2]) )); }
foreach(var myBust in player)
{ if(coords.Exists(x => getDist( x.Item1,x.Item2,myBust[1],myBust[2]) == dists.Min() ) )
{
Tuple<int,int> result = coords.FindAll(x => getDist( x.Item1,x.Item2,myBust[1],myBust[2]) == dists.Min() ).First();
movement[player.IndexOf(myBust)] = "Move " + result.Item1 + " " + result.Item2;
Console.WriteLine("Player Number "+myBust[0]+" going a dist of "+dists.Min()+" to coords "+result.Item1+","+result.Item2);
coords.Remove(result);
temp.Remove(myBust);
}
}
}
这给出了“玩家 2 号从 1871 到坐标 3000,3300 的距离”的正确输出。 这至少是第一次迭代,但随后抛出错误“集合已修改;枚举操作可能无法执行”。 任何建议或修改将不胜感激。
【问题讨论】:
-
你应该重新表述你的问题,因为它并不完全清楚:)
-
旁注:感觉
int[]应该是某种具有属性的类... -
您需要做的第一件事是停止使用数组来存储聚合数据。使用适当的属性声明一个用户定义的类型(即
class)以存储您想要的值(例如X和Y)。您需要做的第二件事是改进问题,以便我们能够理解您的意思。首先提供一个好的minimal reproducible example,它清楚地显示您正在尝试做什么,并准确解释该代码的作用以及您希望它做什么。 -
详细说明用户定义的类型:您可能(可能)会发现为
X和 @987654334 创建或使用内置的Point或类似类型是有意义的@,然后在您的Player类型中包含该类型,以及您想要的任何其他玩家数据。 -
不确定有什么不清楚的,但至于创建一个类来存储玩家信息是可能的,但即便如此,您也会在网格地图上拥有一个具有当前坐标的玩家列表。我正在尝试获取基于回合的运动坐标列表,如果没有坐标在玩家(或侦察员)之间重复。我有一个简单的解决方案,但我发现第一个 myBust 可以劫持另一个侦察员已经在运行的 minDist,当它的工作功能更改为侦察员时;即使后面的侦察兵离得更近。