Monday 22 December 2014

Minesweeper game in C++

Structure of the Problem Requirements 

In  this project we will implement the code of minesweeper game in C++. Minesweeper is deceptively simple test of memory and reasoning. This project cover all the basic of minesweeper games modules and at the end save the result of each player in a file . Here is the complete source code of this project which help you in better understanding. 

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++

Minesweeper Game in C++
Minesweeper Game in C++

Minesweeper Game in C++
Minesweeper Game in C++

Share it Please
asad

About Author!

Asad Niazi is Software Engineer , Programmer, Web Developers and a young mentor of Tech Solutions Desk and Blogging Solutions . Asad Love to writes about Technology, Programming, Blogging and make money online.

0 comments:

Post a Comment