/**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the demonstration applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include class TileData : public QObject { Q_OBJECT public: TileData() : _hasFlag(false), _hasMine(false), _hint(-1), _flipped(false) {} Q_PROPERTY(bool hasFlag READ hasFlag WRITE setHasFlag NOTIFY hasFlagChanged) bool hasFlag() const { return _hasFlag; } Q_PROPERTY(bool hasMine READ hasMine NOTIFY hasMineChanged) bool hasMine() const { return _hasMine; } Q_PROPERTY(int hint READ hint NOTIFY hintChanged) int hint() const { return _hint; } Q_PROPERTY(bool flipped READ flipped NOTIFY flippedChanged()) bool flipped() const { return _flipped; } void setHasFlag(bool flag) {if(flag==_hasFlag) return; _hasFlag = flag; emit hasFlagChanged();} void setHasMine(bool mine) {if(mine==_hasMine) return; _hasMine = mine; emit hasMineChanged();} void setHint(int hint) { if(hint == _hint) return; _hint = hint; emit hintChanged(); } void flip() { if (_flipped) return; _flipped = true; emit flippedChanged(); } void unflip() { if(!_flipped) return; _flipped = false; emit flippedChanged(); } signals: void flippedChanged(); void hasFlagChanged(); void hintChanged(); void hasMineChanged(); private: bool _hasFlag; bool _hasMine; int _hint; bool _flipped; }; class MinehuntGame : public QObject { Q_OBJECT public: MinehuntGame(); Q_PROPERTY(QDeclarativeListProperty tiles READ tiles CONSTANT) QDeclarativeListProperty tiles(); Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY isPlayingChanged) bool isPlaying() {return playing;} Q_PROPERTY(bool hasWon READ hasWon NOTIFY hasWonChanged) bool hasWon() {return won;} Q_PROPERTY(int numMines READ numMines NOTIFY numMinesChanged) int numMines() const{return nMines;} Q_PROPERTY(int numFlags READ numFlags NOTIFY numFlagsChanged) int numFlags() const{return nFlags;} public slots: Q_INVOKABLE bool flip(int row, int col); Q_INVOKABLE bool flag(int row, int col); void setBoard(); void reset(); signals: void isPlayingChanged(); void hasWonChanged(); void numMinesChanged(); void numFlagsChanged(); private: bool onBoard( int r, int c ) const { return r >= 0 && r < numRows && c >= 0 && c < numCols; } TileData *tile( int row, int col ) { return onBoard(row, col) ? _tiles[col+numRows*row] : 0; } int getHint(int row, int col); void setPlaying(bool b){if(b==playing) return; playing=b; emit isPlayingChanged();} QList _tiles; int numCols; int numRows; bool playing; bool won; int remaining; int nMines; int nFlags; }; void tilesPropAppend(QDeclarativeListProperty* prop, TileData* value) { Q_UNUSED(prop); Q_UNUSED(value); return; //Append not supported } int tilesPropCount(QDeclarativeListProperty* prop) { return static_cast*>(prop->data)->count(); } TileData* tilesPropAt(QDeclarativeListProperty* prop, int index) { return static_cast*>(prop->data)->at(index); } QDeclarativeListProperty MinehuntGame::tiles(){ return QDeclarativeListProperty(this, &_tiles, &tilesPropAppend, &tilesPropCount, &tilesPropAt, 0); } MinehuntGame::MinehuntGame() : numCols(9), numRows(9), playing(true), won(false) { setObjectName("mainObject"); srand(QTime(0,0,0).secsTo(QTime::currentTime())); //initialize array for(int ii = 0; ii < numRows * numCols; ++ii) { _tiles << new TileData; } reset(); } void MinehuntGame::setBoard() { foreach(TileData* t, _tiles){ t->setHasMine(false); t->setHint(-1); } //place mines int mines = nMines; remaining = numRows*numCols-mines; while ( mines ) { int col = int((double(rand()) / double(RAND_MAX)) * numCols); int row = int((double(rand()) / double(RAND_MAX)) * numRows); TileData* t = tile( row, col ); if (t && !t->hasMine()) { t->setHasMine( true ); mines--; } } //set hints for (int r = 0; r < numRows; r++) for (int c = 0; c < numCols; c++) { TileData* t = tile(r, c); if (t && !t->hasMine()) { int hint = getHint(r,c); t->setHint(hint); } } setPlaying(true); } void MinehuntGame::reset() { foreach(TileData* t, _tiles){ t->unflip(); t->setHasFlag(false); } nMines = 12; nFlags = 0; setPlaying(false); QTimer::singleShot(600,this, SLOT(setBoard())); } int MinehuntGame::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++) { TileData* t = tile(r, c); if (t && t->hasMine()) hint++; } return hint; } bool MinehuntGame::flip(int row, int col) { if(!playing) return false; TileData *t = tile(row, col); if (!t || t->hasFlag()) return false; if(t->flipped()){ int flags = 0; for (int c = col-1; c <= col+1; c++) for (int r = row-1; r <= row+1; r++) { TileData *nearT = tile(r, c); if(!nearT || nearT == t) continue; if(nearT->hasFlag()) flags++; } if(!t->hint() || t->hint() != flags) return false; for (int c = col-1; c <= col+1; c++) for (int r = row-1; r <= row+1; r++) { TileData *nearT = tile(r, c); if (nearT && !nearT->flipped() && !nearT->hasFlag()) { flip( r, c ); } } return true; } t->flip(); if (t->hint() == 0) { for (int c = col-1; c <= col+1; c++) for (int r = row-1; r <= row+1; r++) { TileData* t = tile(r, c); if (t && !t->flipped()) { flip( r, c ); } } } if(t->hasMine()){ for (int r = 0; r < numRows; r++)//Flip all other mines for (int c = 0; c < numCols; c++) { TileData* t = tile(r, c); if (t && t->hasMine()) { flip(r, c); } } won = false; hasWonChanged(); setPlaying(false); } remaining--; if(!remaining){ won = true; hasWonChanged(); setPlaying(false); } return true; } bool MinehuntGame::flag(int row, int col) { TileData *t = tile(row, col); if(!t) return false; t->setHasFlag(!t->hasFlag()); nFlags += (t->hasFlag()?1:-1); emit numFlagsChanged(); return true; } class MinehuntExtensionPlugin : public QDeclarativeExtensionPlugin { Q_OBJECT public: void registerTypes(const char *uri) { Q_UNUSED(uri); qmlRegisterType(); } void initializeEngine(QDeclarativeEngine *engine, const char *uri) { Q_UNUSED(uri); srand(QTime(0,0,0).secsTo(QTime::currentTime())); MinehuntGame* game = new MinehuntGame(); engine->rootContext()->setContextObject(game); } }; #include "minehunt.moc" Q_EXPORT_PLUGIN(MinehuntExtensionPlugin);