代码之家  ›  专栏  ›  技术社区  ›  dezkev

使用LINQ从对象列表中隔离特定对象

  •  1
  • dezkev  · 技术社区  · 16 年前

    alt text http://img707.yfrog.com/img707/6250/newpicturer.jpg

    我正在努力克隆入侵者。屏幕上有30个外星人以5x6矩阵排列。我需要给最底层的外星人一个射击的能力。 我正在使用LINQ根据location.x将外星人分组为5个组,然后按降序对这些组进行排序。然后我需要选择其中一个组(这给了我5个组) 然后选择组中的第一个外星人并使用它的坐标来发射一次子弹。

    我下面的代码是有效的,但是任何一行的外星人都在愉快地开火——不仅仅是最底层的。我看看下面的代码,告诉我出了什么问题。 (R=随机类的一个实例,所有外星人都在一个名为入侵者的列表中)。

     {
               var query = (from inv in invaders
                             group inv by inv.Location.X
                             into invgroup
                             orderby invgroup.Key descending 
                             select invgroup).ToList();
    
                var invfirst = query[r.Next(query.Count)].First();
    
    
                    invaderShots.Add(new Shot(
                            new Point(invfirst.Area.X + invfirst.Area.Width / 2, invfirst.Area.Y + invfirst.Area.Height + 5),
                            displayrect, Shot.Direction.Down));
    
            }
    

    编辑:

    解决了。大卫B把我推向正确的方向后,它就按要求工作了。

    最终代码如下。 鉴于正在进行的大量分组/排序,可能确实需要一些改进。如果有人对此有建设性的意见,我会全神贯注(在这种情况下,是眼睛)。感谢所有帮助过的人。

       List<Invader> firstinvader = invaders.GroupBy(inv => inv.Location.X)
                    .Select(g => g.OrderByDescending(inv => inv.Location.Y)).ElementAt(r.Next(5)).ToList();
    
                firstinvader.Sort(comparerByLocation);
                Invader item = firstinvader[firstinvader.Count -1];
    
                if(invaderShots.Count < 2)
                {
                    invaderShots.Add(new Shot(
                         new Point(item.Area.X + item.Area.Width / 2, item.Area.Y + item.Area.Height / 2),
                         displayrect, Shot.Direction.Down));
    
                }
                else
                {
                    return;
    
                }
    
    3 回复  |  直到 14 年前
        1
  •  1
  •   Amy B    16 年前
    List<Invader> firstInvaders = invaders
      .GroupBy(inv => inv.Location.X)
      .Select(g => g
         .OrderByDescending(inv => inv.Location.Y)
         .First())
      .ToList();
    
    Invader shooter = firstInvaders[r.Next(firstInvaders.Count)];
    
        2
  •  1
  •   Jon Skeet    16 年前

    您正在订购 但不订购 入侵者 . 这有可能做到:

    var query = (from inv in invaders
                 group inv by inv.Location.X
                 into invgroup
                 orderby invgroup.Key descending 
                 select invgroup.OrderBy(inv => inv.Location.Y)).ToList();
    

    (根据Y是向上还是向下,您可能希望降序。)

    虽然这可能有效,但我不确定始终进行所有这些排序是理想的…你不能把入侵者存储在一个数据结构中,这样做更容易吗?

        3
  •  1
  •   AakashM    16 年前

    您的分组依据 Location.X ,我想是 . 然后按列号对这些组进行排序-请注意,这将对 ,而不是组中的项。既然你选择了一个随机的组,那么你命令它们的事实就无关紧要了。一旦你选择了一个随机组——原始外星人的随机列——你就可以选择 First 但由于外星人没有被命令 在内部 小组,你得到了一个任意的外星人。

    要解决此问题,您需要确保 按高度排序( Location.Y 我猜),所以当你选择 弗斯特 在你随机挑选的小组中,它是最底层的外星人。变化

    select invgroup).ToList();
    

    select invgroup.OrderBy(inv => inv.Location.Y)).ToList();
    

    (假设你 Y 轴朝着正确的方向移动,这样你就可以得到你想要的!