A Simulation Program-Windows Version

The Problem

In this program, we simulating a particle generator. These, strictly imaginary particles, have the property that if a particle is created at the same location where there is already a particle the universe (program) is destroyed (terminated).

We will use a random number generator to create the location for each particle, create the particle and then test to see if it has the same position as another particle. If it is located in the same spot the particle explodes terminating the program. If no other particle is located here, we put the particle on the screen.

We will use the image component to draw items in much the way we did for our in-class lab . In this case we will use it to create a blank screen at the beginning of the program. Our explosion will be generated by a call to a timer that will draw a circle. Each call to the timer draws a larger circle.

The Design

The design of this program is almost trivial. There is one item in the Simulate menu, namely run. Run will clear the list of particles, blank out the screen, then call on a function simulate to create the actual points on the screen and determine if there is an explosion. If there is an explosion, a variable _explosion is set to 1. When this variable is 1, the timer will draw an ever enlarging circle until the radius reaches 200. at that point the timer sets _explode to 0. The timer function is set to run at an interval of 100 (every 0.1 seconds) which means it will draw a circle whenever _explode is not zero.

The actual partical class which I called atom interates with the windows program to draw itself or explode depending on its location. Here is the class description for Atom:

class Atom
{
public:
    Atom (int x=0,int y =0);
    int x() {return _x;}
    int y() {return _y;} 
    int operator ==(const Atom &);// needed for the find function in the array.
private:
    int _x;
    int _y; 
};

The Coding

The function runSimulation is my handler for the menu Simulation's run choice. I used the math function random to create one number between 0 and 599 (random(600)) and a second number between 0 and 299 (random(300)). In order that the numbers be different each time the program is run you must call the function randomize some place in the program. I called randomize in the constructor for the main window. The handler for the Run1 entry in the menu clears the screen and then calls on simulate.

void __fastcall TSimulationSDIAppForm::Run1Click(TObject *Sender)
{
      _points.clearArray();
      TRect rect = Rect(0,0,800,600);
      Image1->Canvas->Brush->Color = clWhite;
      Image1->Canvas->FillRect(rect);
      simulate();
}
The function simulate draws a circle for each atom until a second atom is generated at the same point as one that has already been generated (find discovers this). Then _explode is set to 1, _radius is set to 10 (size of the first circle) and the procedure displays a message box. This halts the program, but the timer continues to interrupt and draw larger circles until the user hits the ok button on the message box and causes _explode to be set to 0 or the radius hits 200.
void __fastcall TSimulationSDIAppForm::simulate()
{
    while (1)
     {
        Atom bomb(random(900),random(500));
        _x = bomb.x();
        _y = bomb.y();
        if (_points.find(bomb)>=0)
        {
             _explode = 1;
             _radius = 10;
             Application->MessageBox("Your System has Exploded","Terminate...Terminate",MB_OK);
             _explode = 0;
             paint();
             return;
         }
        else
        {
            _points.insertItem(bomb);
            Image1->Canvas->Brush->Color = clBlue;
            _radius = 3;
            Image1->Canvas->Ellipse(_x-_radius,_y-_radius,_x+_radius,_y+_radius);
        }      
     }
}

The paint program called here is not the hander for WM_PAINT, it is just a repaint function you must call directly. It clears the screen and redraws each point with the point of explosion somewhat larger.

void __fastcall TSimulationSDIAppForm::paint()
{
   ArrayIterator next(_points);
   
   TRect rect = Rect(0,0,800,600);
   Image1->Canvas->Brush->Color = clWhite;
   Image1->Canvas->FillRect(rect);
   while (next)
   {
      int x = next().x();
      int y = next().y();
      if (x == _x && y == _y)
      {
         Image1->Canvas->Brush->Color = clRed;
         _radius = 6;
      }
      else
      {
         Image1->Canvas->Brush->Color = clBlue;
         _radius = 3;
      }
      Image1->Canvas->Ellipse(x-_radius,y-_radius,x+_radius,y+_radius);
      next++;
   }
}

The Timer

You can add a timer to any program by clicking on the time icon in the system component panel. Drop the timer anywhere on the form and the timer will activate its timer function according to the Interval you set in the Object Inspector. Once you have a timer, doubleclick in Event OnTimer entry in the Object Inspector.The code for the handler follows.

void __fastcall TSimulationSDIAppForm::Timer1Timer(TObject *Sender)
{
    if (_explode)
    {
        if ((_radius%4)==0)
            Image1->Canvas->Brush->Color = clRed;
        else if ((_radius%4)==2)
            Image1->Canvas->Brush->Color = clYellow;
        else if ((_radius%4)== 3)
            Image1->Canvas->Brush->Color = clBlue;
        else
            Image1->Canvas->Brush->Color = clGray;

        Image1->Canvas->Ellipse(_x-_radius,_y-_radius,_x+_radius,_y+_radius);
        _radius +=5;
        if (_radius > 200)
            _explode = 0;
    }
}
Click here to get a zipped version of this program.