Dot Net Thoughts

December 22, 2007

Merry Christmas!

Filed under: csharp — dotnetthoughts @ 10:39 am
Tags: , ,

Merry Christmas everyone! I hope this holiday finds you happy and healthy with your loved ones! We’ve made the journey north to Washington to be with our families, and the kids are very excited for Christmas this year.

In celebration of Christmas, I thought that I would share with you a coded Christmas tree. I learned of this Christmas tree back in college when I was taking a math methods class, and first programmed it on my trusty TI-85 graphing calculator.

 To build this tree, we’re going to play a simple game. It has three rules:

  1. Define three points that represent the verticies of a traingle traingle.
  2. Starting from one of the verticies, move half the distance to a randomly chosen vertex point, and draw a new point.
  3. Starting at the new point, move half the distances to a randomly chosen vertex point and draw a new point.
  4. Repeat step 3 until you get bored.

Let’s implement the steps in order. We’ll simply use a windows form project and paint the results directly on the form itself.

Our first step is the definition of the verticies. We’ll declare three points forming our triangle as member variables on our form.

        Point _initialPoint1 = new Point(200, 0); 
        Point _initialPoint2 = new Point(0, 400); 
        Point _initialPoint3 = new Point(400, 400);

Next, we will need a method to draw our individual points on the form itself. My DrawPoint method accepts a point and a graphics object. Accepting the graphics object as a parameter prevents us from continually having to create and dispose the graphics object.

        private void DrawPoint(Point point, Graphics g) 
        { 
            Pen pen = new Pen(Color.Green); 
            g.DrawRectangle(pen, point.X, point.Y, 1, 1); 
        }

To implement steps two and three, we will need a method which, given a point, will calculate the half the distance to one of the original verticies and return a new point. You’ll notice we had to create a new member variable called _random. I initially was creating a new random method within the function, itself, but I was getting decidely unrandom results. When the Random object is created, it uses a seed value from the system time. My method was getting called faster than the time was changing, so I was seeing repeated “random” numbers. By moving the object creation outside of the method, the object is seeded only once, and the values turn out to be truly random.

        Random _random = new Random();             

        private Point GetNextPoint(Point startPoint) 
        { 
            Point pointToMoveTo = new Point(); 
            int randomValue = _random.Next(3); 
            int newX = 0; 
            int newY = 0;    
          
            if (randomValue == 0) pointToMoveTo = _initialPoint1; 
            else if (randomValue == 1) pointToMoveTo = _initialPoint2; 
            else if (randomValue == 2) pointToMoveTo = _initialPoint3;         
     
            newX = (startPoint.X + pointToMoveTo.X) / 2; 
            newY = (startPoint.Y + pointToMoveTo.Y) / 2;                   

            return new Point (newX, newY); 
        }

Finally, we just need a method to iterate over it several times. I’m running my 50000 times. As always, be sure you dispose any Graphics objects you create.

        private void ChristmasTree_Load(object sender, EventArgs e) 
        { 
            Point currentPoint;               

            this.Show();               

            using (Graphics g = this.CreateGraphics()) 
            { 
                currentPoint = _initialPoint1; 
                for (int i = 0; i < 50000; i++) 
                { 
                    currentPoint = GetNextPoint(currentPoint); 
                    DrawPoint(currentPoint, g); 
                } 
            }  
        }

 Excellent. Let’s build and run our Christmas tree progam and see what comes out.

ChristmasTree

Isn’t that neat? This code generates a well known fractal called a Sierpinski triangle. An entertaining (non-code) alternative to creating the traingle is to write out Pascal’s triangle, and shade in all of the odd numbers. Pretty neat stuff!

Merry Christmas, all! Code Safe!

MW

——————————Complete Code listing——————————————————-

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace ChristmasTree 
{ 
    public partial class frmChristmasTree : Form 
    { 
        public frmChristmasTree() 
        { 
            InitializeComponent(); 
        }          

        Point _initialPoint1 = new Point(200, 0); 
        Point _initialPoint2 = new Point(0, 400); 
        Point _initialPoint3 = new Point(400, 400); 
        Random _random = new Random();          

        private void ChristmasTree_Load(object sender, EventArgs e) 
        { 
            Point currentPoint;             
            this.Show();             
            using (Graphics g = this.CreateGraphics()) 
            { 
                currentPoint = _initialPoint1; 
                for (int i = 0; i < 50000; i++) 
                { 
                    currentPoint = GetNextPoint(currentPoint); 
                    DrawPoint(currentPoint, g); 
                } 
            }  
        }          

        private void DrawPoint(Point point, Graphics g) 
        { 
            Pen pen = new Pen(Color.Green); 
            g.DrawRectangle(pen, point.X, point.Y, 1, 1); 
        }          

        private Point GetNextPoint(Point startPoint) 
        { 
            Point pointToMoveTo = new Point(); 
            int randomValue = _random.Next(3); 
            int newX = 0; 
            int newY = 0;   
           
            if (randomValue == 0) pointToMoveTo = _initialPoint1; 
            else if (randomValue == 1) pointToMoveTo = _initialPoint2; 
            else if (randomValue == 2) pointToMoveTo = _initialPoint3;              

            newX = (startPoint.X + pointToMoveTo.X) / 2; 
            newY = (startPoint.Y + pointToMoveTo.Y) / 2;              

            return new Point (newX, newY); 
        } 
    } 
}
Advertisements

Create a free website or blog at WordPress.com.