Minesweeper implementation using C++ and Qt.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

761 lines
30 KiB

8 years ago
#include "window.h"
myWindow::myWindow(QWidget *parent)
: QMainWindow(parent){
createActions();
createMenus();
createToolbarAndBoard();
createStatusBar();
newGame(0);
/*
* centralWidget is a widget of type QWidget which will be the centralWidget of myWindow class.
*/
centralWidget = new QWidget(); //Allocate memory for the QWidget object centralWidget
setCentralWidget(centralWidget); //Set centralWidget to be the central widget of the class (myWindow)
centralWidget->setLayout(layout); //Set centralWidget's layout to layout
setWindowTitle("My Cool Minesweeper Game!![*]"); //Set window's title
}
/*
* createPushButtonGrid takes two integer arguments and returns a QWidget
* createPushButtonGrid creates a vertical box that contains f_rows horizontal boxes
* Each horizontal box holds f_cols buttons. Then the vertical box is added to a widget
* and the widget is returned.
*/
QWidget* myWindow::createPushButtonGrid(int pLevel, int f_cols, int f_rows){
buttons.push_back(QVector<QVector<MineSweeperButton*> >(f_rows));
QWidget* toBeReturned = new QWidget(); //Allocate memory for the QWidget object toBeReturned
QVBoxLayout* buttonGrid = new QVBoxLayout(); //Allocate memory for the QVBoxLayout object buttonGrid
for(int i=0; i<f_rows; ++i){ //For every row that needs to be build
//buttons[i].push_back(QVector<MineSweeperButton*>());
QHBoxLayout* hbox = new QHBoxLayout(); //Allocate memory for a QHBoxLayout object hbox
for(int j=0; j<f_cols; ++j){ //For every column that needs to be build
buttons[pLevel][i].push_back(new MineSweeperButton(i,j)); //Allocate memory for a QPushButton object button
buttons[pLevel][i][j] -> setFixedSize(SIZE_OF_BUTTON,SIZE_OF_BUTTON); //Set fixed (can't be changed later) size to SIZE_OF_BUTTON
connect(buttons[pLevel][i][j], SIGNAL(released()), this, SLOT(handleButtonReleased()));
connect(buttons[pLevel][i][j], SIGNAL(rightButtonClicked()), this, SLOT(handleRightButton()));
hbox -> addWidget(buttons[pLevel][i][j]); //Add button widget to hbox
}
hbox -> setSpacing(0); //Set spacing of hbox to 0 so buttons will be close to one another
buttonGrid->addLayout(hbox); //Add hbox layout to buttonGrid
}
buttonGrid -> setSpacing(0); //Set buttonGrid's spacing to 0
toBeReturned->setLayout(buttonGrid); //Set buttonGrid to be the layout of toBeReturned widget
toBeReturned->setFixedSize(SIZE_OF_BUTTON*f_cols,SIZE_OF_BUTTON*f_rows); //Set fixed size of toBeReturned
return toBeReturned;
}
void myWindow::createToolbarAndBoard(){
/*
* levelSelect is a layout of QHBoxLayout type, meaning it is a horizontal box that holds
* different widgets. levelSelect is used to hold the buttons for level selection.
*/
levelSelect = new QHBoxLayout(); //Allocate memory for the QHBoxLayout object levelSelect
QPushButton *easy = new QPushButton(tr("&Easy")); //Create button easy
connect(easy, SIGNAL(clicked()), this, SLOT(handleEasy())); //Conect button with appropriate slot
easy->setStatusTip(tr("Start new game at easy level")); //Set status bar tip
QPushButton *moderate = new QPushButton(tr("&Moderate")); //Create button moderate
connect(moderate, SIGNAL(clicked()), this, SLOT(handleModerate())); //Conect button with appropriate slot
moderate->setStatusTip(tr("Start new game at moderate level")); //Set status bar tip
QPushButton *hard = new QPushButton(tr("&Hard")); //Create button hard
connect(hard, SIGNAL(clicked()), this, SLOT(handleHard())); //Conect button with appropriate slot
hard->setStatusTip(tr("Start new game at hard level")); //Set status bar tip
levelSelect->addWidget(easy); //Add button easy to levelSelect Layout
levelSelect->addWidget(moderate); //Add button moderate to levelSelect Layout
levelSelect->addWidget(hard); //Add button hard to levelSelect Layout
/*
* boardSelect is a widget of QStackedWidget type. It has 3 layers of widgets. At any time only one is vissible.
* Each widget in every level contains a button grid with the appropriate amount of buttons for each level.
*/
boardSelect = new QStackedWidget(); //Allocate memory for the QStackedWidget object boardSelect
boardSelect->addWidget(createPushButtonGrid(0,EASY_COLUMNS,EASY_ROWS)); //Add a widget with button grid for easy level
boardSelect->addWidget(createPushButtonGrid(1,MODERATE_COLUMNS,MODERATE_ROWS)); //Add a widget with button grid for moderate level
boardSelect->addWidget(createPushButtonGrid(2,HARD_COLUMNS,HARD_ROWS)); //Add a widget with button grid for hard level
boardSelect->setCurrentIndex(0); //Set stack index to 0, board for easy level will be shown
/*
* Sxolia edw!
*
*/
timer= new QTimer();
lcdNumber1 = new QLCDNumber; //show time
lcdNumber1->setDigitCount(4);
currentTime=0;
connect(timer, SIGNAL(timeout()), this, SLOT(updateTimer()));
/*
* layout is a layout of type QVBoxLayout,meaning it is a vertical box that holds
* different widgets and child layouts. layout should contain every widget and layout
* the basic window has.
*/
layout = new QVBoxLayout; //Allocate memory for the QVBoxLayout object layout
layout->addLayout(levelSelect); //Add levelSelect as a child layout to layout
layout->addWidget(lcdNumber1); //Add clock widget to layout
layout->addWidget(boardSelect); //Add boardSelect widget to layout
layout->setSpacing(0); //Set layout's spacing to 0
}
/*
* createActions allocates memory for the actions of save,save as, open, exit,
* about and about qt. In this funtion these actions are created, given their
* properties and connected to their different signals
*/
void myWindow::createActions(){
openAct = new QAction("&Open",this);
openAct->setShortcuts(QKeySequence::Open);
openAct->setStatusTip(tr("Open a saved game"));
connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
saveAct = new QAction("&Save",this);
saveAct->setShortcuts(QKeySequence::Save);
saveAct->setStatusTip(tr("Save progress"));
connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
saveAsAct = new QAction(tr("Save &As..."), this);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
saveAsAct->setStatusTip(tr("Save progress under a new name"));
connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcuts(QKeySequence::Quit);
exitAct->setStatusTip(tr("Exit the application"));
connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
aboutAct = new QAction(tr("&About"),this);
aboutAct->setStatusTip(tr("Show the application's About box"));
connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
aboutQtAct = new QAction(tr("About &Qt"),this);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}
/*
* createMenus allocates memory for the menus file,help and the submenu new
* In this funtion these menus are created, given their properties and
* defferent actions are added to them. Also the actions added to the new
* submenu are created here.
*/
void myWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
newMenu = fileMenu->addMenu(tr("&New"));
newEasy = new QAction("New &Easy Game (10X10)",newMenu);
newEasy->setStatusTip(tr("New easy game 10 bmbs"));
connect(newEasy, SIGNAL(triggered()), this, SLOT(handleEasy()));
newModerate = new QAction("New &Moderate Game (12X15)",newMenu);
newModerate->setStatusTip(tr("New moderate game 40 bmbs"));
connect(newModerate, SIGNAL(triggered()), this, SLOT(handleModerate()));
newHard = new QAction("New &Hard Game (15X20)",newMenu);
newHard->setStatusTip(tr("New hard game 70 bmbs"));
connect(newHard, SIGNAL(triggered()), this, SLOT(handleHard()));
newMenu->addAction(newEasy);
newMenu->addAction(newModerate);
newMenu->addAction(newHard);
fileMenu->addMenu(newMenu);
fileMenu->addAction(openAct);
fileMenu->addAction(saveAct);
fileMenu->addAction(saveAsAct);
fileMenu->addSeparator();
fileMenu->addAction(exitAct);
menuBar()->addSeparator();
helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(aboutAct);
helpMenu->addAction(aboutQtAct);
}
void myWindow::handleEasy(){
//Button easy was pressed
if(maybeSave()){
setWindowModified(false);
newGame(0);
}
}
void myWindow::handleModerate(){
//Button moderate was pressed
if(maybeSave()){
setWindowModified(false);
newGame(1);
}
}
void myWindow::handleHard(){
//Button moderate was pressed
if(maybeSave()){
setWindowModified(false);
newGame(2);
}
}
void myWindow::newGame(int pLevel){
level = pLevel; //Set level
switch(level){
case 0:
//Set all buttons to initial state
for(int i=0; i<EASY_ROWS; ++i){
for(int j=0; j<EASY_COLUMNS; ++j){
buttons[level][i][j]->setFlat(false);
buttons[level][i][j]->setFlaged(false);
buttons[level][i][j]->setIcon(QIcon());
}
}
board = new Board(BOMBS_ON_EASY,EASY_ROWS,EASY_COLUMNS); //Create a new board
boardSelect->setCurrentIndex(level); //Set boardSelect's index to level (0) to show the board for easy
this->setFixedSize(250,320); //Set window's size
break;
case 1:
//Set all buttons to initial state
for(int i=0; i<MODERATE_ROWS; ++i){
for(int j=0; j<MODERATE_COLUMNS; ++j){
buttons[level][i][j]->setFlat(false);
buttons[level][i][j]->setFlaged(false);
buttons[level][i][j]->setIcon(QIcon());
}
}
board = new Board(BOMBS_ON_MODERATE,MODERATE_ROWS,MODERATE_COLUMNS); //Create a new board
boardSelect->setCurrentIndex(level); //Set boardSelect's index to level (1) to show the board for moderate
this->setFixedSize(330,350); //Set window's size
break;
case 2:
//Set all buttons to initial state
for(int i=0; i<HARD_ROWS; ++i){
for(int j=0; j<HARD_COLUMNS; ++j){
buttons[level][i][j]->setFlat(false);
buttons[level][i][j]->setFlaged(false);
buttons[level][i][j]->setIcon(QIcon());
}
}
board = new Board(BOMBS_ON_HARD,HARD_ROWS,HARD_COLUMNS); //Create a new board
boardSelect->setCurrentIndex(level); //Set boardSelect's index to level (2) to show the board for hard
this->setFixedSize(430,420); //Set window's size
break;
default:
// should never be reached
QMessageBox messageBox;
messageBox.critical(0,"Error","An error has occured at newGame function!");
messageBox.setFixedSize(500,200);
throw(EXCEPTION_EXECUTE_FAULT);
}
gameEnded = false;
trueClickedCounter = 0;
trueFlagCounter = 0;
hasStarted=false;
}
void myWindow::open(){
//Action open was pressed
QString fileName = QFileDialog::getOpenFileName(this); //Ask user to select a file
if (!fileName.isEmpty()) { //User has selected a file
if (isUntitled && !isWindowModified()){ //No progress was made in current game
loadFile(fileName); //Load selected file
} else { //There is unsaved progress in current game
if(maybeSave()) //User wants to save?
loadFile(fileName); //Load selected file
}
}
}
bool myWindow::save(){
//Action save was pressed
if (isUntitled) { //There in no previously saved file of this game
return saveAs(); //Create a new file and save there
}
else if(gameEnded){ //Don't save and ended game!
QMessageBox messageBox;
messageBox.critical(0,"Game ended!",
"You can't save an ended game.");
messageBox.setFixedSize(500,200);
return true;
}
else { //This game has been saved before in a file
return saveFile(curFile); //Replace old file with new
}
}
bool myWindow::saveAs(){
//Action save as was pressed
if(gameEnded){ //Don't save and ended game!
QMessageBox messageBox;
messageBox.critical(0,"Game ended!",
"You can't save an ended game.");
messageBox.setFixedSize(500,200);
return true;
}
//Ask user for a name and directory of the save file
QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),
curFile);
if (fileName.isEmpty()) //No name and directory were givven
return false;
return saveFile(fileName); //Save game
}
void myWindow::about(){
//Action about was pressed
QMessageBox::about(this, tr("About Minesweeper"),
tr("Write shit here!"));
}
void myWindow::wasModified(){
//Action about qt was pressed
setWindowModified(true);
}
void myWindow::createStatusBar(){ //Initialize the status bar
statusBar()->showMessage(tr("Good luck!"));
}
bool myWindow::maybeSave(){
if (isWindowModified() && (!gameEnded) ){ //There has been progress on this game
QMessageBox::StandardButton ret;
//Ask user wether to save or not.
ret = QMessageBox::warning(this, tr("Minesweeper"),
tr("The document has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard
| QMessageBox::Cancel);
if (ret == QMessageBox::Save) //User wants to save
return save(); //Save
else if (ret == QMessageBox::Cancel) //User wants to discard
return false;
}
return true;
}
void myWindow::loadFile(const QString &fileName){ //Load a saved game for directory fileName
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) { //Try to open file
//File could not be oppened
QMessageBox::warning(this, tr("Minesweeper"),
tr("Cannot read file %1:\n%2.")
.arg(fileName)
.arg(file.errorString()));
return;
}
//File was successfully opened
QTextStream in(&file); //Initialize a text stream (same as string stream)
QString line = in.readLine(); //Read a line (first line) from the file
if(line == "Minesweeper game"){ //If the line is correct this is indeed a Minesweeper game file
int lLevel,lRows,lColumns; //Localy used variables
lLevel = (in.readLine().toInt()); //Second line is the level
switch (lLevel){ //Initialize rows and columns depending on the level
case(0):
lRows = EASY_ROWS;
lColumns = EASY_COLUMNS;
break;
case(1):
lRows = MODERATE_ROWS;
lColumns = MODERATE_COLUMNS;
break;
case(2):
lRows = HARD_ROWS;
lColumns = HARD_COLUMNS;
break;
default:
//Should never be reached
QMessageBox messageBox;
messageBox.critical(0,"Error","An error has occured while reading from the file!");
messageBox.setFixedSize(500,200);
throw(EXCEPTION_READ_FAULT);
}
//Declare a vector, will hold the encrypted file data
QVector< QVector<int> > encrypted(lRows, QVector<int>(lColumns));
int lRowCounter = 0;
//Until all neccessery data were readen or reached the end of the file
while( (lRowCounter < lRows) && (!in.atEnd()) ) {
QString line = in.readLine(); //Read next line
QStringList fields = line.split(","); //Split lines data in strings at every ","
if(fields.size() < (lColumns-1)){ //Not enough data on this line
//Should never be reached
QMessageBox messageBox;
messageBox.critical(0,"Error",
"An error has occured while reading from the file!\n Either not enough data on the file or data of wrong format!");
messageBox.setFixedSize(500,200);
throw(EXCEPTION_READ_FAULT);
}
for(int i=0; i<fields.size(); ++i){ //For every string produced
QString tmp = fields.at(i);
encrypted[lRowCounter][i] = tmp.toInt(); //Asign value to the vector
}
++lRowCounter;
}
QVector< QVector<int> > decrypted = board->getDecryption(encrypted); //Decrypt data
newGame(lLevel); //Start a new game
board = new Board(decrypted); //Create new board
lRowCounter = 0; //Restart counter
/*Read and recreate previously done progress */
//Until all neccessery data were readen or reached the end of the file
while( (lRowCounter < lRows) && (!in.atEnd()) ) {
QString line = in.readLine(); //Read next line
QStringList fields = line.split(","); //Split lines data in strings at every ","
if(fields.size() < (lColumns-1)){ //Not enough data on this line
//Should never be reached
QMessageBox messageBox;
messageBox.critical(0,"Error",
"An error has occured while reading from the file!\n Either not enough data on the file or data of wrong format!");
messageBox.setFixedSize(500,200);
throw(EXCEPTION_READ_FAULT);
}
for(int i=0; i<fields.size(); ++i){ //For every string produced
QString tmp = fields.at(i);
int som = tmp.toInt(); //Asign value to a temporary variable
switch(som){
case 0:
//Means button at (lRowCounter,i) hasn't been clicked
break;
case 1:
//Means button at (lRowCounter,i) has been left-clicked before saving
buttons[lLevel][lRowCounter][i]->click(); //Do it again
break;
case -1:
//Means button at (lRowCounter,i) has been right-clicked before saving
buttons[lLevel][lRowCounter][i]->rightButtonClicked(); //Do it again
break;
default:
//Should never be reached
QMessageBox messageBox;
messageBox.critical(0,"Error",
"An error has occured while reading from the file!\n Bad data!");
messageBox.setFixedSize(500,200);
throw(EXCEPTION_READ_FAULT);
}
}
++lRowCounter;
}
/* Data reading is done, am I at the end of the file? */
if(!in.atEnd()){
//Should never be reached
QMessageBox messageBox;
messageBox.critical(0,"Warning",
"There are more data at the end of the file!");
messageBox.setFixedSize(500,200);
}
file.close(); //Close file
setCurrentFile(fileName);
statusBar()->showMessage(tr("File loaded"), 2000);
setWindowModified(false); //No changes done since loading the file
return;
}
else{ //This is propably not a Minesweeper game file, first line was not Minesweeper game
// should never be reached
QMessageBox messageBox;
messageBox.critical(0,"Error",
"An error has occured while loading the file!\nThis is not a Minesweeper game file!");
messageBox.setFixedSize(500,200);
throw(EXCEPTION_INVALID_HANDLE);
}
}
bool myWindow::saveFile(const QString &fileName){ //Save game at fileName directory
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) { //Try to create an empty file
//File could not be created
QMessageBox::warning(this, tr("Minesweeper"),
tr("Cannot write file %1:\n%2.")
.arg(fileName)
.arg(file.errorString()));
return false;
}
//File was successfully created
QTextStream out(&file); //Initialize a text stream (same as string stream)
//Declare a vector and put the encrypted file data there
QVector< QVector<int> > encrypted = board->getEncryption();
out << "Minesweeper game" << endl; //First line is this to distinguish Minesweeper files
out << level << endl; //Second line is the level
/*
* Next line are the encrypted data in this format:
* b(0,0),b(1,0), ... ,b(columns-1,0)
* b(1,1), ... ,b(columns-1,1)
* . .
* . .
* . .
* b(rows-1,0), ... ,b(rows-1,columns-1)
*/
for(int i=0; i<encrypted.size(); ++i){
for(int j=0; j<encrypted.at(i).size(); ++j){
out << encrypted.at(i).at(j); //Write the encrypted number of the board at (i,j)
if(j != (encrypted.at(i).size()-1)) //Make sure we don't put semicolon at the end of the row
out << "," ;
}
out << endl;
}
/*
* Information about which buttons have been clicked or flagged (the actual progress)
* is writen on the file in an array, where 1 represents clicked, -1 represents
* flaged and 0 represents no activity. This array uses the same format as the previous.
*/
for(int i=0; i<encrypted.size(); ++i){
for(int j=0; j<encrypted.at(i).size(); ++j){
if(buttons[level][i][j]->isFlat()){
out << 1;
}
else if(buttons[level][i][j]->isFlaged()){
out << -1;
}
else
out << 0;
if(j != (encrypted.at(i).size()-1)) //Make sure we don't put semicolon at the end of the row
out << "," ;
}
out << endl;
}
file.close(); //Close file
setCurrentFile(fileName);
statusBar()->showMessage(tr("File saved"), 2000);
setWindowModified(false);
return true;
}
void myWindow::setCurrentFile(const QString &fileName){
static int sequenceNumber = 1;
isUntitled = fileName.isEmpty();
if (isUntitled) {
curFile = tr("document%1.txt").arg(sequenceNumber++);
} else {
curFile = QFileInfo(fileName).canonicalFilePath();
}
setWindowModified(false);
setWindowFilePath(curFile);
}
void myWindow::handleButtonReleased(){
//A button has been left-clicked
MineSweeperButton* sendedBy = (MineSweeperButton *) sender(); //Get the button
if(!hasStarted){
timer->start(1000);
hasStarted=true;
}
if(sendedBy->isFlaged() || sendedBy->isFlat()) //If the button is flaged do nothing
return;
setWindowModified(true); //Else there has been progress since last save
switch(board->getNumberOfBombs(sendedBy->getRow(),sendedBy->getColumn())){
case 0: //If the button has no neighboring bombs
{
//Set the button's icon and size for 0
QPixmap pixmap(":/images/zero.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
++trueClickedCounter;
}
break;
case 1: //If the button has one neighboring bomb
{
//Set the button's icon and size for 1
QPixmap pixmap(":/images/one.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
++trueClickedCounter;
}
break;
case 2: //If the button has two neighboring bombs
{
//Set the button's icon and size for 2
QPixmap pixmap(":/images/two.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
++trueClickedCounter;
}
break;
case 3: //If the button has three neighboring bombs
{
//Set the button's icon and size for 3
QPixmap pixmap(":/images/three.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
++trueClickedCounter;
}
break;
case 4: //If the button has four neighboring bombs
{
//Set the button's icon and size for 4
QPixmap pixmap(":/images/four.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
++trueClickedCounter;
}
break;
case 5: //If the button has five neighboring bombs
{
//Set the button's icon and size for 5
QPixmap pixmap(":/images/five.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
++trueClickedCounter;
}
break;
case 6://If the button has six neighboring bombs
{
//Set the button's icon and size for 6
QPixmap pixmap(":/images/six.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
++trueClickedCounter;
}
break;
case 7: //If the button has seven neighboring bombs
{
//Set the button's icon and size for 7
QPixmap pixmap(":/images/seven.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
++trueClickedCounter;
}
break;
case 8: //If the button has eight neighboring bombs
{
//Set the button's icon and size for 8
QPixmap pixmap(":/images/eight.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
++trueClickedCounter;
}
break;
case -1: //If the button has a bomb
{
if(!gameEnded){
//Set the button's icon and size for activated bomb
QPixmap pixmap(":/images/Activatedbomb.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
sendedBy->setFlat(true);
//Player lost!
lose();
}
else{
//Set the button's icon and size for bomb
QPixmap pixmap(":/images/bomb.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
}
}
break;
default:
// should never be reached
QMessageBox messageBox;
messageBox.critical(0,"Error",
"Something went wrong in handelButtonReleased slot!");
messageBox.setFixedSize(500,200);
throw(EXCEPTION_INVALID_HANDLE);
}
sendedBy->setFlat(true); //Set button to flat so we know it's been left-clicked
if(trueClickedCounter == (buttons.at(level).size() * buttons.at(level).at(0).size() - board->getNbombs()) ){
if(!gameEnded)
win();
}
}
void myWindow::handleRightButton(){
//A button has been right-clicked
MineSweeperButton* sendedBy = (MineSweeperButton *) sender(); //Get the button
if(sendedBy->isFlat()) //If the button is flat (has been left-clicked) do nothing
return;
setWindowModified(true); //Else there has been progress since last save
if(!(sendedBy->isFlaged())){ //If the button is not already flagged
//Set the button's icon and size to flag
sendedBy->setFlaged(true);
QPixmap pixmap(":/images/flag.png");
QIcon ButtonIcon(pixmap);
sendedBy->setIcon(ButtonIcon);
sendedBy->setIconSize(pixmap.rect().size());
if(board->getNumberOfBombs(sendedBy->getRow(),sendedBy->getColumn()) == -1){
++trueFlagCounter;
}
else
--trueFlagCounter;
}
else{ //The button is already flagged
//Un-do the "flagging"
sendedBy->setFlaged(false);
sendedBy->setIcon(QIcon());
if(board->getNumberOfBombs(sendedBy->getRow(),sendedBy->getColumn()) == -1){
--trueFlagCounter;
}
else
++trueFlagCounter;
}
if(trueFlagCounter == board->getNbombs()){
if(!gameEnded)
win();
}
}
void myWindow::lose(){
//Player lost
gameEnded = true;
revealAll();
QMessageBox messageBox;
messageBox.critical(0,"You lost!",
"Better luck next time... :)");
messageBox.setFixedSize(500,200);
}
void myWindow::win(){
//Player won
gameEnded = true;
revealAll();
QMessageBox messageBox;
messageBox.critical(0,"You won!",
"Great job! :)");
messageBox.setFixedSize(500,200);
}
void myWindow::updateTimer(){
currentTime++;
lcdNumber1->display(currentTime);
}
void myWindow::revealAll() const{
for(int i=0; i<buttons.at(level).size(); ++i){
for(int j=0; j<buttons.at(level).at(i).size(); ++j){
if(! (buttons.at(level).at(i).at(j)->isFlat()) )
buttons[level][i][j]->click();
}
}
}