author | drw <drw> | 2002-03-15 20:33:05 (UTC) |
---|---|---|
committer | drw <drw> | 2002-03-15 20:33:05 (UTC) |
commit | 20cbfeefd68221f7b6f9dd512c6ff3e9a9484af2 (patch) (side-by-side diff) | |
tree | 06e7b467ababb70d10b0c343f5b7881490c20b66 | |
parent | eb338502c03edbfc8b9b9f00bd95c0c0d4317003 (diff) | |
download | opie-20cbfeefd68221f7b6f9dd512c6ff3e9a9484af2.zip opie-20cbfeefd68221f7b6f9dd512c6ff3e9a9484af2.tar.gz opie-20cbfeefd68221f7b6f9dd512c6ff3e9a9484af2.tar.bz2 |
Fixed segfault and resizing issue for minefield
-rw-r--r-- | noncore/games/minesweep/minefield.cpp | 410 |
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 @@ -69,3 +69,9 @@ static const char *pix_mine[]={ -class Mine : public QTableItem + +static const int maxGrid = 28; +static const int minGrid = 9; + + + +class Mine : public Qt { @@ -84,6 +90,6 @@ public: - 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 ); } @@ -105,3 +111,4 @@ private: MineState st; - + MineField *field; + static QPixmap* knownField; @@ -117,4 +124,3 @@ QPixmap* Mine::mine_pix = 0; -Mine::Mine( QTable *t ) -: QTableItem( t, Never, QString::null ) +Mine::Mine( MineField *f ) { @@ -123,2 +129,3 @@ Mine::Mine( QTable *t ) hint = 0; + field = f; } @@ -175,4 +182,6 @@ void Mine::paletteChange() -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 ) { @@ -181,3 +190,3 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) 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 ); } @@ -190,3 +199,3 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) QBrush br( cg.button() ); - qDrawWinButton( &pp, QRect(0,0,cr.width(), cr.height())/*cr*/, cg, FALSE, &br ); + qDrawWinButton( &pp, cr, cg, FALSE, &br ); } @@ -207,6 +216,6 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) 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 ) { @@ -217,3 +226,4 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) case 2: - p->setPen( green ); + p->setPen( green.dark() ); + break; case 3: @@ -221,7 +231,16 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) 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 ) ); } @@ -229,14 +248,14 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) 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; @@ -244,4 +263,4 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) 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; @@ -249,6 +268,6 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) 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; @@ -264,20 +283,9 @@ void Mine::paint( QPainter* p, const QColorGroup &cg, const QRect& cr, bool ) 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 ) ) ); + setFocusPolicy( QWidget::NoFocus ); @@ -288,3 +296,3 @@ MineField::MineField( QWidget* parent, const char* name ) ignoreClick = FALSE; - currRow = currCol = 0; + currRow = currCol = -1; minecount=0; @@ -292,2 +300,4 @@ MineField::MineField( QWidget* parent, const char* name ) nonminecount=0; + cellSize = -1; + mines = 0; } @@ -296,2 +306,11 @@ MineField::~MineField() { + int i; + if ( mines ) + { + for ( i = 0; i < numCols*numRows; i++ ) + { + delete mines[i]; + } + delete[] mines; + } } @@ -303,3 +322,2 @@ void MineField::setState( State st ) - void MineField::setup( int level ) @@ -308,11 +326,13 @@ void MineField::setup( int level ) setState( Waiting ); - viewport()->setUpdatesEnabled( FALSE ); - - int cellsize; - - int x; - int y; - for ( x = 0; x < numCols(); x++ ) - for ( y = 0; y < numRows(); y++ ) - clearCell( y, x ); + //viewport()->setUpdatesEnabled( FALSE ); + + int i; + if ( mines ) + { + for ( i = 0; i < numCols*numRows; i++ ) + { + delete mines[i]; + } + delete[] mines; + } @@ -320,21 +340,23 @@ void MineField::setup( int level ) 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; @@ -343,13 +365,73 @@ void MineField::setup( int level ) - 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(); - viewport()->setUpdatesEnabled( TRUE ); - viewport()->repaint( TRUE ); +} + +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) ); } @@ -361,9 +443,9 @@ void MineField::placeMines() 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--; @@ -373,14 +455,27 @@ void MineField::placeMines() -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 ) { @@ -390,2 +485,29 @@ void MineField::viewportMouseReleaseEvent( QMouseEvent* e ) + + +/* + 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 ) @@ -409,4 +531,4 @@ int MineField::getHint( int row, int col ) 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++; @@ -417,9 +539,8 @@ int MineField::getHint( int row, int col ) -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 ); @@ -429,7 +550,7 @@ void MineField::setHint( Mine* mine ) 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 ); @@ -439,3 +560,3 @@ void MineField::setHint( Mine* mine ) - mine->setHint( hint ); + m->setHint( hint ); updateCell( row, col ); @@ -444,24 +565,2 @@ void MineField::setHint( Mine* mine ) /* - 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 @@ -475,6 +574,6 @@ void MineField::cellClicked( int row, int col ) 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--; @@ -495,12 +594,12 @@ 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 ); @@ -508,4 +607,4 @@ void MineField::updateMine( int row, int col ) return; - } else if ( mine->state() == Mine::Empty ) { - setHint( mine ); + } else if ( m->state() == Mine::Empty ) { + setHint( row, col ); if ( !wasEmpty ) @@ -515,6 +614,6 @@ void MineField::updateMine( int row, int col ) if ( flagAction != NoAction ) { - if ( mine->state() == Mine::Flagged ) { + if ( m->state() == Mine::Flagged ) { --mineguess; emit mineCount( mineguess ); - if ( mine->isMined() ) + if ( m->isMined() ) --minecount; @@ -523,3 +622,3 @@ void MineField::updateMine( int row, int col ) emit mineCount( mineguess ); - if ( mine->isMined() ) + if ( m->isMined() ) ++minecount; @@ -538,11 +637,11 @@ 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 ); @@ -555,3 +654,3 @@ void MineField::paletteChange( const QPalette &o ) Mine::paletteChange(); - QTable::paletteChange( o ); + QScrollView::paletteChange( o ); } @@ -564,7 +663,7 @@ void MineField::writeConfig(Config& cfg) const 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; @@ -588,10 +687,10 @@ void MineField::readConfig(Config& cfg) 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++; @@ -599,6 +698,6 @@ void MineField::readConfig(Config& cfg) } - 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--; @@ -608,2 +707,5 @@ void MineField::readConfig(Config& cfg) --nonminecount; + break; + default: + break; } @@ -611,7 +713,7 @@ void MineField::readConfig(Config& cfg) } - 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)); } |