Thread: List Graphics Rectangles Chess

  1. #1
    Registered User
    Join Date
    Oct 2010
    Posts
    4

    List Graphics Rectangles Chess

    I am trying to create a list of rectangles derived from a the Winform Client Rectangle. and then have them show on the screen in different colors. Much like a Chess board.

    The list should be easily created, but I am just stuck. I can write this out line by line, but I don't want to define each rectangle 64 times. Plus I could shorten the code substantially.

    This is what I have started, but I should be able to create an array/list of rectangles and create each one using a for loop.

    Code:
          private void DrawMyDocument(Graphics graphics, Rectangle rectangle)
            {
                   
                int xx = this.ClientRectangle.X;
                int yy = this.ClientRectangle.Y;
                int ww = this.ClientRectangle.Width / 8;
                int hh = this.ClientRectangle.Height/8;
    
                Rectangle One = new Rectangle(xx, yy, ww, hh);
                graphics.FillRectangle(Brushes.Red, One);
    
                Rectangle Two = new Rectangle(xx, yy + 32, ww, hh);
                graphics.FillRectangle(Brushes.Gray, Two);
    
                Rectangle Three = new Rectangle(xx, Two.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Red, Three);
    
                Rectangle Four = new Rectangle(xx, Three.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Gray, Four);
    
                Rectangle Five = new Rectangle(xx, Four.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Red, Five);
    
                Rectangle Six = new Rectangle(xx, Five.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Gray, Six);
    
                Rectangle Seven = new Rectangle(xx, Six.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Red, Seven);
    
                Rectangle Eight = new Rectangle(xx, Seven.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Gray, Eight);
    
                int xColumn2 = xx + 32;
    
                Rectangle OneOne = new Rectangle(xColumn2, yy, ww, hh);
                graphics.FillRectangle(Brushes.Gray, OneOne);
    
                Rectangle TwoTwo = new Rectangle(xColumn2, OneOne.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Red, TwoTwo);
    
                Rectangle ThreeThree = new Rectangle(xColumn2, Two.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Gray, ThreeThree);
    
                Rectangle FourFour = new Rectangle(xColumn2, Three.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Red, FourFour);
    
                Rectangle FiveFive = new Rectangle(xColumn2, Four.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Gray, FiveFive);
    
                Rectangle SixSix = new Rectangle(xColumn2, Five.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Red, SixSix);
    
                Rectangle SevenSeven = new Rectangle(xColumn2, Six.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Gray, SevenSeven);
    
                Rectangle EightEight = new Rectangle(xColumn2, Seven.Y + 32, ww, hh);
                graphics.FillRectangle(Brushes.Red, EightEight);
    This code will create the start of a chess board, but There has got to be an easier way to do this using a for loop and list of rectangles.

    This code generates two columns of rectangles of alternating colors. Just like a chess board, but needs to be drastically shortened.

  2. #2
    Registered User
    Join Date
    Mar 2009
    Location
    england
    Posts
    209
    The answer of course is loops!!

    Code:
    namespace painttest
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                this.DoubleBuffered = true;
            }
    
            private void Form1_Paint(object sender, PaintEventArgs e)
            {
                bool should_be_red = true;
    
                int width = (int)Math.Ceiling((double)this.ClientRectangle.Width / 8);
                int height = (int)Math.Ceiling((double)this.ClientRectangle.Height / 8);
    
                for (int a = 0; a < 8; a++) // a = vertical position
                {
                    for (int b = 0; b < 8; b++) // b = horizontal position
                    {
                        using (SolidBrush sb = new SolidBrush(should_be_red ? Color.Red : Color.Gray))
                            e.Graphics.FillRectangle(sb, new Rectangle(b * width, a * height, width, height));
    
                        if ((b + 1) % 8 != 0) // starting next line so stagger the color
                            should_be_red = !should_be_red;
                    }
                }
            }
    
            private void Form1_Resize(object sender, EventArgs e)
            {
                this.Invalidate();
            }
        }
    }
    2 loops to be precise. One to handle X position, the other for Y position. Pretty self explanatory however one point of interest was I had to add a condition as to whether to change the color bool, since the grid is 8 squares (even number) wide it meant that simply changing the color each time would not result in the checkered effect you were looking for.
    Last edited by theoobe; 04-08-2011 at 06:06 AM.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    41
    You can remove the boolean and just use the sum of the indexes. If it's odd one color, even the other. Also no need to create a rectangle object as FillRectangle is overloaded to accept coordinates. So the loops become:
    Code:
    for (int a = 0; a < 8; a++) {
        for (int b = 0; b < 8; b++) {
            using (SolidBrush sb = new SolidBrush((a+b) % 2 == 0 ? Color.Red : Color.Gray)) {
                e.Graphics.FillRectangle(sb, b*width, a*height, width, height);
            }
        }
    }
    Saves you a variable, a class construction and a weird check if you are on the next iteration of a by checking the inner loop.

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    If you are calling that function in a tight loop there is no way the GC is going to clean up that fast. It will clean up just before your system runs out of memory but I bet if you watch task manager you will see your app chewing through memory. If you are going to create that many small objects at runtime in a tight loop you might consider using weak references and/or value types.

  5. #5
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Building on what VirtualAce was saying, you're probably better off moving the brushes outside the loops:
    Code:
    Brush red = new SolidBrush(Color.Red);
    Brush gray = new SolidBrush(Color.Gray);
    Brush[] brushes = new Brush[] { red, gray };
    
    for (int a = 0; a < 8; a++) {
        for (int b = 0; b < 8; b++) {
            e.Graphics.FillRectangle(brushes[(a + b) % 2], b*width, a*height, width, height);
        }
    }
    
    red.Dispose();
    gray.Dispose();
    If you understand what you're doing, you're not learning anything.

  6. #6
    Registered User
    Join Date
    Mar 2011
    Posts
    41
    Quote Originally Posted by VirtualAce View Post
    If you are calling that function in a tight loop there is no way the GC is going to clean up that fast. It will clean up just before your system runs out of memory but I bet if you watch task manager you will see your app chewing through memory. If you are going to create that many small objects at runtime in a tight loop you might consider using weak references and/or value types.
    It's only 64 brushes. It won't eat up that much memory. But yes, I'd move them out of the loops anyway.
    Last edited by Momerath; 04-08-2011 at 10:33 PM.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I was referring to the rectangles or pretty much anything you new up repeatedly inside of a tight loop. The C# GC is extremely lazy by necessity. According to a blog by a developer who worked on the GC it should clean up gen 0, 1 and 2 objects at 256Kb, 1Mb?, and 2Mb. I'm not sure if the 1Mb value is correct for gen 1 objects. It also stated that the GC is free to alter these values based on the needs of your specific program. I've personally witnessed one of the apps I work on eat memory until the breaking point and then the GC runs and cleans it up.

    Here is some good information on the GC:
    http://www.csharphelp.com/2006/08/garbage-collection/

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. c program that accepts and executes commands?
    By Cimposter in forum C Programming
    Replies: 3
    Last Post: 09-30-2009, 02:58 PM
  2. instantiated from here: errors...
    By advocation in forum C++ Programming
    Replies: 5
    Last Post: 03-27-2005, 09:01 AM
  3. How can I traverse a huffman tree
    By carrja99 in forum C++ Programming
    Replies: 3
    Last Post: 04-28-2003, 05:46 PM
  4. List class
    By SilasP in forum C++ Programming
    Replies: 0
    Last Post: 02-10-2002, 05:20 PM
  5. singly linked list
    By clarinetster in forum C Programming
    Replies: 2
    Last Post: 08-26-2001, 10:21 PM