Minesweeper Game Project in C++

This is the best logic building programming for beginners. This project covered all the basic of minesweeper game modules. You can edit the records in each module as per your own requirements.

Source Code 

#include <iostream>
#include <windows.h>
#include <conio.h>
#include <cstdlib>
#include <cctype>
#include <ctime>
#include <vector>
#include <limits>
#include <iomanip>
#include <fstream>

using namespace std;

void main_menu();
void set_level();
int choose_level();
void show_score();
void show_board(vector<vector <int> >&, bool show_mies = false);
void goto_xy(int, int);
void save_score(const int&);
void save_score(const int&);
void set_boards(vector <vector <int> >&);
void set_mines(vector<vector <int> >&, const int&);
int get_input (string, const int, const int lower_limit = 0);

/**
    Struct For Make Limits Of Curcor In Console...!!
    left_x_limit, right_x_limit They Specify The x Co-ordinates Of The Console Between Which Cursor Can Move. Horizontally..!!
    up_y_limit, down_y_limit They Specify The y Co-ordinates Of The Console Between Which Cursor Can Move Vertically...!!
*/
struct ConsoleLimits
{
    int left_x_limit,
         right_x_limit,
         up_y_limit,
         down_y_limit;

} console_limits;

/**
    This Struct Is For Different Type Of Data Used In The Game...!!
    1. no_of_row No. Of Rows Of The Board Display On The Screen....!!!
    2. no_of_cols No. Of Columns Of The Board Display On The Screen....!!!
    3. no_of_mines No. Of Mines That Will Set On The Board...!!
    4. x_pos The x Co-Ordinate Of Cusor On Console...!!
    5. y_pos The y Co-Ordinate Of Cusor On Console...!!
*/
struct GameData
{
    int no_of_rows,
        no_of_cols,
        no_of_mines,
        x_pos,
        y_pos;

    static const int mine_symbol = 0;

} game_date;


int main()
{
    system("COLOR 1F");
    SetConsoleTitle("Mine Sweeper Game..!!");              // Change Title Of The Console...!!
    typedef vector < vector <int > > Board;                 // Define Own Type Of 2-D Vector...!!
    do
    {
        // Playing Main Backgroung Music For The Game...!!
        // PlaySound(TEXT("BackGround Music!_1.wav"), NULL, SND_FILENAME | SND_LOOP | SND_ASYNC);
        // Calling Main Menu...!!
        main_menu();
        // Play Game Sound...!!
        // PlaySound(TEXT("BackGround Music!.wav"), NULL, SND_FILENAME | SND_LOOP | SND_ASYNC);
        // Ask From User To Slect Level...!!
        set_level();

        // The No Of Place That Has No Mines i.e., Opened...!!
        int no_of_unmines = (game_date.no_of_rows * game_date.no_of_cols) - game_date.no_of_mines;

        int row_pos = 0,        // Row Postion Of Board On Which Cusor Is Currently Is....!!!
             col_pos = 0,         // Column Postion Of Board On Which Cusor Is Currently Is....!!!
             score = 0;             // Score Made By User...!!

        char ch;                            // Charecter Entered By User....!! Valid Are (A, S, D, W, a, s, d, w)...!!
        bool game_over = false;         // If User Hit The Mine, Then It Will Be True...!!!

        // Make A Board For Playing Game...!!
        Board board(game_date.no_of_rows,  vector <int > (game_date.no_of_cols));

        // Set Board With Random Numbers [1, 9]
        set_boards(board);
        // Set Mines On Board...!!!
        set_mines(board, game_date.no_of_mines);
        show_board(board);

        game_date.x_pos = console_limits.left_x_limit - 1;
        game_date.y_pos = console_limits.up_y_limit - 1;
        goto_xy(game_date.x_pos, game_date.y_pos);

        while (!game_over && score < no_of_unmines)
        {
                goto_xy(15, console_limits.down_y_limit + 3);
                cout <<setw(15) << "Row Position" << setw(15) << "Col Position\n";
                goto_xy(15, console_limits.down_y_limit + 4);
                cout << setw(10) << row_pos << setw(13) << col_pos << endl;
                goto_xy(25, console_limits.down_y_limit + 6);
                cout << "Score: " << score;

                goto_xy(game_date.x_pos, game_date.y_pos);
                ch = _getch();

                switch (toupper(ch))
                {
                    case 'D':
                        {
                            if (game_date.x_pos < console_limits.right_x_limit)
                            {
                                game_date.x_pos += 2;
                                col_pos++;
                            }
                        }
                    break;

                    case 'A':
                        {
                            if (game_date.x_pos > console_limits.left_x_limit)
                            {
                                game_date.x_pos -= 2;
                                col_pos--;
                            }
                        }
                    break;

                    case 'W':
                        {
                            if(game_date.y_pos > console_limits.up_y_limit)
                            {
                                game_date.y_pos -= 2;
                                row_pos--;
                            }
                        }
                        break;

                    case 'S':
                        {
                            if (game_date.y_pos < console_limits.down_y_limit)
                            {
                                game_date.y_pos += 2;
                                row_pos++;
                            }
                        }
                        break;

                    case '\r':
                        {
                            if (board[row_pos][col_pos] == 0)
                            {
//                                PlaySound(TEXT("Explosion Sound Effects.wav"), NULL, SND_FILENAME | SND_ASYNC);
                                game_over = true;
                            }
                            else if (board[row_pos][col_pos] != -1)
                            {
                                cout << board[row_pos][col_pos];
                                board[row_pos][col_pos] = -1;
                                score++;
                            }
                        }
                        break;

                        goto_xy(game_date.x_pos, game_date.y_pos);
                }
                // End Of (toupper(ch))...!!
            }
                // End Of (!game_over && score < no_of_unmines)...!!!

                game_date.x_pos = 10, game_date.y_pos = 10;
                system("CLS");
                goto_xy(game_date.x_pos, game_date.y_pos);

                if (!game_over && score == no_of_unmines)
                {
                    show_board(board, true);
                    goto_xy(game_date.x_pos, game_date.y_pos + 3);
                    cout << "YOU WIN\n";
                    goto_xy(game_date.x_pos, game_date.y_pos + 4);
                    cout << "YOU SELECT ALL THE BOX THAT ARE NOT A MINE\n";
                    goto_xy(game_date.x_pos, game_date.y_pos + 5);
                }
                // End Of (!game_over && score == no_of_unmines)...!!
                else if (score < no_of_unmines)
                {
                    show_board(board, true);
                    goto_xy(game_date.x_pos, game_date.y_pos + 1);
                    cout << "GAME OVER...!!\n\n";
                    goto_xy(game_date.x_pos, game_date.y_pos + 2);
                    cout << "YOU LOSE...!!YOU HIT A MINE\n";
                    goto_xy(game_date.x_pos, game_date.y_pos + 3);
                }
                // End Of if (score < no_of_unmines)...!!

                goto_xy(game_date.x_pos, game_date.y_pos + 1);
                cout << "YOUR SCORE IS: " << score;
                goto_xy(game_date.x_pos, game_date.y_pos + 4);
                save_score(score);
                system("PAUSE");
            }
        while (true);


    return 0;
}
// End Of main()


/**
    Set Mines On The Board upto num_of_mines...!!
    @Preconditions
    1-->  0 < num_of_mines < (rows * col) Of board...!!
    @param board A 2-D int Vector On Which Mines Will Be Placed...!!
    @param num_of_mies Number Of Mines That Will Be Set Up On board...!!
*/
void set_mines(vector<vector <int> >& board, const int& num_of_mines)
{
    srand(time(0));
    int total_rows = board.size(),
         total_cols = board[0].size(),
         row_location,
         col_location;

    for (int mine = 0; mine < num_of_mines; mine++)
    {
        row_location = rand () % total_rows;
        col_location = rand() % total_cols;
        if (board[row_location][col_location] != game_date.mine_symbol)
        {
            board[row_location][col_location] = game_date.mine_symbol;
        }
        else
            mine--;
    }
} // end set_mines...!!
// eNd oF void set_mines(vector<vector <int> >& board, const int& num_of_mines)

/**
    Set Each Index Of Board With A Random Numbers B/W 1 AND 8 Inclusive....!!!
    Preconditions:
    1 -->  board Size Must Be Greater Then Zero...!!
    @param board A 2-D int Vecotor On Which Random Numbers Will Be Setting Up...!!
*/
void set_boards(vector <vector <int> >& board)
{
    srand (time(0));

    int rows = board.size(),
         cols = board[0].size();

    for (int row_pos = 0; row_pos < rows; row_pos++)
    {
        for (int col_pos = 0; col_pos < cols; col_pos++)
        {
            board[row_pos][col_pos] = 1 + rand() % 9;
        }
    }

} // end of set_board
// eND oF void set_boards(vector <vector <int> >& board)

void show_board(vector <vector <int> >& board, bool show_mines)
{
    char ch = 178;
    game_date.x_pos = 10;
    game_date.y_pos = 3;

    for (int row_pos = 0; row_pos < game_date.no_of_rows; row_pos++)
    {
        goto_xy(game_date.x_pos, game_date.y_pos);
        for (int col_pos = 0; col_pos < game_date.no_of_cols; col_pos++)
        {
            if (show_mines)
            {
                board[row_pos][col_pos] == 0 ? cout << board[row_pos][col_pos] << " " : cout << ch << " ";
            }
            else
                cout << ch << " ";
        }
        game_date.y_pos += 2;
    }
}
// eNd oF void show_board()

void goto_xy(int x_pos, int y_pos)
{
    COORD coord;
    coord.X = x_pos;
    coord.Y = y_pos;
    HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(h_console, coord);
}
// eND oF void goto_xy(int x_pos, int y_pos)

/**
    Retrun An Integer With  lower_limt < int <= upper_limit
    @param str A String That Is To Be Displayed!! It Will Describes That For What Input Is Being Taking..!!
    e.g., If str == "Rows", Then For Row Input Is Being Taking...!!
    @param upper_limits Maximum Number User Can Enter...!!
    @param lower_limt Minimum Number User Can Enter...!! By Default It Is Zero...!!
    @return num An Integer With  lower_limt < num <= upper_limit
*/
int get_input (string str, const int upper_limit, const int lower_limit)
{
    int num;
    do
    {
        cout << "\neNTER A nUMBER fOR " << str << "  (" << (lower_limit + 1) << " " << upper_limit << ")  ";
        cin >> num;

        if (num <= lower_limit && !cin.fail())
        {
            MessageBox(NULL, "iNPUT mUST bE pOSITIVE.!!\n", "eRROR..!!", MB_OK | MB_ICONERROR);
        }

        if (num > upper_limit  && !cin.fail())
        {
            MessageBox(NULL, "iNPUT mUST bE iN LIMITS.!!\ntRY aGain!!", "eRROR!", MB_OK | MB_ICONERROR);
        }

        if (cin.fail())
        {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            MessageBox(NULL, "iNPUT mUST bE aN iNTEGER..!!", "eRROR..!!", MB_OK | MB_ICONERROR);
        }
    }
    while ((num <= lower_limit || num > upper_limit) && !cin.fail());

    system("CLS");

    return num;
}
// eND oF int get_input (string str, const int upper_limit, const int lower_limit)

int choose_level()
{
    SetConsoleTitle("MINE SPEEPRER GAME -> CHOSE LEVEL..!!!");

    cout << "\n\n\n\n\n\n\n\t\t|--------------------------------------------------------------------|\n"
           << "\t\t|                    pRESS 1 fOR LEVEL 1 (eASY mODE)                 |\n\n"
           << "\t\t|                    pRESS 2 fOR LEVEL 2 (mEDUM mODE)                |\n\n"
           << "\t\t|                    pRESS 1 fOR LEVEL 3 (hARD mODE)                 |\n\n"
           << "\t\t|--------------------------------------------------------------------|\n";

    int level = get_input("Level", 3);

    return level;
}
// eND oF int choose_level()

void set_level()
{
    int level = choose_level();
    SetConsoleTitle("Mine Sweeper Game -> Chooce Level...!!");
    switch (level)
    {
    case 1:
        {
            game_date.no_of_rows = 12;
            game_date.no_of_cols = 15;
            game_date.no_of_mines = 75;
            SetConsoleTitle("MINE SWEEPER GAME -> EASY MODE....!!!");
            system("MODE 50, 40");
        }
        break;
        // End Of Case 1...!!!

    case 2:
        {
            game_date.no_of_rows = 17;
            game_date.no_of_cols = 20;
            game_date.no_of_mines = 100;
            SetConsoleTitle("MINE SWEEPER GAME -> MEDIUM MODE....!!!");
            system("MODE 60, 50");
        }
        break;
        // End Of Case 2...!!!

    case 3:
        {
            game_date.no_of_rows = 22;
            game_date.no_of_cols = 25;
            game_date.no_of_mines = 200;
            SetConsoleTitle("MINE SWEEPER GAME -> HARD MODE....!!!");
            system("MODE 77, 55");
        }
        break;
        // End Of Case 3...!!!
    }

    game_date.x_pos = 10;
    game_date.y_pos = 3;
    console_limits.left_x_limit = game_date.x_pos + 1;
    console_limits.right_x_limit = console_limits.left_x_limit + game_date.no_of_cols + game_date.no_of_rows;
    console_limits.up_y_limit = game_date.y_pos + 1;
    console_limits.down_y_limit = console_limits.right_x_limit - 13;

}
// eND oF void set_level()

void show_score()
{
    ifstream file;
    file.open("Scores!.txt");
    string name;
    int score;
    char line_end;

    cout << setw(50) << "nAME" << setw(10) << " sCORE\n";
    while (getline(file, name) && file >> score)
    {
        cout << setw(50) << name << setw(10) << score << endl;
        file.get(line_end);
    }

    file.close();

}
// eND oF void show_score()

void save_score(const int& score)
{
    ofstream file;
    file.open("Scores!.txt", ios::app);
    string name;

    cin.ignore();
    do
    {
        cout << "\teNTER yOUR nAME\n>>> ";
        getline(cin, name);
    }
    while (name.length() == 0);

    file << name << endl << score << endl;

    file.close();
    MessageBox(NULL, "sCORE sAVED", "O.K.,", MB_OK | MB_ICONMASK);
}
// eND oF void save_score(const int& score)

/**
    Main Menus Of The Game...!! Runs When Game Is Start....!!
*/
void main_menu()
{
    string game = "WELCOME TO MINE SWEEPER GAME\n";
    system("MODE 100, 40");
    Sleep(250);
    cout << "\n\n\n\n";
    for (int ch = 0; ch < game.length(); ch++)
    {
        cout << game[ch] << "  ";
        Sleep(500);
    }

    // An Infinte Loop That Will Display Main Options Of The Game...!!
    // This Will Return From Funtion If User Select Choice 2, Otherwise Always Display Main Options...!!
    while(true)
    {
        system("CLS");
        cout << "\n\n\n\n\n\t\t|-----------------------------------------------------------|\n\n";
        cout << "\t\t|                    eNTER 1 fOR vIEW sCORE                 |\n\n";
        cout << "\t\t|                    eNTER 2 fOR plAY gAME!                 |\n\n";
        cout << "\t\t|-----------------------------------------------------------|\n";
        int choice = get_input("cHOICE", 2);

        if (choice == 1)
            {
                show_score();
                system("PAUSE");
            }
        else
            return;
    }
}

Outut of the Program

Minesweeper Games in C++
Minesweeper Game in C++
Share on Google Plus

About Asad

Asad Niazi is Software Engineer , Programmer, Web Developer and a young mentor of BloggersTown and PProgramming. Asad Love to writes about Technology, Programming, Blogging and make money online.
    Blogger Comment
    Facebook Comment

0 comments:

Post a Comment