main.cpp

Contains a hint what is wrong in gtk backend. - Zbigniew Rebacz, 02/24/2015 01:42 AM

Download (4.56 KB)

 
1
#include <CtrlLib/CtrlLib.h>
2

    
3
using namespace Upp;
4

    
5
class Bombs : public TopWindow {
6
public:
7
        virtual void Paint(Draw& w);
8
        virtual void LeftDown(Point p, dword flags);
9
        virtual void RightDown(Point p, dword flags);
10

    
11
private:
12
        Size         level;
13
        int          cx, cy;
14
        int          normal_cells, bombs;
15
        Buffer<byte> field;
16
        MenuBar      menu;
17
        StatusBar    status;
18

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

    
21
        enum {
22
                HIDDEN = 16,
23
                BOMB = 32,
24
                MARK = 64,
25
                EXPLODED = 128,
26

    
27
                UNIT = 30,
28
        };
29

    
30
        void About();
31

    
32
        void File(Bar& menu);
33
        void Game(Bar& menu);
34
        void Menu(Bar& menu);
35

    
36
        void ShowStatus();
37
        void Level(Size sz);
38

    
39
        void Uncover(int x, int y);
40
        void Generate();
41
        void UncoverAll();
42

    
43
public:
44
        typedef Bombs CLASSNAME;
45
        Bombs();
46
};
47

    
48
void Bombs::Generate()
49
{
50
        cx = level.cx;
51
        cy = level.cy;
52
        field.Alloc(cx * cy);
53
        for(int i = cx * cy - 1; i >= 0; i--)
54
                field[i] = (rand() & 15) < 3 ? HIDDEN|BOMB : HIDDEN;
55
        normal_cells = 0;
56
        for(int x = 0; x < cx; x++)
57
                for(int y = 0; y < cy; y++)
58
                        if((Field(x, y) & BOMB) == 0) {
59
                                normal_cells++;
60
                                for(int xx = -1; xx <= 1; xx++)
61
                                        for(int yy = -1; yy <= 1; yy++)
62
                                                if((xx || yy) && x + xx >= 0 && x + xx < cx && y + yy >= 0 && y + yy < cy &&
63
                                                   (Field(x + xx, y + yy) & BOMB))
64
                                                        Field(x, y)++;
65
                        }
66
        bombs = cx * cy - normal_cells;
67
        Rect r = GetRect();
68
        r.SetSize(AddFrameSize(UNIT * cx, UNIT * cy));
69
        SetRect(r);
70
        ShowStatus();
71
        Refresh();
72
}
73

    
74
void Bombs::UncoverAll()
75
{
76
        for(int i = cx * cy - 1; i >= 0; i--)
77
                field[i] &= ~HIDDEN;
78
        Refresh();
79
}
80

    
81
void Bombs::Paint(Draw& w)
82
{
83
        for(int x = 0; x < cx; x++)
84
                for(int y = 0; y < cy; y++) {
85
                        byte f = Field(x, y);
86
                        w.DrawRect(x * UNIT, y * UNIT + UNIT - 1, UNIT, 1, SBlack);
87
                        w.DrawRect(x * UNIT + UNIT - 1, y * UNIT, 1, UNIT, SBlack);
88
                        w.DrawRect(x * UNIT, y * UNIT, UNIT - 1, UNIT - 1,
89
                                   (f & (HIDDEN|MARK)) ? SLtGray : f & BOMB ? SLtRed : SWhite);
90
                        String txt;
91
                        Color ink = SBlack;
92
                        Color cross = Null;
93
                        if(f & MARK) {
94
                                txt = "M";
95
                                ink = SLtRed;
96
                                if((f & (HIDDEN|BOMB)) == BOMB) {
97
                                        ink = SLtBlue;
98
                                        cross = SLtRed;
99
                                }
100
                        }
101
                        else
102
                        if(!(f & HIDDEN))
103
                                if(f & BOMB)
104
                                        txt = "B";
105
                                else {
106
                                        f = f & 15;
107
                                        txt = String(f + '0', 1);
108
                                        ink = f == 0 ? SLtGreen : f == 1 ? SLtBlue : SBlack;
109
                                }
110
                        Size tsz = GetTextSize(txt, Roman(2 * UNIT / 3));
111
                        w.DrawText(x * UNIT + (UNIT - tsz.cx) / 2, y * UNIT + (UNIT - tsz.cy) / 2,
112
                                   txt, Roman(2 * UNIT / 3), ink);
113
                        if(f & EXPLODED)
114
                                cross = SLtBlue;
115
                        //if(!cross.IsNullInstance()) {
116
                                w.DrawLine(x * UNIT, y * UNIT, x * UNIT + UNIT - 1, y * UNIT + UNIT - 1, 1, cross);
117
                                w.DrawLine(x * UNIT, y * UNIT + UNIT - 1, x * UNIT + UNIT - 1, y * UNIT, 1, cross);
118
                        //}
119
                }
120
}
121

    
122
void Bombs::Uncover(int x, int y)
123
{
124
        if(x >= 0 && x < cx && y >= 0 && y < cy) {
125
                byte& f = Field(x, y);
126
                if((f & (HIDDEN|MARK)) == HIDDEN) {
127
                        if(f & BOMB) {
128
                                f |= EXPLODED;
129
                                normal_cells = 0;
130
                                UncoverAll();
131
                                return;
132
                        }
133
                        if((f &= ~HIDDEN) == 0)
134
                                for(int xx = -1; xx <= 1; xx++)
135
                                        for(int yy = -1; yy <= 1; yy++)
136
                                                if(xx || yy)
137
                                                        Uncover(x + xx, y + yy);
138
                        normal_cells--;
139
                        if(normal_cells == 0) {
140
                                UncoverAll();
141
                                PromptOK("[*@4A6 Nice!]&You have found all the bombs!");
142
                        }
143
                }
144
        }
145
}
146

    
147
void Bombs::LeftDown(Point p, dword flags)
148
{
149
        if(!normal_cells)
150
                return;
151
        p /= UNIT;
152
        Uncover(p.x, p.y);
153
        Refresh();
154
        ShowStatus();
155
}
156

    
157
void Bombs::RightDown(Point p, dword flags)
158
{
159
        if(!normal_cells)
160
                return;
161
        p /= UNIT;
162
        if(Field(p.x, p.y) & HIDDEN) {
163
                Field(p.x, p.y) ^= MARK;
164
                Refresh();
165
        }
166
}
167

    
168
void Bombs::ShowStatus()
169
{
170
        status = Format("%d bombs, %d cells remaining", bombs, normal_cells);
171
}
172

    
173
void Bombs::Level(Size sz)
174
{
175
        level = sz;
176
}
177

    
178
void Bombs::About()
179
{
180
        PromptOK("[*A9/ uBombs]&[A5 Ultimate`+`+ example]");
181
}
182

    
183
void Bombs::File(Bar& menu)
184
{
185
        menu.Add("Exit", Breaker(IDOK));
186
        menu.Separator();
187
        menu.Add("About..", THISBACK(About));
188
}
189

    
190
void Bombs::Game(Bar& menu)
191
{
192
        menu.Add("Restart", THISBACK(Generate));
193
        menu.Separator();
194
        menu.Add("Easy", THISBACK1(Level, Size(10, 10)))
195
            .Check(level.cx == 10);
196
        menu.Add("Medium", THISBACK1(Level, Size(15, 15)))
197
            .Check(level.cx == 15);
198
        menu.Add("Difficult", THISBACK1(Level, Size(25, 20)))
199
            .Check(level.cx == 25);
200
}
201

    
202
void Bombs::Menu(Bar& menu)
203
{
204
        menu.Add("File", THISBACK(File));
205
        menu.Add("Game", THISBACK(Game));
206
}
207

    
208
#define IMAGECLASS BombsImg
209
#define IMAGEFILE  <Bombs/bombs.iml>
210
#include <Draw/iml.h>
211

    
212
Bombs::Bombs()
213
{
214
        level = Size(10, 10);
215
        AddFrame(menu);
216
        menu.Set(THISBACK(Menu));
217
        AddFrame(status);
218
        AddFrame(InsetFrame());
219
        Title("uBombs");
220
        Icon(BombsImg::Small());
221
        Generate();
222
}
223

    
224
GUI_APP_MAIN
225
{
226
        Bombs().Run();
227
}