commit 8ae7e6b9abcc77ee0d5b394165910d37101c53d5 Author: Apostolof Date: Sun Jun 18 11:52:17 2017 +0300 Init diff --git a/board.cpp b/board.cpp new file mode 100644 index 0000000..3cec279 --- /dev/null +++ b/board.cpp @@ -0,0 +1,108 @@ +#include "board.h" + +//Constructor that creates the board of the game for a size +Board::Board(int Nbombs, int rows, int cols){ + this->rows=rows; + this->cols=cols; + this->Nbombs=Nbombs; + + for(int j=0;j(cols)); + for(int k=0;k > board){ + rows = board.size(); + cols = board.at(0).size(); + this->gameBoard = board; + int sum = 0; + //Calculate how many bombs the board has + for(int i=0; i= 0) && (y < cols) && (y >= 0)); +} + +//Return the vector of the board +QVector< QVector > Board::getBoard(){ + return gameBoard; +} + +//Return the number of bombs of a position x,y +int Board::getNumberOfBombs(int x,int y){ + return gameBoard[x][y]; +} + +int Board::getNbombs() const{ + return Nbombs; +} + +//Return the board with data encrypted +QVector > Board::getEncryption(){ + QVector< QVector > encrypt(gameBoard.size(), QVector(gameBoard.at(0).size())); + for(int i=0; i > Board::getDecryption(QVector< QVector > board){ + QVector< QVector > decrypt(board.size(), QVector(board.at(0).size())); + for(int i=0; i + +#include +#include + +#define XOR_NUM 6 + +class Board{ + private: + QVector< QVector > gameBoard;//Vector for the board + int rows; //Number of Rows + int cols; //Number of columns + int Nbombs; //Number of Bombs + bool isInsideTheBoard(int, int); //True if coordinates are inside the board + public: + QVector< QVector > getBoard(); //Return the vector of the board + Board(int Nbombs, int rows, int cols); //First constructor + Board(QVector< QVector >); //Second constructor + int calculateNeighborsBombs(int x,int y); + int getNumberOfBombs(int x,int y); + int getNbombs() const; + QVector< QVector > getEncryption(); + QVector< QVector > getDecryption(QVector< QVector >); + +}; + +#endif // BOARD_H diff --git a/images/Activatedbomb.png b/images/Activatedbomb.png new file mode 100644 index 0000000..f3f26b8 Binary files /dev/null and b/images/Activatedbomb.png differ diff --git a/images/bomb.png b/images/bomb.png new file mode 100644 index 0000000..80789be Binary files /dev/null and b/images/bomb.png differ diff --git a/images/eight.png b/images/eight.png new file mode 100644 index 0000000..9767bdf Binary files /dev/null and b/images/eight.png differ diff --git a/images/five.png b/images/five.png new file mode 100644 index 0000000..100f772 Binary files /dev/null and b/images/five.png differ diff --git a/images/flag.png b/images/flag.png new file mode 100644 index 0000000..d606d96 Binary files /dev/null and b/images/flag.png differ diff --git a/images/four.png b/images/four.png new file mode 100644 index 0000000..00a6ea9 Binary files /dev/null and b/images/four.png differ diff --git a/images/one.png b/images/one.png new file mode 100644 index 0000000..1edbecf Binary files /dev/null and b/images/one.png differ diff --git a/images/seven.png b/images/seven.png new file mode 100644 index 0000000..c88f115 Binary files /dev/null and b/images/seven.png differ diff --git a/images/six.png b/images/six.png new file mode 100644 index 0000000..cd5da4f Binary files /dev/null and b/images/six.png differ diff --git a/images/three.png b/images/three.png new file mode 100644 index 0000000..3d49598 Binary files /dev/null and b/images/three.png differ diff --git a/images/two.png b/images/two.png new file mode 100644 index 0000000..307e60a Binary files /dev/null and b/images/two.png differ diff --git a/images/zero.png b/images/zero.png new file mode 100644 index 0000000..672579b Binary files /dev/null and b/images/zero.png differ diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..1af1118 --- /dev/null +++ b/main.cpp @@ -0,0 +1,14 @@ +#include + +#include "window.h" +#include "board.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + myWindow window; + window.show(); + + return app.exec(); +} diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..7de574d --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,24 @@ + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + + + + + + + + + diff --git a/mineicon.ico b/mineicon.ico new file mode 100644 index 0000000..8a0bc37 Binary files /dev/null and b/mineicon.ico differ diff --git a/minesico.rc b/minesico.rc new file mode 100644 index 0000000..2b1a7af --- /dev/null +++ b/minesico.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "mineicon.ico" diff --git a/minesweeperbutton.cpp b/minesweeperbutton.cpp new file mode 100644 index 0000000..2908a6c --- /dev/null +++ b/minesweeperbutton.cpp @@ -0,0 +1,44 @@ +#include "minesweeperbutton.h" +#include +#include + +//Detect Left click +MineSweeperButton::MineSweeperButton(QWidget *parent) : QPushButton(parent) +{ +} + +MineSweeperButton::MineSweeperButton(QString blah) : QPushButton(blah) +{ +} + +//Enables Right clicking +void MineSweeperButton::mousePressEvent(QMouseEvent *qMEvent) +{ + //If we right click + if ( qMEvent->button() == Qt::RightButton ) + { + emit rightButtonClicked(); //emit rightButtonSignal + } + + //Do default behavior otherwise + QPushButton::mousePressEvent(qMEvent); +} + +MineSweeperButton::MineSweeperButton(int row,int column,QWidget *parent) : QPushButton(parent){ + this->row = row; + this->column = column; + this->flaged = false; +} + +int MineSweeperButton::getRow() const{ + return row; +} +int MineSweeperButton::getColumn() const{ + return column; +} +bool MineSweeperButton::isFlaged() const{ + return flaged; +} +void MineSweeperButton::setFlaged(bool flag_state){ + this->flaged = flag_state; +} diff --git a/minesweeperbutton.h b/minesweeperbutton.h new file mode 100644 index 0000000..9e6fca8 --- /dev/null +++ b/minesweeperbutton.h @@ -0,0 +1,27 @@ +#ifndef MINESWEEPERBUTTON_H +#define MINESWEEPERBUTTON_H + +#include + +class MineSweeperButton : public QPushButton +{ + Q_OBJECT +public: + MineSweeperButton(QWidget* = 0); + MineSweeperButton(QString); + MineSweeperButton(int,int,QWidget* = 0); + int getRow() const; + int getColumn() const; + bool isFlaged() const; + void setFlaged(bool); + void setClicked(bool); +signals: + void rightButtonClicked(); +protected: + void mousePressEvent(QMouseEvent*); +private: + int row,column; + bool flaged,clicked; +}; + +#endif // MINESWEEPERBUTTON_H diff --git a/my_minesweeper.pro b/my_minesweeper.pro new file mode 100644 index 0000000..e9eb20f --- /dev/null +++ b/my_minesweeper.pro @@ -0,0 +1,24 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2015-12-20T11:50:09 +# +#------------------------------------------------- + +QT += widgets +QT += designer +RC_FILE = minesico.rc + +HEADERS = window.h \ + minesweeperbutton.h \ + board.h +SOURCES = window.cpp \ + main.cpp \ + minesweeperbutton.cpp \ + board.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/groupbox +INSTALLS += target + +RESOURCES += \ + resource.qrc diff --git a/my_minesweeper.pro.user b/my_minesweeper.pro.user new file mode 100644 index 0000000..5d7fb9b --- /dev/null +++ b/my_minesweeper.pro.user @@ -0,0 +1,318 @@ + + + + + + EnvironmentId + {7e31b7e0-3725-4f5a-a3b0-9d84553c1075} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.9.0 MinGW 32bit + Desktop Qt 5.9.0 MinGW 32bit + qt.59.win32_mingw53_kit + 0 + 0 + 0 + + E:/Workspace/QT/build-my_minesweeper-Desktop_Qt_5_9_0_MinGW_32bit-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + E:/Workspace/QT/build-my_minesweeper-Desktop_Qt_5_9_0_MinGW_32bit-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + E:/Workspace/QT/build-my_minesweeper-Desktop_Qt_5_9_0_MinGW_32bit-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + my_minesweeper + + Qt4ProjectManager.Qt4RunConfiguration:E:/Workspace/QT/my_minesweeper/my_minesweeper.pro + true + + my_minesweeper.pro + false + + E:/Workspace/QT/build-my_minesweeper-Desktop_Qt_5_9_0_MinGW_32bit-Debug + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/my_minesweeper.pro.user.d697354 b/my_minesweeper.pro.user.d697354 new file mode 100644 index 0000000..e3c4b4a --- /dev/null +++ b/my_minesweeper.pro.user.d697354 @@ -0,0 +1,562 @@ + + + + + + EnvironmentId + {d6973540-b17c-4dc7-8548-3d1936c5664b} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.5.1 MinGW 32bit + Desktop Qt 5.5.1 MinGW 32bit + qt.55.win32_mingw492_kit + 1 + 0 + 0 + + E:/qtWorkspace/build-my_minesweeper-Desktop_Qt_5_5_1_MinGW_32bit-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + E:/qtWorkspace/build-my_minesweeper-Desktop_Qt_5_5_1_MinGW_32bit-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + E:/qtWorkspace/build-my_minesweeper-Desktop_Qt_5_5_1_MinGW_32bit-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + my_minesweeper + my_minesweeper2 + Qt4ProjectManager.Qt4RunConfiguration:E:/qtWorkspace/my_minesweeper/my_minesweeper.pro + true + + my_minesweeper.pro + false + false + + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.Target.1 + + MIngw + MIngw + {eec87427-6c04-4bfb-9263-80f771d5b719} + 0 + 0 + 0 + + E:/qtWorkspace/build-my_minesweeper-MIngw-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + E:/qtWorkspace/build-my_minesweeper-MIngw-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + E:/qtWorkspace/build-my_minesweeper-MIngw-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + my_minesweeper + + Qt4ProjectManager.Qt4RunConfiguration:E:/qtWorkspace/sample/my_minesweeper.pro + true + + my_minesweeper.pro + false + false + + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/photothumb.db b/photothumb.db new file mode 100644 index 0000000..fa58b80 Binary files /dev/null and b/photothumb.db differ diff --git a/resource.qrc b/resource.qrc new file mode 100644 index 0000000..47d8f9a --- /dev/null +++ b/resource.qrc @@ -0,0 +1,16 @@ + + + images/zero.png + images/one.png + images/two.png + images/three.png + images/four.png + images/five.png + images/six.png + images/seven.png + images/eight.png + images/bomb.png + images/Activatedbomb.png + images/flag.png + + diff --git a/window.cpp b/window.cpp new file mode 100644 index 0000000..35ed86e --- /dev/null +++ b/window.cpp @@ -0,0 +1,760 @@ +#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 >(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()); + QHBoxLayout* hbox = new QHBoxLayout(); //Allocate memory for a QHBoxLayout object hbox + for(int j=0; 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; isetFlat(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; isetFlat(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; isetFlat(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 > encrypted(lRows, QVector(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 > 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; iclick(); //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 > 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; iisFlat()){ + 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; iisFlat()) ) + buttons[level][i][j]->click(); + } + } +} diff --git a/window.h b/window.h new file mode 100644 index 0000000..ae04e39 --- /dev/null +++ b/window.h @@ -0,0 +1,98 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include +#include +#include +#include +#include "board.h" +#include "minesweeperbutton.h" + +#define SIZE_OF_BUTTON 20 +#define EASY_COLUMNS 10 +#define EASY_ROWS 10 +#define MODERATE_COLUMNS 15 +#define MODERATE_ROWS 12 +#define HARD_COLUMNS 20 +#define HARD_ROWS 15 +#define BOMBS_ON_EASY 10 +#define BOMBS_ON_MODERATE 30 +#define BOMBS_ON_HARD 70 + +class QHBoxLayout; +class QVBoxLayout; + +namespace Ui { + class myWindow; +} + +class myWindow : public QMainWindow +{ + Q_OBJECT + +public: + myWindow(QWidget *parent = 0); +private slots: + void updateTimer(); + void handleEasy(); //For easy button-press + void handleModerate(); //For moderate button-press + void handleHard(); //For hard button-press + void handleButtonReleased(); + void handleRightButton(); + //Slots for menu actions + void open(); + bool save(); + bool saveAs(); + void about(); + void wasModified(); +private: + Board* board; //A pointer to Board objects, holds actual board + int level; //Current game level + int currentTime; + int trueFlagCounter, trueClickedCounter; + bool isUntitled,gameEnded; + bool hasStarted; + QString curFile; //Current file's name + QTimer *timer; + QLCDNumber *lcdNumber1; + QWidget* centralWidget; //Holds basic window layout + QVBoxLayout* layout; //Window layout + QHBoxLayout* levelSelect; //Holds buttons easy,moderate,hard + QHBoxLayout* counters; + QStackedWidget* boardSelect; //Has boards for all levels stacked + QVector< QVector< QVector > > buttons; //Has pointers to all buttons + + //The two basic menus + QMenu *fileMenu; + QMenu *helpMenu; + + //Menu actions and submenus + QMenu *newMenu; //New is a submenu of File menu + QAction *newEasy; + QAction *newModerate; + QAction *newHard; + QAction *openAct; + QAction *saveAct; + QAction *saveAsAct; + QAction *exitAct; + QAction *aboutAct; + QAction *aboutQtAct; + + QWidget *createPushButtonGrid(int pLevel, int f_cols, int f_rows); //Function that creates a button grid of size cols*rows + + void newGame(int); + void createActions(); + void createMenus(); + void createStatusBar(); + void createToolbarAndBoard(); + bool maybeSave(); + void loadFile(const QString &fileName); + bool saveFile(const QString &fileName); + void setCurrentFile(const QString &fileName); + + void lose(); + void revealAll() const; + void win(); +}; + +#endif