views:

96

answers:

3

Hello All,

alt text

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 improvements 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;

            }
+1  A: 

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?

Jon Skeet
Sorry! tried your code but that does'nt work either. Shots are still being fired from many different rows instead of from the bottom most row as required.
dezkev
@dezkev: What's the difference between Location and Area in the invader class?
Jon Skeet
Location is a Point(X,Y) wher e the invader is drawn on screen and area is a property defined as below:public Rectangle Area { get{return new Rectangle(Location,Image.Size);} }
dezkev
+1  A: 

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!)

AakashM
Y axis is vertical. Maybe I need to order them after the random selection. How can i do that ?
dezkev
+1  A: 
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)];
David B
@David B: Tried this out too , does not work. What is happening is that aliens ( or invaders) in the first column ONLY are firing , but again arbitrarily- not the bottom most. So quite an improvement from my existing code , but still needs some tweaking.. will try my best.
dezkev
@David B: after further tweaking, it now works.See Edit in my original post for the final code.
dezkev
Must be your X and Y are switched up.
David B