author | erik <erik> | 2007-01-22 23:01:41 (UTC) |
---|---|---|
committer | erik <erik> | 2007-01-22 23:01:41 (UTC) |
commit | adcf6075db477909dd8170a74862a6ef91a5127f (patch) (side-by-side diff) | |
tree | da0a1e35c5d392271bce29e84d3af5c30a864f56 /noncore/games/minesweep/minefield.cpp | |
parent | 9b4871054d01a47b4c546952a0948553413840d6 (diff) | |
download | opie-adcf6075db477909dd8170a74862a6ef91a5127f.zip opie-adcf6075db477909dd8170a74862a6ef91a5127f.tar.gz opie-adcf6075db477909dd8170a74862a6ef91a5127f.tar.bz2 |
Each file in this commit had a problem where a function might return
a null value for a pointer and that null value was not checked.
Diffstat (limited to 'noncore/games/minesweep/minefield.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/games/minesweep/minefield.cpp | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/noncore/games/minesweep/minefield.cpp b/noncore/games/minesweep/minefield.cpp index 72c05b0..1987ea5 100644 --- a/noncore/games/minesweep/minefield.cpp +++ b/noncore/games/minesweep/minefield.cpp @@ -323,425 +323,427 @@ void MineField::setState( State st ) } void MineField::setup( int level ) { lev = level; setState( Waiting ); //viewport()->setUpdatesEnabled( FALSE ); int i; 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 = 13; numCols = 13; minecount = 33; break; case 3: numCols = 18; numRows = 18; minecount = 66 ; break; } 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 ) { 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 ) { setCellSize( cellSize ); } else { viewport()->setUpdatesEnabled( FALSE ); setCellSize( newCellSize ); viewport()->setUpdatesEnabled( TRUE ); viewport()->repaint( TRUE ); } } int MineField::findCellSize() { 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 ) { int b = 2; int w2 = cellsize*numCols; int h2 = cellsize*numRows; 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 ); if ( m && !m->isMined() && m->state() == Mine::Hidden ) { m->setMined( TRUE ); mines--; } } } void MineField::updateCell( int r, int c ) { updateContents( c*cellSize, r*cellSize, cellSize, cellSize ); } void MineField::contentsMousePressEvent( QMouseEvent* 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::contentsMouseReleaseEvent( QMouseEvent* 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* m = mine( r, c ); if ( m && m->isMined() ) hint++; } return hint; } void MineField::setHint( int row, int col ) { Mine *m = mine( row, col ); if ( !m ) return; 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* m = mine( r, c ); if ( m && m->state() == Mine::Hidden ) { m->activate( TRUE ); nonminecount--; setHint( r, c ); updateCell( r, c ); } } } m->setHint( hint ); updateCell( row, col ); } /* 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* m = mine( row, col ); if ( !m ) return; 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* m = mine( row, col ); if ( !m ) return; bool wasFlagged = m->state() == Mine::Flagged; bool wasEmpty = m->state() == Mine::Empty; m->activate( flagAction == NoAction ); 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 ) { 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 ); setState( GameOver ); } } void MineField::showMines() { for ( int c = 0; c < numCols; c++ ) for ( int r = 0; r < numRows; r++ ) { Mine* m = mine( r, c ); if ( !m ) continue; 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(); 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++ ) { char code='A'+(x*17+y*101)%21; // Reduce the urge to cheat 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"); int x; if ( !grid.isEmpty() ) { int i=0; minecount=0; mineguess=0; 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 (!m) + continue; if ( st >= 5 ) { st-=5; m->setMined(TRUE); minecount++; mineguess++; } m->setState((Mine::MineState)st); switch ( m->state() ) { case Mine::Flagged: if (m->isMined()) minecount--; mineguess--; break; case Mine::Empty: --nonminecount; break; default: break; } } } for ( x = 0; x < numCols; x++ ) { for ( int y = 0; y < numRows; y++ ) { Mine* m = mine( y, x ); - if ( m->state() == Mine::Empty ) + if ( m && 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); } |