applied patch to uncover cells next to 0 automatically
[wxWidgets.git] / demos / bombs / bombs1.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: bombs1.cpp
3 // Purpose: Bombs game
4 // Author: P. Foggia 1996
5 // Modified by:
6 // Created: 1996
7 // RCS-ID: $Id$
8 // Copyright: (c) 1996 P. Foggia
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 /*
13 * implementation of the methods DrawField and OnEvent of the
14 * class BombsCanvas
15 */
16
17 #ifdef __GNUG__
18 #pragma implementation
19 #endif
20
21 #include "wx/wxprec.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif //precompiled headers
26
27 #include "bombs.h"
28
29 /*-------- BombCanvasClass::DrawField(dc, xc1, yc1, xc2, yc2) -------*/
30 /* Draws the field on the device context dc */
31 /* xc1,yc1 etc. are the (inclusive) limits of the area to be drawn, */
32 /* expressed in cells. */
33 /*---------------------------------------------------------------------*/
34 void BombsCanvasClass::DrawField(wxDC *dc, int xc1, int yc1, int xc2, int yc2)
35 { int x,y,xmax,ymax;
36 char buf[2];
37 long chw, chh;
38
39 wxColour *wxBlack = wxTheColourDatabase->FindColour("BLACK");
40 wxColour *wxWhite = wxTheColourDatabase->FindColour("WHITE");
41 wxColour *wxRed = wxTheColourDatabase->FindColour("RED");
42 wxColour *wxBlue = wxTheColourDatabase->FindColour("BLUE");
43 wxColour *wxGrey = wxTheColourDatabase->FindColour("LIGHT GREY");
44 wxColour *wxGreen = wxTheColourDatabase->FindColour("GREEN");
45
46 wxPen *blackPen = wxThePenList->FindOrCreatePen(*wxBlack, 1, wxSOLID);
47 wxPen *redPen = wxThePenList->FindOrCreatePen(*wxRed, 1, wxSOLID);
48 wxPen *bluePen = wxThePenList->FindOrCreatePen(*wxBlue, 1, wxSOLID);
49 wxBrush *whiteBrush = wxTheBrushList->FindOrCreateBrush(*wxWhite, wxSOLID);
50 wxBrush *greyBrush = wxTheBrushList->FindOrCreateBrush(*wxGrey, wxSOLID);
51 wxBrush *redBrush = wxTheBrushList->FindOrCreateBrush(*wxRed, wxSOLID);
52
53 xmax=field_width*x_cell*X_UNIT;
54 ymax=field_height*y_cell*Y_UNIT;
55
56
57 dc->SetPen(* blackPen);
58 for(x=xc1; x<=xc2; x++)
59 dc->DrawLine(x*x_cell*X_UNIT, 0, x*x_cell*X_UNIT, ymax);
60 for(y=xc1; y<=yc2; y++)
61 dc->DrawLine(0, y*y_cell*Y_UNIT, xmax, y*y_cell*Y_UNIT);
62
63
64 wxFont font= BOMBS_FONT;
65 dc->SetFont(font);
66
67 buf[1]='\0';
68 for(x=xc1; x<=xc2; x++)
69 for(y=yc1; y<=yc2; y++)
70 { if (wxGetApp().Game.IsMarked(x,y))
71 { dc->SetPen(* blackPen);
72 dc->SetBrush(* greyBrush);
73 dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT,
74 x_cell*X_UNIT+1, y_cell*Y_UNIT+1);
75 *buf='M';
76 if (!wxGetApp().Game.IsHidden(x,y) && wxGetApp().Game.IsBomb(x,y))
77 dc->SetTextForeground(*wxBlue);
78 else
79 dc->SetTextForeground(*wxRed);
80 dc->SetTextBackground(*wxGrey);
81 dc->GetTextExtent(buf, &chw, &chh);
82 dc->DrawText( buf,
83 x*x_cell*X_UNIT + (x_cell*X_UNIT-chw)/2,
84 y*y_cell*Y_UNIT + (y_cell*Y_UNIT-chh)/2
85 );
86 if (!wxGetApp().Game.IsHidden(x,y) && wxGetApp().Game.IsBomb(x,y))
87 { dc->SetPen(*redPen);
88 dc->DrawLine(x*x_cell*X_UNIT, y*y_cell*Y_UNIT,
89 (x+1)*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT);
90 dc->DrawLine(x*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT,
91 (x+1)*x_cell*X_UNIT, y*y_cell*Y_UNIT);
92 }
93 }
94 else if (wxGetApp().Game.IsHidden(x,y))
95 { dc->SetPen(*blackPen);
96 dc->SetBrush(*greyBrush);
97 dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT,
98 x_cell*X_UNIT+1, y_cell*Y_UNIT+1);
99 }
100 else if (wxGetApp().Game.IsBomb(x,y))
101 { dc->SetPen(* blackPen);
102 dc->SetBrush(* redBrush);
103 dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT,
104 x_cell*X_UNIT+1, y_cell*Y_UNIT+1);
105 *buf='B';
106 dc->SetTextForeground(* wxBlack);
107 dc->SetTextBackground(* wxRed);
108 dc->GetTextExtent(buf, &chw, &chh);
109 dc->DrawText( buf,
110 x*x_cell*X_UNIT + (x_cell*X_UNIT-chw)/2,
111 y*y_cell*Y_UNIT + (y_cell*Y_UNIT-chh)/2
112 );
113 if (wxGetApp().Game.IsExploded(x,y))
114 { dc->SetPen(* bluePen);
115 dc->DrawLine(x*x_cell*X_UNIT, y*y_cell*Y_UNIT,
116 (x+1)*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT);
117 dc->DrawLine(x*x_cell*X_UNIT, (y+1)*y_cell*Y_UNIT,
118 (x+1)*x_cell*X_UNIT, y*y_cell*Y_UNIT);
119 }
120 }
121 else // Display a digit
122 { dc->SetPen(* blackPen);
123 dc->SetBrush(* whiteBrush);
124 dc->DrawRectangle( x*x_cell*X_UNIT, y*y_cell*Y_UNIT,
125 x_cell*X_UNIT+1, y_cell*Y_UNIT+1);
126 *buf = (wxGetApp().Game.Get(x,y) & BG_MASK) + '0';
127 dc->GetTextExtent(buf, &chw, &chh);
128 switch(*buf)
129 { case '0': dc->SetTextForeground(* wxGreen); break;
130 case '1': dc->SetTextForeground(* wxBlue); break;
131 default: dc->SetTextForeground(* wxBlack); break;
132 }
133 dc->SetTextBackground(* wxWhite);
134 dc->DrawText( buf,
135 x*x_cell*X_UNIT + (x_cell*X_UNIT-chw)/2,
136 y*y_cell*Y_UNIT + (y_cell*Y_UNIT-chh)/2
137 );
138 }
139 }
140 dc->SetFont(wxNullFont);
141
142 if (wxGetApp().BombsFrame)
143 { char buf[80];
144 sprintf(buf, "%d bombs %d remaining cells",
145 wxGetApp().Game.GetBombs(), wxGetApp().Game.GetRemainingCells());
146 wxGetApp().BombsFrame->SetStatusText(buf, 0);
147 }
148 }
149
150 /*-------- BombCanvasClass::Refresh(xc1, yc1, xc2, yc2) -------------*/
151 /* Refreshes the field image */
152 /* xc1,yc1 etc. are the (inclusive) limits of the area to be drawn, */
153 /* expressed in cells. */
154 /*---------------------------------------------------------------------*/
155 void BombsCanvasClass::Refresh(int xc1, int yc1, int xc2, int yc2)
156 {
157 wxClientDC dc(this);
158 DrawField(& dc, xc1, yc1, xc2, yc2);
159 if (bmp)
160 { wxMemoryDC memDC;
161 memDC.SelectObject(* bmp);
162 DrawField(&memDC, xc1, yc1, xc2, yc2);
163 memDC.SelectObject(wxNullBitmap);
164 }
165 }
166
167 // Called when uncovering a cell.
168 void BombsCanvasClass::Uncover(int x, int y)
169 {
170 wxGetApp().Game.Unhide(x,y);
171 Refresh(x, y, x, y);
172 if (wxGetApp().Game.IsBomb(x,y) || wxGetApp().Game.GetRemainingCells()==0)
173 { wxBell();
174 if (!wxGetApp().Game.IsBomb(x,y))
175 { wxMessageBox("Nice! You found all the bombs!", "wxWin Bombs",
176 wxOK|wxCENTRE, wxGetApp().BombsFrame);
177 }
178 else // x,y is a bomb
179 { wxGetApp().Game.Explode(x, y);
180 }
181 for(x=0; x<field_width; x++)
182 for(y=0; y<field_height; y++)
183 wxGetApp().Game.Unhide(x,y);
184 Refresh(0, 0, field_width-1, field_height-1);
185 }
186 else if (!wxGetApp().Game.Get(x, y))
187 { int left = ( x > 0 ) ? x-1 : 0;
188 int right = ( x < wxGetApp().Game.GetWidth() - 1 )?
189 x+1 : wxGetApp().Game.GetWidth() - 1;
190 int top = ( y > 0 ) ? y-1 : 0;
191 int bottom = ( y < wxGetApp().Game.GetHeight() - 1 )?
192 y+1 : wxGetApp().Game.GetHeight() - 1;
193 int i,j;
194 for (j = top; j <= bottom; j++)
195 for (i=left; i <= right; i++)
196 if ((i != x || j != y) && wxGetApp().Game.IsHidden(i,j)
197 && !wxGetApp().Game.IsMarked(i,j))
198 Uncover(i,j);
199 }
200 }
201
202 // Called when the canvas receives a mouse event.
203 void BombsCanvasClass::OnEvent(wxMouseEvent& event)
204 {
205 wxCoord fx, fy;
206 event.GetPosition(&fx, &fy);
207 int x = fx/(x_cell*X_UNIT);
208 int y = fy/(y_cell*Y_UNIT);
209 if (x<field_width && y<field_height)
210 { if ( (event.RightDown() || (event.LeftDown() && event.ShiftDown()))
211 && (wxGetApp().Game.IsHidden(x,y)
212 || wxGetApp().Game.GetRemainingCells()==0))
213 { wxGetApp().Game.Mark(x,y);
214 Refresh(x, y, x, y);
215 return;
216 }
217 else if (event.LeftDown() && wxGetApp().Game.IsHidden(x,y)
218 && !wxGetApp().Game.IsMarked(x,y))
219 { Uncover(x,y);
220 return;
221 }
222 }
223 }
224