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 by calling its show function.

One new problem here is how do we draw in a TWindow (or any window). All windows graphics is handled by the TDC class. As you see this class has a large number of drawing functions. It also uses the class TPoint. In this program we will draw points and circles using the TDC class.

The Design

Our program will be very simple. We use AppExpert to create a new windows program with main window a TWindow. Our simulation will run in response to a request for run from the simulation menu. This menu is modified using the resource editor. The class expert is used to create a handler for the run command.

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);
    void show(TDC *); // if the atom is not at the same location as another atom
    void explode(TDC *);// if the atom is at the same location as another atom
    int operator ==(const Atom &);// needed for the find function in the array.
private:
    TPoint where;
};

Notice that both the show and explode functions must draw on the screen, so the TDC object is passed as a parameter. If we create a scenario for show, you can see the need for a TDC object, and since this is a windows object it must be passed to show.

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 virtual function SetUpWindow which I created in ClassExpert where it is listed under the list Virtual Functions. It was also necessary to create a pointer to a TDC here and delete the pointer after its use. Each time through the loop the function calls the Windows function Invalidate. Invalidate is a windows command that causes the window and all its subwindows to be redrawn. The redraw is accomplished by the message WM_PAINT .

void SimulateWindow::runSimulation ()
{

	 // INSERT>> Your code here.
	TDC *DragDC = new TClientDC(*this);
	while (1)
	 {
		Atom bomb(random(800),random(550));
		crashSpot =points.find(bomb);
		if (crashSpot >=0)
		{
			bomb.explode(DragDC);
			points[crashSpot].mark();
			MessageBox("Your System has Exploded","Terminate...Terminate");
			Invalidate();
			delete DragDC;
			return;
		}
		else
		{
			points.insertItem(bomb);
			bomb.show(DragDC);
		}
	  	Invalidate();
	 }
}

The atom functions do the actual drawing. Each is passed a TDC pointer since these pointers are windows based.

Atom::Atom (int x,int y)
	:where(x,y){}
void Atom::show(TDC *dc)
{
	//dc->SetPixel(where,TColor::Black);
	dc->SetPixel(where,TColor::LtRed);
	TColor b;
	int size;
	if (_mark)
	{
		b = TColor::LtRed;
		size = 4;
	}
	else
	{
		b = TColor::LtGreen;
		size = 2;
	}
	TBrush brush(b);
	dc->SelectObject(brush);
	TPoint topLeft = where;
	topLeft.Offset(-size,-size);
	TPoint bottomRight = where;
	bottomRight.Offset(size,size);
	dc->Ellipse(topLeft,bottomRight);
}

void Atom::explode(TDC *dc)
{
	dc->SetPixel(where,TColor::LtRed);
	for (int k = 0;k<500;k+=10)
	for (int i = 0;i< 3+k;i+=31)
	{
		TColor bColor;
		if ((i%4)==0)
			bColor = TColor::LtRed;
		else if ((i%4)==2)
			bColor = TColor::LtYellow;
		else if ((i%4)== 3)
			bColor = TColor::White;
		else
      			bColor = TColor::LtGray;
		TBrush brush(bColor);
		dc->SelectObject(brush);
		TPoint topLeft = where;
		topLeft.Offset(-i,-i);
		TPoint bottomRight = where;
		bottomRight.Offset(i,i);
		dc->Ellipse(topLeft,bottomRight);
	}
}

int Atom::operator ==(const Atom &a)const
{
	return where==a.where;
}
Notice that the constructor for Atom has its TPoint where initialized in the initialization area of the constructor.

The WM_Paint message is handled by the EvPaint function. This is a standard OWL transformation. The event handler for WM_XXXXX is always named EvXXXXX.
To create a handler for this message look under Windows Messages, Basic Messages in the ClassExpert Event Pane.
Once the event handler exists we add the required process. In this case we want to traverse the array points and draw each point in the window.

void SimulateWindow::EvPaint ()
{
    TWindow::EvPaint();

    // INSERT>> Your code here.
    TDC *DragDC = new TClientDC(*this);
    ArrayIterator next(points);
    while(next)
    {
        next().show(DragDC);
        next++;
     }
     delete DragDC;
}

To clear the screen we need only use clearArray to empty the array and invalidate the window to remove the spots.

Complete Program

Click here to get a zipped version of this program.