summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--noncore/games/minesweep/minefield.cpp400
1 files changed, 251 insertions, 149 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
@@ -46,102 +46,109 @@ static const char *pix_flag[]={
".....#.......",
"...#####.....",
"..#######....",
"............."};
static const char *pix_mine[]={
"13 13 3 1",
"# c #000000",
". c None",
"a c #ffffff",
"......#......",
"......#......",
"..#.#####.#..",
"...#######...",
"..##aa#####..",
"..##aa#####..",
"#############",
"..#########..",
"..#########..",
"...#######...",
"..#.#####.#..",
"......#......",
"......#......"};
-class Mine : public QTableItem
+
+static const int maxGrid = 28;
+static const int minGrid = 9;
+
+
+
+class Mine : public Qt
{
public:
enum MineState {
Hidden = 0,
Empty,
Mined,
Flagged,
#ifdef MARK_UNSURE
Unsure,
#endif
Exploded,
Wrong
};
- Mine( QTable* );
- void paint( QPainter * p, const QColorGroup & cg, const QRect & cr, bool selected );
- EditType editType() const { return Never; }
- QSize sizeHint() const { return QSize( 12, 12 ); }
+ Mine( MineField* );
+ void paint( QPainter * p, const QColorGroup & cg, const QRect & cr );
+
+ QSize sizeHint() const { return QSize( maxGrid, maxGrid ); }
void activate( bool sure = TRUE );
void setHint( int );
void setState( MineState );
MineState state() const { return st; }
bool isMined() const { return mined; }
void setMined( bool m ) { mined = m; }
static void paletteChange();
private:
bool mined;
int hint;
MineState st;
+ MineField *field;
static QPixmap* knownField;
static QPixmap* unknownField;
static QPixmap* flag_pix;
static QPixmap* mine_pix;
};
QPixmap* Mine::knownField = 0;
QPixmap* Mine::unknownField = 0;
QPixmap* Mine::flag_pix = 0;
QPixmap* Mine::mine_pix = 0;
-Mine::Mine( QTable *t )
-: QTableItem( t, Never, QString::null )
+Mine::Mine( MineField *f )
{
mined = FALSE;
st = Hidden;
hint = 0;
+ field = f;
}
void Mine::activate( bool sure )
{
if ( !sure ) {
switch ( st ) {
case Hidden:
setState( Flagged );
break;
case Flagged:
#ifdef MARK_UNSURE
setState( Unsure );
break;
case Unsure:
#endif
setState( Hidden );
default:
break;
}
} else if ( st == Flagged ) {
return;
} else {
if ( mined ) {
setState( Exploded );
@@ -152,472 +159,567 @@ void Mine::activate( bool sure )
}
void Mine::setState( MineState s )
{
st = s;
}
void Mine::setHint( int h )
{
hint = h;
}
void Mine::paletteChange()
{
delete knownField;
knownField = 0;
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, bool )
+void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr )
{
+ int x = cr.x();
+ int y = cr.y();
if ( !knownField ) {
knownField = new QPixmap( cr.width(), cr.height() );
QPainter pp( knownField );
QBrush br( cg.button().dark(115) );
- qDrawWinButton( &pp, QRect(0,0,cr.width(), cr.height())/*cr*/, cg, TRUE, &br );
+ qDrawWinButton( &pp, cr, cg, TRUE, &br );
}
const int pmmarg=cr.width()/5;
if ( !unknownField ) {
unknownField = new QPixmap( cr.width(), cr.height() );
QPainter pp( unknownField );
QBrush br( cg.button() );
- qDrawWinButton( &pp, QRect(0,0,cr.width(), cr.height())/*cr*/, cg, FALSE, &br );
+ qDrawWinButton( &pp, cr, cg, FALSE, &br );
}
if ( !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 ) {
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( 0, 0, *unknownField );
+ p->drawPixmap( x, y, *unknownField );
break;
case Empty:
- p->drawPixmap( 0, 0, *knownField );
+ p->drawPixmap( x, y, *knownField );
if ( hint > 0 ) {
switch( hint ) {
case 1:
p->setPen( blue );
break;
case 2:
- p->setPen( green );
+ p->setPen( green.dark() );
+ break;
case 3:
p->setPen( red );
break;
- default:
+ case 4:
+ p->setPen( darkYellow.dark() );
+ break;
+ case 5:
p->setPen( darkMagenta );
break;
+ case 6:
+ p->setPen( darkRed );
+ break;
+ default:
+ p->setPen( black );
+ break;
}
- p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, QString().setNum( hint ) );
+ p->drawText( cr, AlignHCenter | AlignVCenter, QString::number( hint ) );
}
break;
case Mined:
- p->drawPixmap( 0, 0, *knownField );
- p->drawPixmap( pmmarg, pmmarg, *mine_pix );
+ p->drawPixmap( x, y, *knownField );
+ p->drawPixmap( x+pmmarg, y+pmmarg, *mine_pix );
break;
case Exploded:
- p->drawPixmap( 0, 0, *knownField );
- p->drawPixmap( pmmarg, pmmarg, *mine_pix );
+ p->drawPixmap( x, y, *knownField );
+ p->drawPixmap( x+pmmarg, y+pmmarg, *mine_pix );
p->setPen( red );
- p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, "X" );
+ p->drawText( cr, AlignHCenter | AlignVCenter, "X" );
break;
case Flagged:
- p->drawPixmap( 0, 0, *unknownField );
- p->drawPixmap( pmmarg, pmmarg, *flag_pix );
+ p->drawPixmap( x, y, *unknownField );
+ p->drawPixmap( x+pmmarg, y+pmmarg, *flag_pix );
break;
#ifdef MARK_UNSURE
case Unsure:
- p->drawPixmap( 0, 0, *unknownField );
- p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, "?" );
+ p->drawPixmap( x, y, *unknownField );
+ p->drawText( cr, AlignHCenter | AlignVCenter, "?" );
break;
#endif
case Wrong:
- p->drawPixmap( 0, 0, *unknownField );
- p->drawPixmap( pmmarg, pmmarg, *flag_pix );
+ p->drawPixmap( x, y, *unknownField );
+ p->drawPixmap( x+pmmarg, y+pmmarg, *flag_pix );
p->setPen( red );
- p->drawText( QRect( 0, 0, cr.width(), cr.height() ), AlignHCenter | AlignVCenter, "X" );
+ p->drawText( cr, AlignHCenter | AlignVCenter, "X" );
break;
}
p->restore();
}
/*
MineField implementation
*/
MineField::MineField( QWidget* parent, const char* name )
-: QTable( parent, name )
+: QScrollView( parent, name )
{
setState( GameOver );
- setShowGrid( FALSE );
- horizontalHeader()->hide();
- verticalHeader()->hide();
- setTopMargin( 0 );
- setLeftMargin( 0 );
setSizePolicy( QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum ) );
- setSelectionMode( QTable::NoSelection );
setFocusPolicy( QWidget::NoFocus );
- setCurrentCell( -1, -1 );
-
- connect( this, SIGNAL( pressed( int, int, int, const QPoint& ) ), this, SLOT( cellPressed( int, int ) ) );
- connect( this, SIGNAL( clicked( int, int, int, const QPoint& ) ), this, SLOT( cellClicked( int, int ) ) );
-
holdTimer = new QTimer( this );
connect( holdTimer, SIGNAL( timeout() ), this, SLOT( held() ) );
flagAction = NoAction;
ignoreClick = FALSE;
- currRow = currCol = 0;
+ currRow = currCol = -1;
minecount=0;
mineguess=0;
nonminecount=0;
+ cellSize = -1;
+ mines = 0;
}
MineField::~MineField()
{
+ int i;
+ if ( mines )
+ {
+ for ( 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 cellsize;
+ //viewport()->setUpdatesEnabled( FALSE );
- int x;
- int y;
- for ( x = 0; x < numCols(); x++ )
- for ( y = 0; y < numRows(); y++ )
- clearCell( y, x );
+ int i;
+ if ( mines )
+ {
+ for ( i = 0; i < numCols*numRows; i++ )
+ {
+ delete mines[i];
+ }
+ delete[] mines;
+ }
switch( lev ) {
case 1:
- setNumRows( 9 );
- setNumCols( 9 );
+ numRows = 9 ;
+ numCols = 9 ;
minecount = 12;
- cellsize = 21;
break;
case 2:
- setNumRows( 16 );
- setNumCols( 16 );
+ numRows = 16;
+ numCols = 16;
minecount = 45;
- cellsize = 14;
break;
case 3:
- setNumRows( 18 );
- setNumCols( 18 );
+ numCols = 18;
+ numRows = 18;
minecount = 66 ;
- cellsize = 12;
break;
}
- nonminecount = numRows()*numCols() - minecount;
+ 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();
- for ( y = 0; y < numRows(); y++ )
- setRowHeight( y, cellsize );
- for ( x = 0; x < numCols(); x++ )
- setColumnWidth( x, cellsize );
- for ( x = 0; x < numCols(); x++ )
- for ( y = 0; y < numRows(); y++ )
- setItem( y, x, new Mine( this ) );
-
+ 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 )
+{
+ 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 ) {
+ 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 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 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) );
+}
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());
+ int col = int((double(rand()) / double(RAND_MAX)) * numCols);
+ int row = int((double(rand()) / double(RAND_MAX)) * numRows);
- Mine* mine = (Mine*)item( row, col );
+ Mine* m = mine( row, col );
- if ( mine && !mine->isMined() && mine->state() == Mine::Hidden ) {
- mine->setMined( TRUE );
+ if ( m && !m->isMined() && m->state() == Mine::Hidden ) {
+ m->setMined( TRUE );
mines--;
}
}
}
-void MineField::paintFocus( QPainter*, const QRect& )
+
+void MineField::updateCell( int r, int c )
{
+ updateContents( c*cellSize, r*cellSize, cellSize, cellSize );
}
-void MineField::viewportMousePressEvent( QMouseEvent* e )
+
+void MineField::contentsMousePressEvent( QMouseEvent* e )
{
- QTable::viewportMousePressEvent( e );
+ int c = e->pos().x() / cellSize;
+ int r = e->pos().y() / cellSize;
+ if ( onBoard( r, c ) )
+ cellPressed( r, c );
+ else
+ currCol = currRow = -1;
}
-void MineField::viewportMouseReleaseEvent( QMouseEvent* e )
+void MineField::contentsMouseReleaseEvent( QMouseEvent* e )
{
- QTable::viewportMouseReleaseEvent( e );
+ int c = e->pos().x() / cellSize;
+ int r = e->pos().y() / cellSize;
+ if ( onBoard( r, c ) && c == currCol && r == currRow )
+ cellClicked( r, c );
+
+
if ( flagAction == FlagNext ) {
flagAction = NoAction;
}
}
+
+
+/*
+ state == Waiting means no "hold"
+
+
+*/
+void MineField::cellPressed( int row, int col )
+{
+ if ( state() == GameOver )
+ return;
+ currRow = row;
+ currCol = col;
+ if ( state() == Playing )
+ holdTimer->start( 150, TRUE );
+}
+
+void MineField::held()
+{
+ flagAction = FlagNext;
+ updateMine( currRow, currCol );
+ ignoreClick = TRUE;
+}
+
+
+
+
void MineField::keyPressEvent( QKeyEvent* e )
{
#if defined(Q_WS_QWS) || defined(_WS_QWS_)
flagAction = ( e->key() == Key_Up ) ? FlagOn : NoAction;
#else
flagAction = ( ( e->state() & ShiftButton ) == ShiftButton ) ? FlagOn : NoAction;
#endif
}
void MineField::keyReleaseEvent( QKeyEvent* )
{
flagAction = NoAction;
}
int MineField::getHint( int row, int col )
{
int hint = 0;
for ( int c = col-1; c <= col+1; c++ )
for ( int r = row-1; r <= row+1; r++ ) {
- Mine* mine = (Mine*)item( r, c );
- if ( mine && mine->isMined() )
+ Mine* m = mine( r, c );
+ if ( m && m->isMined() )
hint++;
}
return hint;
}
-void MineField::setHint( Mine* mine )
+void MineField::setHint( int row, int col )
{
- if ( !mine )
+ Mine *m = mine( row, col );
+ if ( !m )
return;
- int row = mine->row();
- int col = mine->col();
int hint = getHint( row, col );
if ( !hint ) {
for ( int c = col-1; c <= col+1; c++ )
for ( int r = row-1; r <= row+1; r++ ) {
- Mine* mine = (Mine*)item( r, c );
- if ( mine && mine->state() == Mine::Hidden ) {
- mine->activate( TRUE );
+ Mine* m = mine( r, c );
+ if ( m && m->state() == Mine::Hidden ) {
+ m->activate( TRUE );
nonminecount--;
- setHint( mine );
+ setHint( r, c );
updateCell( r, c );
}
}
}
- mine->setHint( hint );
+ m->setHint( hint );
updateCell( row, col );
}
/*
- state == Waiting means no "hold"
-
-
-*/
-void MineField::cellPressed( int row, int col )
-{
- if ( state() == GameOver )
- return;
- currRow = row;
- currCol = col;
- if ( state() == Playing )
- holdTimer->start( 150, TRUE );
-}
-
-void MineField::held()
-{
- flagAction = FlagNext;
- updateMine( currRow, currCol );
- ignoreClick = TRUE;
-}
-
-/*
Only place mines after first click, since it is pointless to
kill the player before the game has started.
*/
void MineField::cellClicked( int row, int col )
{
if ( state() == GameOver )
return;
if ( state() == Waiting ) {
- Mine* mine = (Mine*)item( row, col );
- if ( !mine )
+ Mine* m = mine( row, col );
+ if ( !m )
return;
- mine->setState( Mine::Empty );
+ m->setState( Mine::Empty );
nonminecount--;
placeMines();
setState( Playing );
emit gameStarted();
updateMine( row, col );
} else { // state() == Playing
holdTimer->stop();
if ( ignoreClick )
ignoreClick = FALSE;
else
updateMine( row, col );
}
}
void MineField::updateMine( int row, int col )
{
- Mine* mine = (Mine*)item( row, col );
- if ( !mine )
+ Mine* m = mine( row, col );
+ if ( !m )
return;
- bool wasFlagged = mine->state() == Mine::Flagged;
- bool wasEmpty = mine->state() == Mine::Empty;
+ bool wasFlagged = m->state() == Mine::Flagged;
+ bool wasEmpty = m->state() == Mine::Empty;
- mine->activate( flagAction == NoAction );
+ m->activate( flagAction == NoAction );
- if ( mine->state() == Mine::Exploded ) {
+ if ( m->state() == Mine::Exploded ) {
emit gameOver( FALSE );
setState( GameOver );
return;
- } else if ( mine->state() == Mine::Empty ) {
- setHint( mine );
+ } else if ( m->state() == Mine::Empty ) {
+ setHint( row, col );
if ( !wasEmpty )
nonminecount--;
}
if ( flagAction != NoAction ) {
- if ( mine->state() == Mine::Flagged ) {
+ if ( m->state() == Mine::Flagged ) {
--mineguess;
emit mineCount( mineguess );
- if ( mine->isMined() )
+ if ( m->isMined() )
--minecount;
} else if ( wasFlagged ) {
++mineguess;
emit mineCount( mineguess );
- if ( mine->isMined() )
+ if ( m->isMined() )
++minecount;
}
}
updateCell( row, col );
if ( !minecount && !mineguess || !nonminecount ) {
emit gameOver( TRUE );
setState( GameOver );
}
}
void MineField::showMines()
{
- for ( int c = 0; c < numCols(); c++ )
- for ( int r = 0; r < numRows(); r++ ) {
- Mine* mine = (Mine*)item( r, c );
- if ( !mine )
+ for ( int c = 0; c < numCols; c++ )
+ for ( int r = 0; r < numRows; r++ ) {
+ Mine* m = mine( r, c );
+ if ( !m )
continue;
- if ( mine->isMined() && mine->state() == Mine::Hidden )
- mine->setState( Mine::Mined );
- if ( !mine->isMined() && mine->state() == Mine::Flagged )
- mine->setState( Mine::Wrong );
+ if ( m->isMined() && m->state() == Mine::Hidden )
+ m->setState( Mine::Mined );
+ if ( !m->isMined() && m->state() == Mine::Flagged )
+ m->setState( Mine::Wrong );
updateCell( r, c );
}
}
void MineField::paletteChange( const QPalette &o )
{
Mine::paletteChange();
- QTable::paletteChange( o );
+ QScrollView::paletteChange( o );
}
void MineField::writeConfig(Config& cfg) const
{
cfg.setGroup("Field");
cfg.writeEntry("Level",lev);
QString grid="";
if ( stat == Playing ) {
- for ( int x = 0; x < numCols(); x++ )
- for ( int y = 0; y < numRows(); y++ ) {
+ for ( int 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
- Mine* mine = (Mine*)item( y, x );
- int st = (int)mine->state(); if ( mine->isMined() ) st+=5;
+ const Mine* m = mine( y, x );
+ int st = (int)m->state(); if ( m->isMined() ) st+=5;
grid += code + st;
}
}
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");
if ( !grid.isEmpty() ) {
int i=0;
minecount=0;
mineguess=0;
- for ( int x = 0; x < numCols(); x++ ) {
- for ( int y = 0; y < numRows(); y++ ) {
+ for ( int 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* mine = (Mine*)item( y, x );
+ Mine* m = mine( y, x );
if ( st >= 5 ) {
st-=5;
- mine->setMined(TRUE);
+ m->setMined(TRUE);
minecount++;
mineguess++;
}
- mine->setState((Mine::MineState)st);
- switch ( mine->state() ) {
+ m->setState((Mine::MineState)st);
+ switch ( m->state() ) {
case Mine::Flagged:
- if (mine->isMined())
+ if (m->isMined())
minecount--;
mineguess--;
break;
case Mine::Empty:
--nonminecount;
+ break;
+ default:
+ break;
}
}
}
- for ( int x = 0; x < numCols(); x++ ) {
- for ( int y = 0; y < numRows(); y++ ) {
- Mine* mine = (Mine*)item( y, x );
- if ( mine->state() == Mine::Empty )
- mine->setHint(getHint(y,x));
+ for ( int 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 );
}