Struggling with C++ Minesweeper Game

Pages: 1234
Sorry about that it was my fault should of read it, was a very long day.

I am struggling to find a suitable place to include set_mines within the beginners level, Have got got any advise as to where you think it should go? as the places taht I have tried don't seem to be implementing it, do I include it like,
cout << set_mines;
or
set_mines;

Thanks
Sam
closed account (o3hC5Di1)
Hi there,

set_mines is a function, so it should always be called with parenthesis: set_mines().
In this case, set_mines also takes parameters, as defined in its declaration:
void set_mines(char** board, int columns, int rows, int mines)

the place where you are calling it is excellent, but as said you are calling a function, the function's purpose is only to assign mines randomly.

Now, I think you misunderstood when I "strike-through" 'd some of your code, here's the correct code for your set_mines function:

1
2
3
4
5
6
7
8
9
10
11
12
13
void set_mines(char** board, int columns, int rows, int mines)
{ 
    int minecounter = 0, X, Y;
	do
	{
		X = rand()%rows;   //we use rows and columns passed in the
                Y = rand()%columns; //parameters so it will work in whatever level we use this
                if (board[X][Y] !='b')
		{
			minecounter++;
		}
	} while (minecounter < mines);
}


And calling set_mines is as easy as: (line 114)
1
2
//assign bombs by putting the letter "b" in certain fields of our board
set_mines(beginnerboard, rows, columns, mines);


Does that make sense to you?

All the best,
NwN
Last edited on
Removed
Last edited on
closed account (o3hC5Di1)
Haha, 1000 apologies, I copied the wrong code and forgot to adapt it, here's the right one (I think):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void set_mines(char** board, int columns, int rows, int mines)
{ 
    int minecounter = 0, X, Y;
	do
	{
		X = rand()%rows;   //we use rows and columns passed in the
                Y = rand()%columns; //parameters so it will work in whatever level we use this
                if (board[X][Y] !='b')
		{
			board[X][Y] = 'b'; //Assign the bomb
                        minecounter++;
		}
	} while (minecounter < mines);
}


All the best,
NwN
Lol, bits KK it was my fault really as I should have noticed it.

Now it is functioning and working :D

What would you suggest the next step is?

As i could do with changing the array to show numbers on the X and Y axis and then create a leader board.

Thanks
closed account (o3hC5Di1)
hillkidstr wrote:
As i could do with changing the array to show numbers on the X and Y axis


Alright, first, where would we need to put the code for this?
I.e. where do the actual printing of the board?

-N
Really sorry for late reply.

I think that the code would go within the display board function?
closed account (o3hC5Di1)
Exactly!

Now, the output we want is as follows:


   0 1 2 3
0  . . . .
1  . . . .
2  . . . .
3  . . . .


Notice that the first (x-axis) numbers are a row, whilst the Y-axis numbers are a column.

So let's look at our display_board function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void display_board(char** board, int rows, int columns)
{
    for (rows=0; rows<9; rows++) 
    {
        for (columns=0; columns<9; columns++)
        {
            if (board[rows][columns] == 'e')
            { cout<<"- ";} //dash if guessed and no bomb
            else if (board[rows][columns] == 'x')
            {cout<<"X ";} // X marks a marked bomb
            else
            { cout<<". ";} //point if not guessed, or if bomb
        }
        
        cout<<endl;
    }
}


- You need to print (cout <<) the first row (numbers on the x axis) before any of the other rows are generated.
- You need to print the numbers of the Y-axis as the first column (=character) of every row that's generated.

Have a crack at it and let us know how you get on :)

All the best,
NwN
Last edited on
Right this one is more complicated that the random mines, the only thing that I can come up with which i know is wrong as it doesn't work is,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void display_board(char** board, int rows, int columns)
{
	cout << board [X] = {0, 1, 2, 3, 4, 5, 6, 7, 8};

    for (rows=0; rows<9; rows++) 
    {
        for (columns=0; columns<9; columns++)
        {
            if (board[rows][columns] == 'e')
            { cout<<"- ";} //dash if guessed and no bomb
            else if (board[rows][columns] == 'x')
            {cout<<"X ";} // X marks a marked bomb
            else
            { cout<<". ";} //point if not guessed, or if bomb
        }
        
        cout<<endl;
    }
}


Last edited on
closed account (o3hC5Di1)
Hi there,

You found the right place for the first row, good stuff!
Here's what to do for the first row with explanations:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void display_board(char** board, int rows, int columns)
{
    /* instruction beneath is incorrect, correct would be
     * cout << "  0 1 2 3 4 5 6 7 8";
     * your code assigns a value to a variable, never done in cout */
    cout << board [X] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
    
    /* Previous would work if we didn't have different levels requiring
     * different sizes of boards, now we need to use the columns parameter
     * so we know how many numbers to show, like so: */
  
    string xnumbers = "  ";  //this will hold the numbers, starts with 2 spaces
    for (int i=0; i<columns; i++)  //make a number for every column
    {
        xnumbers += " "+i;  //add a space + the number to the string
    }

    cout << xnumbers;  //print the first line

    for (int r=0; r<rows; r++) 
    {
        /* as for our Y axis numbers, we want them at the start of every row
         * so we put them before we start generating dots or dashes
         * we can use the counter of the row-loop as the actual numbers: */

        cout << r << " ";  //prints number+space

        for (int c=0; c<columns; c++)
        {
            if (board[rows][columns] == 'e')
            { cout<<"- ";} //dash if guessed and no bomb
            else if (board[rows][columns] == 'x')
            {cout<<"X ";} // X marks a marked bomb
            else
            { cout<<". ";} //point if not guessed, or if bomb
        }
        
        cout<<endl;
    }
}



I haven't tested this, but i think it should work like this :)
Let me know if something is unclear.

All the best,
NwN
Last edited on
Thanks for that :D

Right there was a error when I put the code in on this part
cout << xnumbers; //print the first line

it said that << no operator matches these operands?

so I changed it to just xnumbers; which seemed to work but up on selecting the beginners level it is pointing an error to this line of the code line 59

display_board(board, rows, columns);
closed account (o3hC5Di1)
Strange!

Could you post your full code again together with the error please?

Thanks!

NwN
Removed
Last edited on
Line 35 and 37.

rows and columns are both outside the valid values for indexing board. I suspect you meant to use r and c.

closed account (o3hC5Di1)
Correct, thanks cire!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void display_board(char** board, int rows, int columns)
{    
    string xnumbers = "  ";  //this will hold the numbers, starts with 2 spaces
    for (int i=0; i<columns; i++)  //make a number for every column
    {
        xnumbers += " "+i;  //add a space + the number to the string
    }

    cout << xnumbers;  //print the first line

    for (int r=0; r<rows; r++) 
    {
        /* as for our Y axis numbers, we want them at the start of every row
         * so we put them before we start generating dots or dashes
         * we can use the counter of the row-loop as the actual numbers: */

        cout << r << " ";  //prints number+space

        for (int c=0; c<columns; c++)
        {
            if (board[r][c] == 'e')
            { cout<<"- ";} //dash if guessed and no bomb
            else if (board[r][c] == 'x')
            {cout<<"X ";} // X marks a marked bomb
            else
            { cout<<". ";} //point if not guessed, or if bomb
        }
        
        cout<<endl;
    }
}
Last edited on
Thanks I feel so think it should of been something I should of seen :(

the only problem now is that the cout << xnumbers; //print the first line

doesnt work due to the error mentioned above it said that << no operator matches these operands?

and when taken out it runs but doesnt display the X numbers so I suspect its because it isnt displaying them due to not allow the cout function.

closed account (o3hC5Di1)
Alright, change of plans for the row :D

Code posted in next post.
Last edited on
Still the same? I am confused aswell, here is a copy of my code will remove the old ones so the thread doesn't lock up.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Minesweeper 4.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <ctime>
using namespace std;

int score = 0;
int X,Y;

/* we take out the functionality of displaying the board
** this way we can display beginner/intermediate/... boards
** with just this function.*/
void display_board(char** board, int rows, int columns)
{    
    string xnumbers = "  ";  //this will hold the numbers, starts with 2 spaces
    for (int i=0; i<columns; i++)  //make a number for every column
    {
        xnumbers += " "+i;  //add a space + the number to the string
    }

    cout << xnumbers;

    for (int r=0; r<rows; r++) 
    {
        /* as for our Y axis numbers, we want them at the start of every row
         * so we put them before we start generating dots or dashes
         * we can use the counter of the row-loop as the actual numbers: */

        cout << r << " ";  //prints number+space

        for (int c=0; c<columns; c++)
        {
            if (board[r][c] == 'e')
            { cout<<"- ";} //dash if guessed and no bomb
            else if (board[r][c] == 'x')
            {cout<<"X ";} // X marks a marked bomb
            else
            { cout<<". ";} //point if not guessed, or if bomb
        }
        
        cout<<endl;
    }
}

/* we take out the functionality of playing i.e. marking fields,
** again so that this can apply to all levels */
void play_board(char** board, int rows, int columns, int mines)
{
    int guessed_mines = 0; //keep track of number of correctly guessed mines
    int X, Y;   //user specified X/Y coordinates
    char userchoice;
    
    //we need to do the following in a loop until either the player hits a bomb
    //or the player finds the mines and wins the game
    do
    {
        display_board(board, rows, columns);

        cout<<"Enter X Co-ordinate (1-8)"<<endl;
    	cin>>X;
    	cout<<"Enter Y Co-ordinate (1-8)"<<endl;
    	cin>>Y;
    	cout<<"Enter M to make move, B to mark as bomb"<<endl;
    	cin>>userchoice;
    	if (Y>rows||X>columns)
    	    cout << "You have entered the wrong Co-ordinates, Please Retry" << endl;

        //if user choses Move and hits a bomb, game ends
	    if (userchoice=='m' && board[X][Y] == 'b')
	    {
            cout << "Boom! Sorry, you lost this game. Better luck next time!" <<endl;
			cout << "Your total score for this game is : ";
            break;
        }
        //if user choses mark Bomb on a bomb field, set value to x
	    else if (userchoice=='b' && board[X][Y] == 'b') 
	    {
            board[X][Y] = 'x';
            guessed_mines++;
			score = score + 10;
        }         
        //possibly you may want to add a check when user marks bomb but field is empty.
	    //if field is empty and not already marked as bomb, mark as [e]mpty.
        else
	    {
            if (board[X][Y] != 'x') board[X][Y] = 'e';
			++score;
        }
    } while (guessed_mines < mines);
    
    //if the number of guessed mines is indeed the number of mines in the board, win
    if (guessed_mines == mines)
    {
        cout << "You won!" << endl;
        //you can insert a question here like "play again? next level?"
    }
}


void set_mines(char** board, int columns, int rows, int mines)
{ 
    int minecounter = 0, X, Y;
	do
	{
		X = rand()%rows;   //we use rows and columns passed in the
                Y = rand()%columns; //parameters so it will work in whatever level we use this
                if (board[X][Y] !='b')
		{
			board[X][Y] = 'b'; //Assign the bomb
			minecounter++;
		}
	} while (minecounter < mines);
}

void beginner() { //Beginner

    int rows=9, columns=9, mines=10;

	cout << "You have selected to play the Beginner level of minesweeper, Good Luck!" << endl;
	//declare and fill the board matrix, can't use regular array as we're passing
    //this to functions, don't worry about it now, just know this is an ugly quickfix.
	char** beginnerboard = new char *[rows];  
    for (int i=0;i<rows;i++)
    {
        beginnerboard[i] = new char[columns];
    }
    //assign bombs by putting the letter "b" in certain fields of our board
	set_mines(beginnerboard, rows, columns, mines);
	
	
    
    //play the game
    play_board(beginnerboard, rows, columns, mines);
	cout<<score<<endl;
    system ("pause");
    delete[] beginnerboard;
}

void leaguetable() //Table
{
	system("cls");
	cout << "This is the League Table" << endl;
	system ("pause");
}

void displayMenu() //Menu
{
        char choice;

        system("cls");
        cout << "Welcome to Minesweeper" << endl;
        cout << "1.Beginner" << endl;
        cout << "2.Intermediate" << endl;
        cout << "3.Expert" << endl;
        cout << "4.League Table" << endl;
        cout << "5.Exit" << endl;
        cout << "Please enter your menu choice: ";
        cin >> choice;

        switch (choice)
        { 
                case '1' : 
                    beginner(); 
                    break;
                case '2' : break;
                case '3' : break;
                case '4' : leaguetable();
                           break;
                case '5' : cout << "Thanks for playing minesweeper" << endl;
                           break;

                default :
                       cout << "Please enter a value between 1 and 5" << endl;
                       system ("pause");
                          
        }
}


int main() 
{
	srand(time(NULL));
    displayMenu();
    system("pause");
    return 0;
}
closed account (o3hC5Di1)
Sorry, still learning myself!

This will work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void display_board(char** board, int rows, int columns)
{    
    // printing the first row here
    cout << "  ";
    for (int i=0; i<8; i++)  //make a number for every column
        cout << " " << i;

    for (int r=0; r<rows; r++) 
    {
        /* as for our Y axis numbers, we want them at the start of every row
         * so we put them before we start generating dots or dashes
         * we can use the counter of the row-loop as the actual numbers: */

        cout << r << " ";  //prints number+space

        for (int c=0; c<columns; c++)
        {
            if (board[r][c] == 'e')
            { cout<<"- ";} //dash if guessed and no bomb
            else if (board[r][c] == 'x')
            {cout<<"X ";} // X marks a marked bomb
            else
            { cout<<". ";} //point if not guessed, or if bomb
        }
        
        cout<<endl;
    }
}
No need to be sorry without you i would still be banging my head against a brick wall lol

Its all working now :D i really cannot believe I have a working game :D

Would the league table be the next thing to do?

or to add the rest of the levels in?

If league table would it be something like this char name; and then to then have something like this

1
2
3
 
cout << "Please enter your name for the leaderboard"
cin >> name >> endl;


and then I am lost as I would imagine the name and score would need to be written to a file?
Pages: 1234