minefield.cpp

来自「Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3」· C++ 代码 · 共 931 行 · 第 1/2 页

CPP
931
字号
	    {#ifdef QTOPIA_PHONE		if( r == currRow && c == currCol )		    m->setSelected( TRUE );		else		    m->setSelected( FALSE );#endif		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 = 0;        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 ){    if (Global::mousePreferred()) {        int c = e->pos().x() / cellSize;        int r = e->pos().y() / cellSize;        if ( onBoard( r, c ) )	    cellPressed( r, c );        else	    currCol = currRow = -1;        pressed = TRUE;    }}void MineField::contentsMouseReleaseEvent( QMouseEvent* e ){    if (Global::mousePreferred()) {        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;        }        pressed = FALSE;    }}/* 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(){#ifndef QTOPIA_PHONE    flagAction = FlagNext;    updateMine( currRow, currCol );    ignoreClick = TRUE;#else    if( !mAlreadyHeld || Global::mousePreferred())    {	flagAction = FlagNext;	updateMine( currRow, currCol );	ignoreClick = TRUE;        if (!Global::mousePreferred())    	    mAlreadyHeld = TRUE;    }#endif}void MineField::keyPressEvent( QKeyEvent* e ){#ifndef QTOPIA_PHONE#if defined(Q_WS_QWS) || defined(_WS_QWS_)    flagAction = ( e->key() == Key_Up ) ? FlagOn : NoAction;#else    flagAction = ( ( e->state() & ShiftButton ) ==  ShiftButton ) ? FlagOn : NoAction;#endif#endif#ifdef QTOPIA_PHONE    if (e->isAutoRepeat()) {	QScrollView::keyPressEvent( e );	return;    }    int row = currRow, col = currCol;    int key = e->key();    if ( key == Key_Select ) {	cellPressed( currRow, currCol );	pressed = TRUE;    } else if( key == Key_Back || key == Key_No ) {	QScrollView::keyPressEvent( e );    } else {	if( state() == GameOver )	    return;	switch( key )	{	    case Key_Up:		--row;		break;	    case Key_Down:		++row;		break;	    case Key_Left:		--col;		break;	    case Key_Right:		++col;		break;	    default:		QScrollView::keyPressEvent( e );		break;	}	if( (currRow != row || currCol != col) && onBoard( row, col ) )	{	    //update affected mines	    updateCell( currRow, currCol );	    currRow = row;	    currCol = col;	    updateCell( currRow, currCol );	    	    //qDebug("curRow=%d curCol=%d", currRow, currCol );	}    }#endif}void MineField::keyReleaseEvent( QKeyEvent *e ){    flagAction = NoAction;#ifdef QTOPIA_PHONE    if (e->isAutoRepeat()) {	QScrollView::keyPressEvent( e );	return;    }    int key = e->key();    if ( key == Key_Select && pressed ) {	mAlreadyHeld = FALSE;	if( state() == GameOver )	    emit newGameSelected();	else	    cellClicked( currRow, currCol );    } else {	QScrollView::keyReleaseEvent( e );    }    pressed = FALSE;#else    Q_UNUSED( e );#endif}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 ( 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 )		    m->setHint(getHint(y,x));	    }	}    }    setState( Playing );    emit mineCount( mineguess );}QSize MineField::sizeHint() const{    if ( qApp->desktop()->width() >= 240 && qApp->desktop()->height() >= 260 ) 	return QSize(200,200);    else 	return QSize(160, 160);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?