3
\$\begingroup\$

This is my first attempt to draw using FLTK libraries *:

// Objective: Draw an 8-by-8, red and white checkers board  

#include "std_lib_facilities.h"
#include <iostream>
#include "Simple_window.h"

int main(){
try{
    // create a window in the center of the screen wiht size: 600x600
    int wWidth = 660;
    int wHeight = 660;
    Point centerScreen(x_max()/2 - wWidth/2, y_max()/2 - wHeight/2);
    Simple_window sw(centerScreen, 660, 660, "Chapter 12 Exercise 3");

    // starting upper left coordinates of the window + 10 pixels frame
    int tlx = sw.x_max() - 650;
    int tly = sw.y_max() - 650;
    // Point topLeftCheckers(tlx, tly);

    // instantiate all the squares as rectangle objects with: heigth = width
    int numOfColumns = 8;
    int numOfRows = 8;

    // sqrSize == step of drawing
    int sqrSize = 80;

    // vector holding all (pointes to) rectangles
    vector<Graph_lib::Rectangle*> rects;
    int numOfSquares = numOfColumns *  numOfRows;
    rects.reserve(numOfSquares);

    for(size_t i=0; i < numOfColumns; ++i){
        for(size_t j=0; j < numOfRows; ++j){
            // create a 64 conjugate squares with size = 80, 
            Graph_lib::Rectangle* r = new Graph_lib::Rectangle(Point(tlx + sqrSize*i, tly + sqrSize*j), sqrSize, sqrSize);
            // fill the consequtive squares with white or red color
            if ((i+j) % 2 == 0) r->set_fill_color(Color::red);
            else r->set_color(Color::white);
            // save object in vector
            rects.push_back(r);
        }
    }
    // attach all the rectangle objects to the window object
    for(size_t k=0; k < rects.size(); ++k) sw.attach(*rects[k]);

    sw.wait_for_button();

}catch(exception& e){
    cerr << e.what() << endl;
    getchar();

}catch(...){
    cerr <<"Default exception!"<< endl;
    getchar();
}
return 0;
}

Questions:

  1. Are there any optimizations (or anything better) that can be done on the above code?
  2. Any useful tips and practices that one should know in the early stages, when using GUI's packages like FLTK?

*as part of B. Stroustrup's "Principles and practice of C++".
All the needed files for compilation are here.
The FLTK could be found here

\$\endgroup\$
3
\$\begingroup\$
    int wWidth = 660;
    int wHeigth = 660;

If you never change these, you may as well make them constants.

    const int wWidth = 660;
    const int wHeight = 660;

Then it's clear that they aren't intended to change.

I also fixed the spelling of "height".

    Simple_window sw(centerScreen, 660, 660, "Chapter 12 Exercise 3");

You just created variables for this. Why not use them?

    Simple_window sw(centerScreen, wWidth, wHeight, "Chapter 12 Exercise 3");

Then you can change one value and have it propagate through.

    int tlx = sw.x_max() - 650;
    int tly = sw.y_max() - 650;

Same thing here.

    const int FRAME_SIZE = 10;
    const int TOP_LEFT_X = sw.x_max() - wWidth + FRAME_SIZE;
    const int TOP_LEFT_Y = sw.y_max() - wHeight + FRAME_SIZE;

This would also save you a comment, as it is much more obvious what this does.

        for(size_t j=0; j < numOfColumns; ++j){

It won't make a functional difference if both are 8, but this should be

        for (size_t j = 0; j < numOfRows; ++j) {

Otherwise if you change one value without changing the other (e.g. if you wanted a 12x8 checkerboard), it won't draw the board as you designate it.

            if ((i+j) % 2 == 0) r->set_fill_color(Color::red);
            else r->set_color(Color::white);

It's more robust in the face of future edits to write this as

            if ((i + j) % 2 == 0) {
                r->set_fill_color(Color::red);
            } else {
                r->set_color(Color::white);
            }

Also consider

            r->set_fill_color(((i + j) % 2 == 0) ? Color::red : Color::white);

Which is more direct.

    for(size_t k=0; k < rects.size(); ++k) sw.attach(*rects[k]);

Why do this separately? Instead, put it in the j loop, at the end.

            sw.attach(*r);

Note that you can do this even if you put it in rects as well.

For this code, you don't need rects at all. Perhaps you're planning on using it later, but you don't really need it now.

In C++, when you use the new operator, the memory remains allocated until you explicitly delete it. You may want to use smart pointers. Those would work more like you think, with garbage collection when there are no references left.

Also, if you hadn't used new but instead created a local variable that would have been automatically destroyed, putting it in rects wouldn't have worked. The rects vector would have just contained a bunch of references to memory that no longer represented what it had when it was created.

\$\endgroup\$
  • \$\begingroup\$ Thank you for the useful suggestions, I've just applied them in the original code. Now, considering the comment about the last line of code: the for loop sw.attach(*rects[k]), my train of thought was to save the newly created objects in the for j loop in a container because after the loop is executed I didn't know is they were considered temporary (thereby destroyed) or not. That is why rects exists by the way: to save the temporary objects created in the for j loop for further use. \$\endgroup\$ – Ziezi Aug 31 '15 at 10:33
  • 1
    \$\begingroup\$ I edited my response into the answer. \$\endgroup\$ – mdfst13 Sep 1 '15 at 18:42
  • \$\begingroup\$ great, I see, so using new is what makes the object non-local and this is why rects is redundant. One last question: In the above code do I need to (and if so how) delete all the dynamically allocated objects. Is a for loop on the vector elements containing a delete rects[i] statement is going to do the job? \$\endgroup\$ – Ziezi Sep 1 '15 at 18:50
  • 1
    \$\begingroup\$ @simplicisveritatis For completeness' sake, you should do something like delete rects[i] in a loop when you're done. In this case though you'd do that at the end of the program when the memory will be released anyway. So it's good practice to do it but not horrible if you don't. I'd be more worried about this if your code was running in its own function or class where a user might expect to be able to continue after finishing (e.g. to stop displaying a checker board and start displaying a go or tic tac toe board). \$\endgroup\$ – mdfst13 Sep 2 '15 at 22:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.