开发者

Using LINQ to isolate a particular object from a list of objects

Using LINQ to isolate a particular object from a list of objects

(source: yfrog.com)

I am trying my hand at making an invaders clone. there are 30 aliens arranged in a 5x 6 matrix on screen. I need to give the bottom most alien the ability to fire a shot. I am using LINQ to group the aliens into 5 groups based on Location.X and then sort the groups descending.I then need to choose one of the groups ( that gives me 5 groups) and select the First alien in the group and use it;s coordinate to fire a shot.

My code below ,well ,works , but aliens in ANY row are merrily firing shots- not just the bottom most. Pl look at my code below and tell me whats wrong. (r = an instance of the Random class, all aliens are in a list called invaders).

 {
           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));

        }

EDIT:

Solved.Now it works as required after David B pushed me in the right direction.

Final code below. May definitely need some improv开发者_C百科ements in light of the large number of grouping/sorting going on. If anyone has something constructive to say on this I am all ears ( or eyes , in this case). Thanks to all who helped.

   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;

            }


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)];


You're ordering the groups but not ordering the invaders. It's possible that this will do it:

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();

(You may want to make the ordering descending, depending on whether Y is up or down.)

While this may work, I'm not sure that doing all this sorting all the time is ideal... can you not store the invaders in a data structure which helps you do this more easily?


You are grouping by Location.X, which I am going to guess is the column. You then order these groups by the column number - note that this orders the groups, not the items within the groups. Since you then pick a random group, the fact that you ordered them is irrelevant. Once you have picked a random group - a random column of the original aliens - you then pick the First of the group, but since the aliens are not ordered within the groups, you are getting an arbitrary alien.

To fix this, you'll need to make sure that the groups are ordered by height (Location.Y, I guess), so that when you select the First of the group you pick randomly, it is the bottommost alien. Change

select invgroup).ToList();

to

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

(assuming your Y axis goes in the right direction for this to give what you want!)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜