summaryrefslogtreecommitdiff
authordrw <drw>2002-03-15 20:33:05 (UTC)
committer drw <drw>2002-03-15 20:33:05 (UTC)
commit20cbfeefd68221f7b6f9dd512c6ff3e9a9484af2 (patch) (unidiff)
tree06e7b467ababb70d10b0c343f5b7881490c20b66
parenteb338502c03edbfc8b9b9f00bd95c0c0d4317003 (diff)
downloadopie-20cbfeefd68221f7b6f9dd512c6ff3e9a9484af2.zip
opie-20cbfeefd68221f7b6f9dd512c6ff3e9a9484af2.tar.gz
opie-20cbfeefd68221f7b6f9dd512c6ff3e9a9484af2.tar.bz2
Fixed segfault and resizing issue for minefield
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/minesweep/minefield.cpp410
1 files changed, 256 insertions, 154 deletions
diff --git a/noncore/games/minesweep/minefield.cpp b/noncore/games/minesweep/minefield.cpp
index be2f9a3..eca1a36 100644
--- a/noncore/games/minesweep/minefield.cpp
+++ b/noncore/games/minesweep/minefield.cpp
@@ -38,586 +38,688 @@ static const char *pix_flag[]={
38".............", 38".............",
39".....#xxxxxx.", 39".....#xxxxxx.",
40".....#xxxxxx.", 40".....#xxxxxx.",
41".....#xxxxxx.", 41".....#xxxxxx.",
42".....#xxxxxx.", 42".....#xxxxxx.",
43".....#.......", 43".....#.......",
44".....#.......", 44".....#.......",
45".....#.......", 45".....#.......",
46".....#.......", 46".....#.......",
47"...#####.....", 47"...#####.....",
48"..#######....", 48"..#######....",
49"............."}; 49"............."};
50 50
51static const char *pix_mine[]={ 51static const char *pix_mine[]={
52"13 13 3 1", 52"13 13 3 1",
53"# c #000000", 53"# c #000000",
54". c None", 54". c None",
55"a c #ffffff", 55"a c #ffffff",
56"......#......", 56"......#......",
57"......#......", 57"......#......",
58"..#.#####.#..", 58"..#.#####.#..",
59"...#######...", 59"...#######...",
60"..##aa#####..", 60"..##aa#####..",
61"..##aa#####..", 61"..##aa#####..",
62"#############", 62"#############",
63"..#########..", 63"..#########..",
64"..#########..", 64"..#########..",
65"...#######...", 65"...#######...",
66"..#.#####.#..", 66"..#.#####.#..",
67"......#......", 67"......#......",
68"......#......"}; 68"......#......"};
69 69
70class Mine : public QTableItem 70
71static const int maxGrid = 28;
72static const int minGrid = 9;
73
74
75
76class Mine : public Qt
71{ 77{
72public: 78public:
73 enum MineState { 79 enum MineState {
74 Hidden = 0, 80 Hidden = 0,
75 Empty, 81 Empty,
76 Mined, 82 Mined,
77 Flagged, 83 Flagged,
78#ifdef MARK_UNSURE 84#ifdef MARK_UNSURE
79 Unsure, 85 Unsure,
80#endif 86#endif
81 Exploded, 87 Exploded,
82 Wrong 88 Wrong
83 }; 89 };
84 90
85 Mine( QTable* ); 91 Mine( MineField* );
86 void paint( QPainter * p, const QColorGroup & cg, const QRect & cr, bool selected ); 92 void paint( QPainter * p, const QColorGroup & cg, const QRect & cr );
87 EditType editType() const { return Never; } 93
88 QSize sizeHint() const { return QSize( 12, 12 ); } 94 QSize sizeHint() const { return QSize( maxGrid, maxGrid ); }
89 95
90 void activate( bool sure = TRUE ); 96 void activate( bool sure = TRUE );
91 void setHint( int ); 97 void setHint( int );
92 98
93 void setState( MineState ); 99 void setState( MineState );
94 MineState state() const { return st; } 100 MineState state() const { return st; }
95 101
96 bool isMined() const { return mined; } 102 bool isMined() const { return mined; }
97 void setMined( bool m ) { mined = m; } 103 void setMined( bool m ) { mined = m; }
98 104
99 static void paletteChange(); 105 static void paletteChange();
100 106
101private: 107private:
102 bool mined; 108 bool mined;
103 int hint; 109 int hint;
104 110
105 MineState st; 111 MineState st;
106 112 MineField *field;
113
107 static QPixmap* knownField; 114 static QPixmap* knownField;
108 static QPixmap* unknownField; 115 static QPixmap* unknownField;
109 static QPixmap* flag_pix; 116 static QPixmap* flag_pix;
110 static QPixmap* mine_pix; 117 static QPixmap* mine_pix;
111}; 118};
112 119
113QPixmap* Mine::knownField = 0; 120QPixmap* Mine::knownField = 0;
114QPixmap* Mine::unknownField = 0; 121QPixmap* Mine::unknownField = 0;
115QPixmap* Mine::flag_pix = 0; 122QPixmap* Mine::flag_pix = 0;
116QPixmap* Mine::mine_pix = 0; 123QPixmap* Mine::mine_pix = 0;
117 124
118Mine::Mine( QTable *t ) 125Mine::Mine( MineField *f )
119: QTableItem( t, Never, QString::null )
120{ 126{
121 mined = FALSE; 127 mined = FALSE;
122 st = Hidden; 128 st = Hidden;
123 hint = 0; 129 hint = 0;
130 field = f;
124} 131}
125 132
126void Mine::activate( bool sure ) 133void Mine::activate( bool sure )
127{ 134{
128 if ( !sure ) { 135 if ( !sure ) {
129 switch ( st ) { 136 switch ( st ) {
130 case Hidden: 137 case Hidden:
131 setState( Flagged ); 138 setState( Flagged );
132 break; 139 break;
133 case Flagged: 140 case Flagged:
134#ifdef MARK_UNSURE 141#ifdef MARK_UNSURE
135 setState( Unsure ); 142 setState( Unsure );
136 break; 143 break;
137 case Unsure: 144 case Unsure:
138#endif 145#endif
139 setState( Hidden ); 146 setState( Hidden );
140 default: 147 default:
141 break; 148 break;
142 } 149 }
143 } else if ( st == Flagged ) { 150 } else if ( st == Flagged ) {
144 return; 151 return;
145 } else { 152 } else {
146 if ( mined ) { 153 if ( mined ) {
147 setState( Exploded ); 154 setState( Exploded );
148 } else { 155 } else {
149 setState( Empty ); 156 setState( Empty );
150 } 157 }
151 } 158 }
152} 159}
153 160
154void Mine::setState( MineState s ) 161void Mine::setState( MineState s )
155{ 162{
156 st = s; 163 st = s;
157} 164}
158 165
159void Mine::setHint( int h ) 166void Mine::setHint( int h )
160{ 167{
161 hint = h; 168 hint = h;
162} 169}
163 170
164void Mine::paletteChange() 171void Mine::paletteChange()
165{ 172{
166 delete knownField; 173 delete knownField;
167 knownField = 0; 174 knownField = 0;
168 delete unknownField; 175 delete unknownField;
169 unknownField = 0; 176 unknownField = 0;
170 delete mine_pix; 177 delete mine_pix;
171 mine_pix = 0; 178 mine_pix = 0;
172 delete flag_pix; 179 delete flag_pix;
173 flag_pix = 0; 180 flag_pix = 0;
174} 181}
175 182
176void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) 183void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr )
177{ 184{
185 int x = cr.x();
186 int y = cr.y();
178 if ( !knownField ) { 187 if ( !knownField ) {
179 knownField = new QPixmap( cr.width(), cr.height() ); 188 knownField = new QPixmap( cr.width(), cr.height() );
180 QPainter pp( knownField ); 189 QPainter pp( knownField );
181 QBrush br( cg.button().dark(115) ); 190 QBrush br( cg.button().dark(115) );
182 qDrawWinButton( &pp, QRect(0,0,cr.width(), cr.height())/*cr*/, cg, TRUE, &br ); 191 qDrawWinButton( &pp, cr, cg, TRUE, &br );
183 } 192 }
184 193
185 const int pmmarg=cr.width()/5; 194 const int pmmarg=cr.width()/5;
186 195
187 if ( !unknownField ) { 196 if ( !unknownField ) {
188 unknownField = new QPixmap( cr.width(), cr.height() ); 197 unknownField = new QPixmap( cr.width(), cr.height() );
189 QPainter pp( unknownField ); 198 QPainter pp( unknownField );
190 QBrush br( cg.button() ); 199 QBrush br( cg.button() );
191 qDrawWinButton( &pp, QRect(0,0,cr.width(), cr.height())/*cr*/, cg, FALSE, &br ); 200 qDrawWinButton( &pp, cr, cg, FALSE, &br );
192 } 201 }
193 202
194 if ( !flag_pix ) { 203 if ( !flag_pix ) {
195 flag_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 ); 204 flag_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 );
196 flag_pix->convertFromImage( QImage(pix_flag).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) ); 205 flag_pix->convertFromImage( QImage(pix_flag).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) );
197 } 206 }
198 207
199 if ( !mine_pix ) { 208 if ( !mine_pix ) {
200 mine_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 ); 209 mine_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 );
201 mine_pix->convertFromImage( QImage(pix_mine).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) ); 210 mine_pix->convertFromImage( QImage(pix_mine).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) );
202 } 211 }
203 212
204 p->save(); 213 p->save();
205 214
206 switch(st) { 215 switch(st) {
207 case Hidden: 216 case Hidden:
208 p->drawPixmap( 0, 0, *unknownField ); 217 p->drawPixmap( x, y, *unknownField );
209 break; 218 break;
210 case Empty: 219 case Empty:
211 p->drawPixmap( 0, 0, *knownField ); 220 p->drawPixmap( x, y, *knownField );
212 if ( hint > 0 ) { 221 if ( hint > 0 ) {
213 switch( hint ) { 222 switch( hint ) {
214 case 1: 223 case 1:
215 p->setPen( blue ); 224 p->setPen( blue );
216 break; 225 break;
217 case 2: 226 case 2:
218 p->setPen( green ); 227 p->setPen( green.dark() );
228 break;
219 case 3: 229 case 3:
220 p->setPen( red ); 230 p->setPen( red );
221 break; 231 break;
222 default: 232 case 4:
233 p->setPen( darkYellow.dark() );
234 break;
235 case 5:
223 p->setPen( darkMagenta ); 236 p->setPen( darkMagenta );
224 break; 237 break;
238 case 6:
239 p->setPen( darkRed );
240 break;
241 default:
242 p->setPen( black );
243 break;
225 } 244 }
226 p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, QString().setNum( hint ) ); 245 p->drawText( cr, AlignHCenter | AlignVCenter, QString::number( hint ) );
227 } 246 }
228 break; 247 break;
229 case Mined: 248 case Mined:
230 p->drawPixmap( 0, 0, *knownField ); 249 p->drawPixmap( x, y, *knownField );
231 p->drawPixmap( pmmarg, pmmarg, *mine_pix ); 250 p->drawPixmap( x+pmmarg, y+pmmarg, *mine_pix );
232 break; 251 break;
233 case Exploded: 252 case Exploded:
234 p->drawPixmap( 0, 0, *knownField ); 253 p->drawPixmap( x, y, *knownField );
235 p->drawPixmap( pmmarg, pmmarg, *mine_pix ); 254 p->drawPixmap( x+pmmarg, y+pmmarg, *mine_pix );
236 p->setPen( red ); 255 p->setPen( red );
237 p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, "X" ); 256 p->drawText( cr, AlignHCenter | AlignVCenter, "X" );
238 break; 257 break;
239 case Flagged: 258 case Flagged:
240 p->drawPixmap( 0, 0, *unknownField ); 259 p->drawPixmap( x, y, *unknownField );
241 p->drawPixmap( pmmarg, pmmarg, *flag_pix ); 260 p->drawPixmap( x+pmmarg, y+pmmarg, *flag_pix );
242 break; 261 break;
243#ifdef MARK_UNSURE 262#ifdef MARK_UNSURE
244 case Unsure: 263 case Unsure:
245 p->drawPixmap( 0, 0, *unknownField ); 264 p->drawPixmap( x, y, *unknownField );
246 p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, "?" ); 265 p->drawText( cr, AlignHCenter | AlignVCenter, "?" );
247 break; 266 break;
248#endif 267#endif
249 case Wrong: 268 case Wrong:
250 p->drawPixmap( 0, 0, *unknownField ); 269 p->drawPixmap( x, y, *unknownField );
251 p->drawPixmap( pmmarg, pmmarg, *flag_pix ); 270 p->drawPixmap( x+pmmarg, y+pmmarg, *flag_pix );
252 p->setPen( red ); 271 p->setPen( red );
253 p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, "X" ); 272 p->drawText( cr, AlignHCenter | AlignVCenter, "X" );
254 break; 273 break;
255 } 274 }
256 275
257 p->restore(); 276 p->restore();
258} 277}
259 278
260/* 279/*
261 MineField implementation 280 MineField implementation
262*/ 281*/
263 282
264MineField::MineField( QWidget* parent, const char* name ) 283MineField::MineField( QWidget* parent, const char* name )
265: QTable( parent, name ) 284: QScrollView( parent, name )
266{ 285{
267 setState( GameOver ); 286 setState( GameOver );
268 setShowGrid( FALSE );
269 horizontalHeader()->hide();
270 verticalHeader()->hide();
271 setTopMargin( 0 );
272 setLeftMargin( 0 );
273 287
274 setSizePolicy( QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum ) ); 288 setSizePolicy( QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum ) );
275
276 setSelectionMode( QTable::NoSelection );
277 setFocusPolicy( QWidget::NoFocus );
278
279 setCurrentCell( -1, -1 );
280 289
281 connect( this, SIGNAL( pressed( int, int, int, const QPoint& ) ), this, SLOT( cellPressed( int, int ) ) ); 290 setFocusPolicy( QWidget::NoFocus );
282 connect( this, SIGNAL( clicked( int, int, int, const QPoint& ) ), this, SLOT( cellClicked( int, int ) ) );
283 291
284 holdTimer = new QTimer( this ); 292 holdTimer = new QTimer( this );
285 connect( holdTimer, SIGNAL( timeout() ), this, SLOT( held() ) ); 293 connect( holdTimer, SIGNAL( timeout() ), this, SLOT( held() ) );
286 294
287 flagAction = NoAction; 295 flagAction = NoAction;
288 ignoreClick = FALSE; 296 ignoreClick = FALSE;
289 currRow = currCol = 0; 297 currRow = currCol = -1;
290 minecount=0; 298 minecount=0;
291 mineguess=0; 299 mineguess=0;
292 nonminecount=0; 300 nonminecount=0;
301 cellSize = -1;
302 mines = 0;
293} 303}
294 304
295MineField::~MineField() 305MineField::~MineField()
296{ 306{
307 int i;
308 if ( mines )
309 {
310 for ( i = 0; i < numCols*numRows; i++ )
311 {
312 delete mines[i];
313 }
314 delete[] mines;
315 }
297} 316}
298 317
299void MineField::setState( State st ) 318void MineField::setState( State st )
300{ 319{
301 stat = st; 320 stat = st;
302} 321}
303 322
304
305void MineField::setup( int level ) 323void MineField::setup( int level )
306{ 324{
307 lev = level; 325 lev = level;
308 setState( Waiting ); 326 setState( Waiting );
309 viewport()->setUpdatesEnabled( FALSE ); 327 //viewport()->setUpdatesEnabled( FALSE );
310 328
311 int cellsize; 329 int i;
312 330 if ( mines )
313 int x; 331 {
314 int y; 332 for ( i = 0; i < numCols*numRows; i++ )
315 for ( x = 0; x < numCols(); x++ ) 333 {
316 for ( y = 0; y < numRows(); y++ ) 334 delete mines[i];
317 clearCell( y, x ); 335 }
336 delete[] mines;
337 }
318 338
319 switch( lev ) { 339 switch( lev ) {
320 case 1: 340 case 1:
321 setNumRows( 9 ); 341 numRows = 9 ;
322 setNumCols( 9 ); 342 numCols = 9 ;
323 minecount = 12; 343 minecount = 12;
324 cellsize = 21;
325 break; 344 break;
326 case 2: 345 case 2:
327 setNumRows( 16 ); 346 numRows = 16;
328 setNumCols( 16 ); 347 numCols = 16;
329 minecount = 45; 348 minecount = 45;
330 cellsize = 14;
331 break; 349 break;
332 case 3: 350 case 3:
333 setNumRows( 18 ); 351 numCols = 18;
334 setNumCols( 18 ); 352 numRows = 18;
335 minecount = 66 ; 353 minecount = 66 ;
336 cellsize = 12;
337 break; 354 break;
338 } 355 }
339 nonminecount = numRows()*numCols() - minecount; 356 mines = new (Mine*)[numRows*numCols];
357 for ( i = 0; i < numCols*numRows; i++ )
358 mines[i] = new Mine( this );
359
360
361 nonminecount = numRows*numCols - minecount;
340 mineguess = minecount; 362 mineguess = minecount;
341 emit mineCount( mineguess ); 363 emit mineCount( mineguess );
342 Mine::paletteChange(); 364 Mine::paletteChange();
343 365
344 for ( y = 0; y < numRows(); y++ ) 366 if ( availableRect.isValid() )
345 setRowHeight( y, cellsize ); 367 setCellSize(findCellSize());
346 for ( x = 0; x < numCols(); x++ ) 368 // viewport()->setUpdatesEnabled( TRUE );
347 setColumnWidth( x, cellsize ); 369 //viewport()->repaint( TRUE );
348 for ( x = 0; x < numCols(); x++ ) 370 updateContents( 0, 0, numCols*cellSize, numRows*cellSize );
349 for ( y = 0; y < numRows(); y++ )
350 setItem( y, x, new Mine( this ) );
351
352 updateGeometry(); 371 updateGeometry();
353 viewport()->setUpdatesEnabled( TRUE ); 372}
354 viewport()->repaint( TRUE ); 373
374void MineField::drawContents( QPainter * p, int clipx, int clipy, int clipw, int cliph )
375{
376 int c1 = clipx / cellSize;
377 int c2 = ( clipx + clipw - 1 ) / cellSize;
378 int r1 = clipy / cellSize;
379 int r2 = ( clipy + cliph - 1 ) / cellSize;
380
381 for ( int c = c1; c <= c2 ; c++ ) {
382 for ( int r = r1; r <= r2 ; r++ ) {
383 int x = c * cellSize;
384 int y = r * cellSize;
385 Mine *m = mine( r, c );
386 if ( m )
387 m->paint( p, colorGroup(), QRect(x, y, cellSize, cellSize ) );
388 }
389 }
390}
391
392
393// Chicken and egg problem: We need to know how big the parent is
394// before we can decide how big to make the table.
395
396void MineField::setAvailableRect( const QRect &r )
397{
398 availableRect = r;
399 int newCellSize = findCellSize();
400 if ( newCellSize != cellSize ) {
401 viewport()->setUpdatesEnabled( FALSE );
402 setCellSize( newCellSize );
403 viewport()->setUpdatesEnabled( TRUE );
404 viewport()->repaint( TRUE );
405 }
406}
407
408int MineField::findCellSize()
409{
410 int w = availableRect.width() - 1;
411 int h = availableRect.height() - 1;
412 int cellsize;
413
414 cellsize = QMIN( w/numCols, h/numRows );
415 cellsize = QMIN( QMAX( cellsize, minGrid ), maxGrid );
416 return cellsize;
417}
418
419
420void MineField::setCellSize( int cellsize )
421{
422 cellSize = cellsize;
423
424 int w = availableRect.width();
425 int h = availableRect.height();
426
427 int w2 = cellsize*numCols;
428 int h2 = cellsize*numRows;
429
430 resizeContents( w2, h2 );
431
432 int b = 5;
433
434 setGeometry( availableRect.x() + (w-w2)/2, availableRect.y() + (h-h2)/2,
435 w2+b, h2+b );
436 // QMIN(w,w2+b), QMIN(h,h2+b) );
355} 437}
356 438
357 439
358void MineField::placeMines() 440void MineField::placeMines()
359{ 441{
360 int mines = minecount; 442 int mines = minecount;
361 while ( mines ) { 443 while ( mines ) {
362 int col = int((double(rand()) / double(RAND_MAX)) * numCols()); 444 int col = int((double(rand()) / double(RAND_MAX)) * numCols);
363 int row = int((double(rand()) / double(RAND_MAX)) * numRows()); 445 int row = int((double(rand()) / double(RAND_MAX)) * numRows);
364 446
365 Mine* mine = (Mine*)item( row, col ); 447 Mine* m = mine( row, col );
366 448
367 if ( mine && !mine->isMined() && mine->state() == Mine::Hidden ) { 449 if ( m && !m->isMined() && m->state() == Mine::Hidden ) {
368 mine->setMined( TRUE ); 450 m->setMined( TRUE );
369 mines--; 451 mines--;
370 } 452 }
371 } 453 }
372} 454}
373 455
374void MineField::paintFocus( QPainter*, const QRect& ) 456
457void MineField::updateCell( int r, int c )
375{ 458{
459 updateContents( c*cellSize, r*cellSize, cellSize, cellSize );
376} 460}
377 461
378void MineField::viewportMousePressEvent( QMouseEvent* e ) 462
463void MineField::contentsMousePressEvent( QMouseEvent* e )
379{ 464{
380 QTable::viewportMousePressEvent( e ); 465 int c = e->pos().x() / cellSize;
466 int r = e->pos().y() / cellSize;
467 if ( onBoard( r, c ) )
468 cellPressed( r, c );
469 else
470 currCol = currRow = -1;
381} 471}
382 472
383void MineField::viewportMouseReleaseEvent( QMouseEvent* e ) 473void MineField::contentsMouseReleaseEvent( QMouseEvent* e )
384{ 474{
385 QTable::viewportMouseReleaseEvent( e ); 475 int c = e->pos().x() / cellSize;
476 int r = e->pos().y() / cellSize;
477 if ( onBoard( r, c ) && c == currCol && r == currRow )
478 cellClicked( r, c );
479
480
386 if ( flagAction == FlagNext ) { 481 if ( flagAction == FlagNext ) {
387 flagAction = NoAction; 482 flagAction = NoAction;
388 } 483 }
389} 484}
390 485
486
487
488/*
489 state == Waiting means no "hold"
490
491
492*/
493void MineField::cellPressed( int row, int col )
494{
495 if ( state() == GameOver )
496 return;
497 currRow = row;
498 currCol = col;
499 if ( state() == Playing )
500 holdTimer->start( 150, TRUE );
501}
502
503void MineField::held()
504{
505 flagAction = FlagNext;
506 updateMine( currRow, currCol );
507 ignoreClick = TRUE;
508}
509
510
511
512
391void MineField::keyPressEvent( QKeyEvent* e ) 513void MineField::keyPressEvent( QKeyEvent* e )
392{ 514{
393#if defined(Q_WS_QWS) || defined(_WS_QWS_) 515#if defined(Q_WS_QWS) || defined(_WS_QWS_)
394 flagAction = ( e->key() == Key_Up ) ? FlagOn : NoAction; 516 flagAction = ( e->key() == Key_Up ) ? FlagOn : NoAction;
395#else 517#else
396 flagAction = ( ( e->state() & ShiftButton ) == ShiftButton ) ? FlagOn : NoAction; 518 flagAction = ( ( e->state() & ShiftButton ) == ShiftButton ) ? FlagOn : NoAction;
397#endif 519#endif
398} 520}
399 521
400void MineField::keyReleaseEvent( QKeyEvent* ) 522void MineField::keyReleaseEvent( QKeyEvent* )
401{ 523{
402 flagAction = NoAction; 524 flagAction = NoAction;
403} 525}
404 526
405int MineField::getHint( int row, int col ) 527int MineField::getHint( int row, int col )
406{ 528{
407 int hint = 0; 529 int hint = 0;
408 for ( int c = col-1; c <= col+1; c++ ) 530 for ( int c = col-1; c <= col+1; c++ )
409 for ( int r = row-1; r <= row+1; r++ ) { 531 for ( int r = row-1; r <= row+1; r++ ) {
410 Mine* mine = (Mine*)item( r, c ); 532 Mine* m = mine( r, c );
411 if ( mine && mine->isMined() ) 533 if ( m && m->isMined() )
412 hint++; 534 hint++;
413 } 535 }
414 536
415 return hint; 537 return hint;
416} 538}
417 539
418void MineField::setHint( Mine* mine ) 540void MineField::setHint( int row, int col )
419{ 541{
420 if ( !mine ) 542 Mine *m = mine( row, col );
543 if ( !m )
421 return; 544 return;
422 545
423 int row = mine->row();
424 int col = mine->col();
425 int hint = getHint( row, col ); 546 int hint = getHint( row, col );
426 547
427 if ( !hint ) { 548 if ( !hint ) {
428 for ( int c = col-1; c <= col+1; c++ ) 549 for ( int c = col-1; c <= col+1; c++ )
429 for ( int r = row-1; r <= row+1; r++ ) { 550 for ( int r = row-1; r <= row+1; r++ ) {
430 Mine* mine = (Mine*)item( r, c ); 551 Mine* m = mine( r, c );
431 if ( mine && mine->state() == Mine::Hidden ) { 552 if ( m && m->state() == Mine::Hidden ) {
432 mine->activate( TRUE ); 553 m->activate( TRUE );
433 nonminecount--; 554 nonminecount--;
434 setHint( mine ); 555 setHint( r, c );
435 updateCell( r, c ); 556 updateCell( r, c );
436 } 557 }
437 } 558 }
438 } 559 }
439 560
440 mine->setHint( hint ); 561 m->setHint( hint );
441 updateCell( row, col ); 562 updateCell( row, col );
442} 563}
443 564
444/* 565/*
445 state == Waiting means no "hold"
446
447
448*/
449void MineField::cellPressed( int row, int col )
450{
451 if ( state() == GameOver )
452 return;
453 currRow = row;
454 currCol = col;
455 if ( state() == Playing )
456 holdTimer->start( 150, TRUE );
457}
458
459void MineField::held()
460{
461 flagAction = FlagNext;
462 updateMine( currRow, currCol );
463 ignoreClick = TRUE;
464}
465
466/*
467 Only place mines after first click, since it is pointless to 566 Only place mines after first click, since it is pointless to
468 kill the player before the game has started. 567 kill the player before the game has started.
469*/ 568*/
470 569
471void MineField::cellClicked( int row, int col ) 570void MineField::cellClicked( int row, int col )
472{ 571{
473 if ( state() == GameOver ) 572 if ( state() == GameOver )
474 return; 573 return;
475 if ( state() == Waiting ) { 574 if ( state() == Waiting ) {
476 Mine* mine = (Mine*)item( row, col ); 575 Mine* m = mine( row, col );
477 if ( !mine ) 576 if ( !m )
478 return; 577 return;
479 mine->setState( Mine::Empty ); 578 m->setState( Mine::Empty );
480 nonminecount--; 579 nonminecount--;
481 placeMines(); 580 placeMines();
482 setState( Playing ); 581 setState( Playing );
483 emit gameStarted(); 582 emit gameStarted();
484 updateMine( row, col ); 583 updateMine( row, col );
485 } else { // state() == Playing 584 } else { // state() == Playing
486 holdTimer->stop(); 585 holdTimer->stop();
487 if ( ignoreClick ) 586 if ( ignoreClick )
488 ignoreClick = FALSE; 587 ignoreClick = FALSE;
489 else 588 else
490 updateMine( row, col ); 589 updateMine( row, col );
491 } 590 }
492} 591}
493 592
494void MineField::updateMine( int row, int col ) 593void MineField::updateMine( int row, int col )
495{ 594{
496 Mine* mine = (Mine*)item( row, col ); 595 Mine* m = mine( row, col );
497 if ( !mine ) 596 if ( !m )
498 return; 597 return;
499 598
500 bool wasFlagged = mine->state() == Mine::Flagged; 599 bool wasFlagged = m->state() == Mine::Flagged;
501 bool wasEmpty = mine->state() == Mine::Empty; 600 bool wasEmpty = m->state() == Mine::Empty;
502 601
503 mine->activate( flagAction == NoAction ); 602 m->activate( flagAction == NoAction );
504 603
505 if ( mine->state() == Mine::Exploded ) { 604 if ( m->state() == Mine::Exploded ) {
506 emit gameOver( FALSE ); 605 emit gameOver( FALSE );
507 setState( GameOver ); 606 setState( GameOver );
508 return; 607 return;
509 } else if ( mine->state() == Mine::Empty ) { 608 } else if ( m->state() == Mine::Empty ) {
510 setHint( mine ); 609 setHint( row, col );
511 if ( !wasEmpty ) 610 if ( !wasEmpty )
512 nonminecount--; 611 nonminecount--;
513 } 612 }
514 613
515 if ( flagAction != NoAction ) { 614 if ( flagAction != NoAction ) {
516 if ( mine->state() == Mine::Flagged ) { 615 if ( m->state() == Mine::Flagged ) {
517 --mineguess; 616 --mineguess;
518 emit mineCount( mineguess ); 617 emit mineCount( mineguess );
519 if ( mine->isMined() ) 618 if ( m->isMined() )
520 --minecount; 619 --minecount;
521 } else if ( wasFlagged ) { 620 } else if ( wasFlagged ) {
522 ++mineguess; 621 ++mineguess;
523 emit mineCount( mineguess ); 622 emit mineCount( mineguess );
524 if ( mine->isMined() ) 623 if ( m->isMined() )
525 ++minecount; 624 ++minecount;
526 } 625 }
527 } 626 }
528 627
529 updateCell( row, col ); 628 updateCell( row, col );
530 629
531 if ( !minecount && !mineguess || !nonminecount ) { 630 if ( !minecount && !mineguess || !nonminecount ) {
532 emit gameOver( TRUE ); 631 emit gameOver( TRUE );
533 setState( GameOver ); 632 setState( GameOver );
534 } 633 }
535} 634}
536 635
537void MineField::showMines() 636void MineField::showMines()
538{ 637{
539 for ( int c = 0; c < numCols(); c++ ) 638 for ( int c = 0; c < numCols; c++ )
540 for ( int r = 0; r < numRows(); r++ ) { 639 for ( int r = 0; r < numRows; r++ ) {
541 Mine* mine = (Mine*)item( r, c ); 640 Mine* m = mine( r, c );
542 if ( !mine ) 641 if ( !m )
543 continue; 642 continue;
544 if ( mine->isMined() && mine->state() == Mine::Hidden ) 643 if ( m->isMined() && m->state() == Mine::Hidden )
545 mine->setState( Mine::Mined ); 644 m->setState( Mine::Mined );
546 if ( !mine->isMined() && mine->state() == Mine::Flagged ) 645 if ( !m->isMined() && m->state() == Mine::Flagged )
547 mine->setState( Mine::Wrong ); 646 m->setState( Mine::Wrong );
548 647
549 updateCell( r, c ); 648 updateCell( r, c );
550 } 649 }
551} 650}
552 651
553void MineField::paletteChange( const QPalette &o ) 652void MineField::paletteChange( const QPalette &o )
554{ 653{
555 Mine::paletteChange(); 654 Mine::paletteChange();
556 QTable::paletteChange( o ); 655 QScrollView::paletteChange( o );
557} 656}
558 657
559void MineField::writeConfig(Config& cfg) const 658void MineField::writeConfig(Config& cfg) const
560{ 659{
561 cfg.setGroup("Field"); 660 cfg.setGroup("Field");
562 cfg.writeEntry("Level",lev); 661 cfg.writeEntry("Level",lev);
563 QString grid=""; 662 QString grid="";
564 if ( stat == Playing ) { 663 if ( stat == Playing ) {
565 for ( int x = 0; x < numCols(); x++ ) 664 for ( int x = 0; x < numCols; x++ )
566 for ( int y = 0; y < numRows(); y++ ) { 665 for ( int y = 0; y < numRows; y++ ) {
567 char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat 666 char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat
568 Mine* mine = (Mine*)item( y, x ); 667 const Mine* m = mine( y, x );
569 int st = (int)mine->state(); if ( mine->isMined() ) st+=5; 668 int st = (int)m->state(); if ( m->isMined() ) st+=5;
570 grid += code + st; 669 grid += code + st;
571 } 670 }
572 } 671 }
573 cfg.writeEntry("Grid",grid); 672 cfg.writeEntry("Grid",grid);
574} 673}
575 674
576void MineField::readConfig(Config& cfg) 675void MineField::readConfig(Config& cfg)
577{ 676{
578 cfg.setGroup("Field"); 677 cfg.setGroup("Field");
579 lev = cfg.readNumEntry("Level",1); 678 lev = cfg.readNumEntry("Level",1);
580 setup(lev); 679 setup(lev);
581 flagAction = NoAction; 680 flagAction = NoAction;
582 ignoreClick = FALSE; 681 ignoreClick = FALSE;
583 currRow = currCol = 0; 682 currRow = currCol = 0;
584 QString grid = cfg.readEntry("Grid"); 683 QString grid = cfg.readEntry("Grid");
585 if ( !grid.isEmpty() ) { 684 if ( !grid.isEmpty() ) {
586 int i=0; 685 int i=0;
587 minecount=0; 686 minecount=0;
588 mineguess=0; 687 mineguess=0;
589 for ( int x = 0; x < numCols(); x++ ) { 688 for ( int x = 0; x < numCols; x++ ) {
590 for ( int y = 0; y < numRows(); y++ ) { 689 for ( int y = 0; y < numRows; y++ ) {
591 char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat 690 char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat
592 int st = (char)(QChar)grid[i++]-code; 691 int st = (char)(QChar)grid[i++]-code;
593 Mine* mine = (Mine*)item( y, x ); 692 Mine* m = mine( y, x );
594 if ( st >= 5 ) { 693 if ( st >= 5 ) {
595 st-=5; 694 st-=5;
596 mine->setMined(TRUE); 695 m->setMined(TRUE);
597 minecount++; 696 minecount++;
598 mineguess++; 697 mineguess++;
599 } 698 }
600 mine->setState((Mine::MineState)st); 699 m->setState((Mine::MineState)st);
601 switch ( mine->state() ) { 700 switch ( m->state() ) {
602 case Mine::Flagged: 701 case Mine::Flagged:
603 if (mine->isMined()) 702 if (m->isMined())
604 minecount--; 703 minecount--;
605 mineguess--; 704 mineguess--;
606 break; 705 break;
607 case Mine::Empty: 706 case Mine::Empty:
608 --nonminecount; 707 --nonminecount;
708 break;
709 default:
710 break;
609 } 711 }
610 } 712 }
611 } 713 }
612 for ( int x = 0; x < numCols(); x++ ) { 714 for ( int x = 0; x < numCols; x++ ) {
613 for ( int y = 0; y < numRows(); y++ ) { 715 for ( int y = 0; y < numRows; y++ ) {
614 Mine* mine = (Mine*)item( y, x ); 716 Mine* m = mine( y, x );
615 if ( mine->state() == Mine::Empty ) 717 if ( m->state() == Mine::Empty )
616 mine->setHint(getHint(y,x)); 718 m->setHint(getHint(y,x));
617 } 719 }
618 } 720 }
619 } 721 }
620 setState( Playing ); 722 setState( Playing );
621 emit mineCount( mineguess ); 723 emit mineCount( mineguess );
622} 724}
623 725