summaryrefslogtreecommitdiff
path: root/noncore/games/minesweep/minefield.cpp
Side-by-side diff
Diffstat (limited to 'noncore/games/minesweep/minefield.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/minesweep/minefield.cpp144
1 files changed, 85 insertions, 59 deletions
diff --git a/noncore/games/minesweep/minefield.cpp b/noncore/games/minesweep/minefield.cpp
index 04cfb97..1790110 100644
--- a/noncore/games/minesweep/minefield.cpp
+++ b/noncore/games/minesweep/minefield.cpp
@@ -1,34 +1,35 @@
/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include "minefield.h"
-#include <qpe/config.h>
+#include <qtopia/config.h>
+#include <qtopia/qpeapplication.h>
#include <qpainter.h>
#include <qdrawutil.h>
#include <qpixmap.h>
#include <qimage.h>
#include <qtimer.h>
#include <stdlib.h>
static const char *pix_flag[]={
"13 13 3 1",
"# c #000000",
@@ -60,25 +61,25 @@ static const char *pix_mine[]={
"..##aa#####..",
"..##aa#####..",
"#############",
"..#########..",
"..#########..",
"...#######...",
"..#.#####.#..",
"......#......",
"......#......"};
static const int maxGrid = 28;
-static const int minGrid = 9;
+static const int minGrid = 12;
class Mine : public Qt
{
public:
enum MineState {
Hidden = 0,
Empty,
Mined,
Flagged,
#ifdef MARK_UNSURE
@@ -175,46 +176,54 @@ void Mine::paletteChange()
delete unknownField;
unknownField = 0;
delete mine_pix;
mine_pix = 0;
delete flag_pix;
flag_pix = 0;
}
void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr )
{
int x = cr.x();
int y = cr.y();
- if ( !knownField ) {
+ if ( !knownField || knownField->width() != cr.width() ||
+ knownField->height() != cr.height() ) {
+ delete knownField;
knownField = new QPixmap( cr.width(), cr.height() );
QPainter pp( knownField );
QBrush br( cg.button().dark(115) );
- qDrawWinButton( &pp, cr, cg, TRUE, &br );
+ qDrawWinButton( &pp, QRect( 0, 0, cr.width(), cr.height() ), cg, TRUE, &br );
}
const int pmmarg=cr.width()/5;
- if ( !unknownField ) {
+ if ( !unknownField || unknownField->width() != cr.width() ||
+ unknownField->height() != cr.height() ) {
+ delete unknownField;
unknownField = new QPixmap( cr.width(), cr.height() );
QPainter pp( unknownField );
QBrush br( cg.button() );
- qDrawWinButton( &pp, cr, cg, FALSE, &br );
+ qDrawWinButton( &pp, QRect( 0, 0, cr.width(), cr.height() ), cg, FALSE, &br );
}
- if ( !flag_pix ) {
+ if ( !flag_pix || flag_pix->width() != cr.width()-pmmarg*2 ||
+ flag_pix->height() != cr.height()-pmmarg*2 ) {
+ delete flag_pix;
flag_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 );
flag_pix->convertFromImage( QImage(pix_flag).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) );
}
- if ( !mine_pix ) {
+ if ( !mine_pix || mine_pix->width() != cr.width()-pmmarg*2 ||
+ mine_pix->height() != cr.height()-pmmarg*2 ) {
+ delete mine_pix;
mine_pix = new QPixmap( cr.width()-pmmarg*2, cr.height()-pmmarg*2 );
mine_pix->convertFromImage( QImage(pix_mine).smoothScale(cr.width()-pmmarg*2, cr.height()-pmmarg*2) );
}
p->save();
switch(st) {
case Hidden:
p->drawPixmap( x, y, *unknownField );
break;
case Empty:
p->drawPixmap( x, y, *knownField );
@@ -274,175 +283,179 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr )
}
p->restore();
}
/*
MineField implementation
*/
MineField::MineField( QWidget* parent, const char* name )
: QScrollView( parent, name )
{
+ viewport()->setBackgroundMode( NoBackground );
setState( GameOver );
setSizePolicy( QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum ) );
-
+
setFocusPolicy( QWidget::NoFocus );
holdTimer = new QTimer( this );
connect( holdTimer, SIGNAL( timeout() ), this, SLOT( held() ) );
flagAction = NoAction;
ignoreClick = FALSE;
currRow = currCol = -1;
minecount=0;
mineguess=0;
nonminecount=0;
cellSize = -1;
- mines = 0;
+
+ numRows = numCols = 0;
+ mines = NULL;
}
MineField::~MineField()
{
- int i;
- if ( mines )
- {
- for ( i = 0; i < numCols*numRows; i++ )
- {
- delete mines[i];
- }
- delete[] mines;
- }
+ for ( int i = 0; i < numCols*numRows; i++ )
+ delete mines[i];
+ delete[] mines;
}
void MineField::setState( State st )
{
stat = st;
}
void MineField::setup( int level )
{
lev = level;
setState( Waiting );
//viewport()->setUpdatesEnabled( FALSE );
int i;
- if ( mines )
- {
- for ( i = 0; i < numCols*numRows; i++ )
- {
- delete mines[i];
- }
- delete[] mines;
- }
+ for ( i = 0; i < numCols*numRows; i++ )
+ delete mines[i];
+ delete[] mines;
switch( lev ) {
case 1:
numRows = 9 ;
numCols = 9 ;
minecount = 12;
break;
case 2:
- numRows = 16;
- numCols = 16;
- minecount = 45;
+ numRows = 13;
+ numCols = 13;
+ minecount = 33;
break;
case 3:
numCols = 18;
numRows = 18;
minecount = 66 ;
break;
}
- mines = new Mine*[numRows*numCols];
+ mines = new Mine* [numRows*numCols];
for ( i = 0; i < numCols*numRows; i++ )
mines[i] = new Mine( this );
-
+
nonminecount = numRows*numCols - minecount;
mineguess = minecount;
emit mineCount( mineguess );
Mine::paletteChange();
if ( availableRect.isValid() )
setCellSize(findCellSize());
// viewport()->setUpdatesEnabled( TRUE );
//viewport()->repaint( TRUE );
updateContents( 0, 0, numCols*cellSize, numRows*cellSize );
updateGeometry();
}
-void MineField::drawContents( QPainter * p, int clipx, int clipy, int clipw, int cliph )
+void MineField::drawContents( QPainter * p, int clipx, int clipy, int clipw, int cliph )
{
int c1 = clipx / cellSize;
int c2 = ( clipx + clipw - 1 ) / cellSize;
int r1 = clipy / cellSize;
int r2 = ( clipy + cliph - 1 ) / cellSize;
-
+
for ( int c = c1; c <= c2 ; c++ ) {
for ( int r = r1; r <= r2 ; r++ ) {
int x = c * cellSize;
int y = r * cellSize;
Mine *m = mine( r, c );
if ( m )
m->paint( p, colorGroup(), QRect(x, y, cellSize, cellSize ) );
}
}
}
// Chicken and egg problem: We need to know how big the parent is
// before we can decide how big to make the table.
void MineField::setAvailableRect( const QRect &r )
{
availableRect = r;
int newCellSize = findCellSize();
- if ( newCellSize != cellSize ) {
+
+
+ if ( newCellSize == cellSize ) {
+ setCellSize( cellSize );
+ } else {
viewport()->setUpdatesEnabled( FALSE );
setCellSize( newCellSize );
viewport()->setUpdatesEnabled( TRUE );
viewport()->repaint( TRUE );
}
}
int MineField::findCellSize()
{
- int w = availableRect.width() - 1;
- int h = availableRect.height() - 1;
+ int w = availableRect.width() - 2;
+ int h = availableRect.height() - 2;
int cellsize;
-
+
cellsize = QMIN( w/numCols, h/numRows );
cellsize = QMIN( QMAX( cellsize, minGrid ), maxGrid );
return cellsize;
}
void MineField::setCellSize( int cellsize )
{
- cellSize = cellsize;
-
- int w = availableRect.width();
- int h = availableRect.height();
-
+ int b = 2;
+
int w2 = cellsize*numCols;
int h2 = cellsize*numRows;
-
- resizeContents( w2, h2 );
-
- int b = 5;
-
- setGeometry( availableRect.x() + (w-w2)/2, availableRect.y() + (h-h2)/2,
- w2+b, h2+b );
-// QMIN(w,w2+b), QMIN(h,h2+b) );
+
+ int w = QMIN( availableRect.width(), w2+b );
+ int h = QMIN( availableRect.height(), h2+b );
+
+ //
+ // Don't rely on the change in cellsize to force a resize,
+ // as it's possible to have the same size cells when going
+ // from a large play area to a small one.
+ //
+ resizeContents(w2, h2);
+
+ if ( availableRect.height() < h2 &&
+ availableRect.width() - w > style().scrollBarExtent().width() ) {
+ w += style().scrollBarExtent().width();
+ }
+
+ setGeometry( availableRect.x() + (availableRect.width()-w)/2,
+ availableRect.y() + (availableRect.height()-h)/2, w, h );
+ cellSize = cellsize;
}
void MineField::placeMines()
{
int mines = minecount;
while ( mines ) {
int col = int((double(rand()) / double(RAND_MAX)) * numCols);
int row = int((double(rand()) / double(RAND_MAX)) * numRows);
Mine* m = mine( row, col );
@@ -604,28 +617,32 @@ void MineField::updateMine( int row, int col )
if ( m->state() == Mine::Exploded ) {
emit gameOver( FALSE );
setState( GameOver );
return;
} else if ( m->state() == Mine::Empty ) {
setHint( row, col );
if ( !wasEmpty )
nonminecount--;
}
if ( flagAction != NoAction ) {
if ( m->state() == Mine::Flagged ) {
- --mineguess;
- emit mineCount( mineguess );
- if ( m->isMined() )
- --minecount;
+ if (mineguess > 0) {
+ --mineguess;
+ emit mineCount( mineguess );
+ if ( m->isMined() )
+ --minecount;
+ } else {
+ m->setState(Mine::Hidden);
+ }
} else if ( wasFlagged ) {
++mineguess;
emit mineCount( mineguess );
if ( m->isMined() )
++minecount;
}
}
updateCell( row, col );
if ( !minecount && !mineguess || !nonminecount ) {
emit gameOver( TRUE );
@@ -672,29 +689,30 @@ void MineField::writeConfig(Config& cfg) const
cfg.writeEntry("Grid",grid);
}
void MineField::readConfig(Config& cfg)
{
cfg.setGroup("Field");
lev = cfg.readNumEntry("Level",1);
setup(lev);
flagAction = NoAction;
ignoreClick = FALSE;
currRow = currCol = 0;
QString grid = cfg.readEntry("Grid");
+ int x;
if ( !grid.isEmpty() ) {
int i=0;
minecount=0;
mineguess=0;
- for ( int x = 0; x < numCols; x++ ) {
+ for ( x = 0; x < numCols; x++ ) {
for ( int y = 0; y < numRows; y++ ) {
char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat
int st = (char)(QChar)grid[i++]-code;
Mine* m = mine( y, x );
if ( st >= 5 ) {
st-=5;
m->setMined(TRUE);
minecount++;
mineguess++;
}
m->setState((Mine::MineState)st);
switch ( m->state() ) {
@@ -702,24 +720,32 @@ void MineField::readConfig(Config& cfg)
if (m->isMined())
minecount--;
mineguess--;
break;
case Mine::Empty:
--nonminecount;
break;
default:
break;
}
}
}
- for ( int x = 0; x < numCols; x++ ) {
+ for ( x = 0; x < numCols; x++ ) {
for ( int y = 0; y < numRows; y++ ) {
Mine* m = mine( y, x );
if ( m->state() == Mine::Empty )
m->setHint(getHint(y,x));
}
}
}
setState( Playing );
emit mineCount( mineguess );
}
+QSize MineField::sizeHint() const
+{
+ if ( qApp->desktop()->width() >= 240 )
+ return QSize(200,200);
+ else
+ return QSize(160, 160);
+}
+