Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
UppHub
Status & Roadmap
FAQ
Authors & License
Forums
Funding U++
Search on this site











SourceForge.net Logo

SourceForge.net Logo

GitHub Logo

Discord Logo

U++ vs wxWidgets

To compare U++ with wxWindows, we decided to reimplement wxWindows demonstration example "Bombs". On the left side is U++ code, on the right side wxWidgets code (part of wxWidgets release).

 

 

 

U++ version

wxWidgets version

#include <CtrlLib/CtrlLib.h>

 

class Bombs : public TopWindow {

public:

    virtual void Paint(Draw& w);

    virtual void LeftDown(Point p, dword flags);

    virtual void RightDown(Point p, dword flags);

 

private:

    Size         level;

    int          cx, cy;

    int          normal_cells, bombs;

    Buffer<byte> field;

    MenuBar      menu;

    StatusBar    status;

    

    byte& Field(int x, int y) { return field[x + y * cx]; }

    

    enum {

        HIDDEN = 16,

        BOMB = 32,

        MARK = 64,

        EXPLODED = 128,

 

        UNIT = 30,

    };

 

    void About();

    

    void File(Bar& menu);

    void Game(Bar& menu);

    void Menu(Bar& menu);

    

    void Status();

    void Level(Size sz);

 

public:

    void Uncover(int x, int y);

    void Generate();

    void UncoverAll();

 

    typedef Bombs CLASSNAME;

    Bombs();

};

 

void Bombs::Generate()

{

    cx = level.cx;

    cy = level.cy;

    field.Alloc(cx * cy);

    for(int i = cx * cy - 1; i >= 0; i--)

        field[i] = (rand() & 15) < 3 ? HIDDEN|BOMB : HIDDEN;

    normal_cells = 0;

    for(int x = 0; x < cx; x++)

        for(int y = 0; y < cy; y++)

            if((Field(x, y) & BOMB) == 0) {

                normal_cells++;

                for(int xx = -1; xx <= 1; xx++)

                    for(int yy = -1; yy <= 1; yy++)

                        if((xx || yy) && x + xx >= 0 && x + xx < cx && y + yy >= 0 && y + yy < cy &&

                           (Field(x + xx, y + yy) & BOMB))

                            Field(x, y)++;

            }

    bombs = cx * cy - normal_cells;

    Rect r = GetRect();

    r.SetSize(AddFrameSize(UNIT * cx, UNIT * cy));

    SetRect(r);

    Status();

    Refresh();

}

 

void Bombs::UncoverAll()

{

    for(int i = cx * cy - 1; i >= 0; i--)

        field[i] &= ~HIDDEN;

    Refresh();

}

 

void Bombs::Paint(Draw& w)

{

    for(int x = 0; x < cx; x++)

        for(int y = 0; y < cy; y++) {

            byte f = Field(x, y);

            w.DrawRect(x * UNIT, y * UNIT + UNIT - 1, UNIT, 1, SBlack);

            w.DrawRect(x * UNIT + UNIT - 1, y * UNIT, 1, UNIT, SBlack);

            w.DrawRect(x * UNIT, y * UNIT, UNIT - 1, UNIT - 1,

                       (f & (HIDDEN|MARK)) ? SLtGray : f & BOMB ? SLtRed : SWhite);

            String txt;

            Color ink = SBlack;

            Color cross = Null;

            if(f & MARK) {

                txt = "M";

                ink = SLtRed;

                if((f & (HIDDEN|BOMB)) == BOMB) {

                    ink = SLtBlue;

                    cross = SLtRed;

                }

            }

            else

            if(!(f & HIDDEN))

                if(f & BOMB)

                    txt = "B";

                else {

                    f = f & 15;

                    txt = String(f + '0', 1);

                    ink = f == 0 ? SLtGreen : f == 1 ? SLtBlue : SBlack;

                }

            Size tsz = w.GetTextSize(txt, Roman(2 * UNIT / 3));

            w.DrawText(x * UNIT + (UNIT - tsz.cx) / 2, y * UNIT + (UNIT - tsz.cy) / 2,

                       txt, Roman(2 * UNIT / 3), ink);

            if(f & EXPLODED)

                cross = SLtBlue;

            w.DrawLine(x * UNIT, y * UNIT, x * UNIT + UNIT - 1, y * UNIT + UNIT - 1, 1, cross);

            w.DrawLine(x * UNIT, y * UNIT + UNIT - 1, x * UNIT + UNIT - 1, y * UNIT, 1, cross);

        }

}

 

void Bombs::Uncover(int x, int y)

{

    if(x >= 0 && x < cx && y >= 0 && y < cy) {

        byte& f = Field(x, y);

        if((f & (HIDDEN|MARK)) == HIDDEN) {

            if(f & BOMB) {

                f |= EXPLODED;

                normal_cells = 0;

                UncoverAll();

                return;

            }

            if((f &= ~HIDDEN) == 0)

                for(int xx = -1; xx <= 1; xx++)

                    for(int yy = -1; yy <= 1; yy++)

                        if(xx || yy)

                            Uncover(x + xx, y + yy);

            normal_cells--;

            if(normal_cells == 0) {

                UncoverAll();

                PromptOK("[*@4A6 Nice!]&You have found all the bombs!");

            }

        }

    }

}

 

void Bombs::LeftDown(Point p, dword flags)

{

    if(!normal_cells)

        return;

    p /= UNIT;

    Uncover(p.x, p.y);

    Refresh();

    Status();

}

 

void Bombs::RightDown(Point p, dword flags)

{

    if(!normal_cells)

        return;

    p /= UNIT;

    if(Field(p.x, p.y) & HIDDEN) {

        Field(p.x, p.y) ^= MARK;

        Refresh();

    }

}

 

void Bombs::Status()

{

    status = Format("%d bombs, %d cells remaining", bombs, normal_cells);

}

 

void Bombs::Level(Size sz)

{

    level = sz;

}

 

void Bombs::About()

{

    PromptOK("[*A9/ uBombs]&[A5 Ultimate`+`+ example]");

}

 

void Bombs::File(Bar& menu)

{

    menu.Add("Exit", Breaker(IDOK));

    menu.Separator();

    menu.Add("About..", THISBACK(About));

}

 

void Bombs::Game(Bar& menu)

{

    menu.Add("Restart", THISBACK(Generate));

    menu.Separator();

    menu.Add("Easy", THISBACK1(Level, Size(10, 10)))

        .Check(level.cx == 10);

    menu.Add("Medium", THISBACK1(Level, Size(15, 15)))

        .Check(level.cx == 15);

    menu.Add("Difficult", THISBACK1(Level, Size(25, 20)))

        .Check(level.cx == 25);

}

 

void Bombs::Menu(Bar& menu)

{

    menu.Add("File", THISBACK(File));

    menu.Add("Game", THISBACK(Game));

}

 

#define IMAGECLASS BombsImg

#define IMAGEFILE  <Bombs/bombs.iml>

#include <Draw/iml.h>

 

Bombs::Bombs()

{

    level = Size(10, 10);

    AddFrame(menu);

    menu.Set(THISBACK(Menu));

    AddFrame(status);

    AddFrame(InsetFrame());

    Title("uBombs");

    Icon(BombsImg::Small());

    Generate();

}

 

GUI_APP_MAIN

{

    Bombs b;

    b.Run();

}

 

#include <wx/wx.h>

 

const int ID_RESTART =   100;

const int ID_EASY =      101;

const int ID_MEDIUM =    102;

const int ID_DIFFICULT = 103;

 

class MyFrame: public wxFrame

{

public:

   MyFrame( const wxString &title, const wxPoint& pos, const wxSize& size );

   void OnAbout( wxCommandEvent &event );

   void OnQuit( wxCommandEvent &event );

   void OnLevel( wxCommandEvent &event );

   void OnRestart( wxCommandEvent &event );

   void OnPaint( wxPaintEvent& event );

   void OnLeftDown( wxMouseEvent &event );

   void OnRightDown( wxMouseEvent &event );

 

   wxSize       level;

   int          cx, cy;

   int          normal_cells, bombs;

   wxString     field;

   

   enum {

       HIDDEN = 16,

       BOMB = 32,

       MARK = 64,

       EXPLODED = 128,

       UNIT = 30,

   };

   

   wxChar& Field(int x, int y) { return field[x + y * cx]; }

   void Level( wxSize size )   { level = size; }

   void Status();

 

public:

   void Uncover(int x, int y);

   void Generate();

   void UncoverAll();

};

 

class MyApp: public wxApp

{

public:

   virtual bool OnInit();

};

 

MyFrame::MyFrame( const wxString &title, const wxPoint &position, const wxSize& size ) :

   wxFrame( NULL, -1, title, position, size )

{

   wxMenu *file_menu = new wxMenu;

   file_menu->Append( wxID_ABOUT, wxT("About..."), wxT("Program info") );

   file_menu->AppendSeparator();

   file_menu->Append( wxID_EXIT, wxT("Quit"), wxT("Quit wxBombs") );

   

   wxMenu *game_menu = new wxMenu;

   game_menu->Append( ID_RESTART, wxT("Restart"), wxT("Restart game") );

   game_menu->AppendSeparator();

   game_menu->AppendRadioItem( ID_EASY, wxT("Easy"), wxT("Easy level") );

   game_menu->AppendRadioItem( ID_MEDIUM, wxT("Medium"), wxT("Medium level") );

   game_menu->AppendRadioItem( ID_DIFFICULT, wxT("Difficult"), wxT("Difficult level") );

 

   wxMenuBar *menu_bar = new wxMenuBar();

   menu_bar->Append( file_menu, wxT("File") );

   menu_bar->Append( game_menu, wxT("Game") );

   

   SetMenuBar( menu_bar );

   

   CreateStatusBar(1);

   

   Connect( wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnAbout) );

   Connect( wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnQuit) );

   Connect( ID_RESTART, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnRestart) );

   Connect( ID_EASY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnLevel) );

   Connect( ID_MEDIUM, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnLevel) );

   Connect( ID_DIFFICULT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnLevel) );

   

   Connect( -1, wxEVT_LEFT_DOWN, wxMouseEventHandler(MyFrame::OnLeftDown) );

   Connect( -1, wxEVT_RIGHT_DOWN, wxMouseEventHandler(MyFrame::OnRightDown) );

   Connect( -1, wxEVT_PAINT, wxPaintEventHandler(MyFrame::OnPaint) );

   

   level = wxSize( 10, 10 );

}

 

 

void MyFrame::OnAbout( wxCommandEvent &event )

{

   wxMessageDialog dialog( this, wxT("Welcome to wxBombs"), wxT("About wxBombs"), wxOK|wxICON_INFORMATION );

   dialog.ShowModal();

}

 

void MyFrame::OnQuit( wxCommandEvent &event )

{

    Close( TRUE );

}

 

void MyFrame::OnLevel( wxCommandEvent &event )

{

   switch (event.GetId())

   {

       case ID_EASY:       Level( wxSize( 10,10 ) ); break;

       case ID_MEDIUM:     Level( wxSize( 15,15 ) ); break;

       case ID_DIFFICULT:  Level( wxSize( 25,25 ) ); break;

   }

}

 

void MyFrame::OnRestart( wxCommandEvent &event )

{

   Generate();

}

 

void MyFrame::OnPaint( wxPaintEvent& event )

{

   wxPaintDC w( this );

   

   for(int x = 0; x < cx; x++)

       for(int y = 0; y < cy; y++) {

           wxChar f = Field(x, y);

           w.SetPen( *wxBLACK_PEN );

           w.DrawRectangle(x * UNIT, y * UNIT + UNIT - 1, UNIT, 1 );

           w.DrawRectangle(x * UNIT + UNIT - 1, y * UNIT, 1, UNIT );

           

           w.SetPen( (f & (HIDDEN|MARK)) ? *wxGREY_PEN : f & BOMB ? *wxRED_PEN : *wxWHITE_PEN );

           w.DrawRectangle(x * UNIT, y * UNIT, UNIT - 1, UNIT - 1 );

 

           wxString txt;

           wxColour ink = *wxBLACK;

           wxPen cross;

           if(f & MARK) {

               txt = wxT("M");

               ink = *wxRED;

               if((f & (HIDDEN|BOMB)) == BOMB) {

                   ink = *wxBLUE;

                   cross = *wxBLACK_PEN;

               }

           }

           else

           if(!(f & HIDDEN))

               if(f & BOMB)

                   txt = wxT("B");

               else {

                   f = f & 15;

                   txt = wxString( wxChar( f + wxT('0') ), (unsigned int )1);

                   ink = f == 0 ? *wxGREEN : f == 1 ? *wxBLUE : *wxBLACK;

               }

 

           wxSize tsz = w.GetTextExtent(txt);

           w.DrawText(txt, x * UNIT + (UNIT - tsz.x) / 2, y * UNIT + (UNIT - tsz.y) / 2 );

           if(f & EXPLODED)

               cross = wxPen( *wxBLUE );

           

           if (cross != wxNullPen)

           {

               w.SetPen ( cross );

               w.DrawLine(x * UNIT, y * UNIT, x * UNIT + UNIT - 1, y * UNIT + UNIT - 1 );

               w.DrawLine(x * UNIT, y * UNIT + UNIT - 1, x * UNIT + UNIT - 1, y * UNIT );

           }

       }

}

 

void MyFrame::OnLeftDown( wxMouseEvent &event )

{

   if(!normal_cells)

       return;

   wxPoint p( event.GetX(), event.GetY() );

   p.x /= UNIT;

   p.y /= UNIT;

   Uncover(p.x, p.y);

   Refresh();

   Status();

}

 

void MyFrame::OnRightDown( wxMouseEvent &event )

{

   if(!normal_cells)

       return;

   wxPoint p( event.GetX(), event.GetY() );

   p.x /= UNIT;

   p.y /= UNIT;

   if(Field(p.x, p.y) & HIDDEN) {

       Field(p.x, p.y) ^= MARK;

       Refresh();

   }

}

 

void MyFrame::Status()

{

   wxString text;

   text.Printf( wxT("%d bombs, %d cells remaining"), bombs, normal_cells );

   SetStatusText( text );

}

 

void MyFrame::Generate()

{

   cx = level.x;

   cy = level.y;

   field.Alloc(cx * cy);

   for(int i = cx * cy - 1; i >= 0; i--)

       field[i] = (rand() & 15) < 3 ? HIDDEN|BOMB : HIDDEN;

   normal_cells = 0;

   for(int x = 0; x < cx; x++)

       for(int y = 0; y < cy; y++)

           if((Field(x, y) & BOMB) == 0) {

               normal_cells++;

               for(int xx = -1; xx <= 1; xx++)

                   for(int yy = -1; yy <= 1; yy++)

                    if((xx || yy) && x + xx >= 0 && x + xx < cx && y + yy >= 0 && y + yy < cy &&

                          (Field(x + xx, y + yy) & BOMB))

                           Field(x, y)++;

           }

   bombs = cx * cy - normal_cells;

   SetClientSize( wxSize(UNIT * cx, UNIT * cy));

   Status();

   Refresh();

}

 

void MyFrame::Uncover(int x, int y)

{

   if(x >= 0 && x < cx && y >= 0 && y < cy) {

       wxChar& f = Field(x, y);

       if((f & (HIDDEN|MARK)) == HIDDEN) {

           if(f & BOMB) {

               f |= EXPLODED;

               normal_cells = 0;

               UncoverAll();

               return;

           }

 

           if((f &= ~HIDDEN) == 0)

               for(int xx = -1; xx <= 1; xx++)

                   for(int yy = -1; yy <= 1; yy++)

                       if(xx || yy)

                           Uncover(x + xx, y + yy);

           normal_cells--;

           if(normal_cells == 0) {

               UncoverAll();

               wxMessageDialog dialog( this, wxT("You have found all the bombs!"), wxT("wxBombs"), wxOK|wxICON_INFORMATION );

               dialog.ShowModal();

           }

       }

   }

}

 

void MyFrame::UncoverAll()

{

   for(int i = cx * cy - 1; i >= 0; i--)

       field[i] = field[i] & ~HIDDEN;

   Refresh();

}

 

IMPLEMENT_APP(MyApp)

 

bool MyApp::OnInit()

{

   MyFrame *frame = new MyFrame( wxT("wxBombs"), wxPoint(20,20), wxSize(500,340) );

   frame->Show( TRUE );

   return TRUE;

}

Do you want to contribute?