-2

I am creating a Minesweeper game. However, while testing the generating function, It malfunctions almost always (if not always), and I do not understand why.

Here is my code:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>


using namespace std;
struct board {
    int width=9, mines=10;
    char board[9][9];
    /* char board[][]
     * -1 = Mine
     * 0 = No mines near
     * 0+ = x amount of mines are near
     */
};
struct point {
    int x,y;
};
board newBoard(){
    board board1;
    point randPoint;
    for(int i=0;i<board1.width;i++){
        for(int j=0;j<board1.width;j++) board1.board[i][j]=0; // Initialize array
    }
    for(int i=0;i<board1.mines;i++){
        randPoint.x=rand()%board1.width, randPoint.y=rand()%board1.width; // Where will the mine go?
        if(board1.board[randPoint.x][randPoint.y]!=-1){ // If not already a mine
            board1.board[randPoint.x][randPoint.y]=-1; //make a mine
        } else i--; //else don't count this
    }
    for(int i=0;i<board1.width;i++){
        for(int j=0;j<board1.width;j++){
            if(board1.board[i][j]==-1) { // If mine exists
                // The if checks preceding the ++'s are to prevent out of bounds erors
                if (j-1>=0) board1.board[i][j-1]++;
                if (j+1<board1.width) board1.board[i][j+1]++;
                if (i-1>=0) board1.board[i-1][j]++;
                if (i+1<board1.width) board1.board[i+1][j]++;
                if ((i-1>=0) && (j-1>=0)) board1.board[i-1][j-1]++;
                if ((i-1>=0) && (j+1<board1.width))board1.board[i-1][j+1]++;
                if ((i+1<board1.width) && (j-1>=0))board1.board[i+1][j-1]++;
                if ((i+1<board1.width) && (j+1<board1.width))board1.board[i+1][j+1]++;
            }
        }
    }
    return board1;
}

int main() {
    board boardGame=newBoard();
    printf("-   ");
    for(int i=0;i<boardGame.width;i++) printf("%i ",i+1);
    printf("\n\n");
    for(int i=0;i<boardGame.width;i++){
        printf("%i. ",i+1);
        for(int j=0;j<boardGame.width;j++) if (boardGame.board[i][j]==-1) {
                printf(" X");
            } else {
                printf(" %i", boardGame.board[i][j]);
            }
        printf("\n");
    }
    return 0;
}

This produces:

-   1 2 3 4 5 6 7 8 9 

1.  0 0 0 0 1 X 1 0 0
2.  1 1 0 0 2 2 2 1 1
3.  X 2 1 1 1 X 1 1 X
4.  1 2 X 0 1 1 0 1 1
5.  0 1 1 1 0 0 0 0 0
6.  0 0 0 0 1 1 1 0 0
7.  0 0 1 1 2 X 1 0 0
8.  1 1 2 X 2 1 1 0 0
9.  1 X 2 1 1 0 0 0 0

As you most likely already know, in the game of minesweeper, there is mines (in this case will they will be marked as X), and all nearby grid points are the number of mines near it (if you are still unfamiliar with it this page may of use). As you can see, the numbers at 4,7 and 4,4 are incorrect.

I do not know why this is this way. Could someone aid my understanding in this, and tell my how to to fix this?


Also, I just noticed that this produces the same output every time it is run. Why?

Kaiden Prince
  • 472
  • 3
  • 18
  • 5
    Five bucks says you can march through this with a debugger and figure out what's wrong as fast as I can. – user4581301 Oct 26 '15 at 18:53
  • When incrementing the counter for the mines you need to check if there is a mine there. You are taking a mine (== -1) and adding one. – ioums Oct 26 '15 at 18:54
  • 1
    What do you mean by "it malfunctions"? Crashes? Doesn't crash but gives wrong results? – PaulMcKenzie Oct 26 '15 at 18:55
  • @ioums That is likely the problem, thank you. – Kaiden Prince Oct 26 '15 at 18:56
  • 1
    That addendum I can answer. You don't call [`srand`](http://en.cppreference.com/w/cpp/numeric/random/srand) to seed the randomizer. Without `srand` the randomizer will always have the same same starting point and generate the same results. For better results, consider using the newer [random library](http://en.cppreference.com/w/cpp/numeric/random) instead of `srand`/`rand` – user4581301 Oct 26 '15 at 18:56
  • 3
    @KaidenPrince `and tell my how to to fix this?` You fix it by debugging, something we would have to do to tell you what's wrong. Writing programs and debugging them are part and parcel of learning how to program. Just writing a bunch of code, seeing it doesn't work, and then going on SO is not the way it's supposed to work. – PaulMcKenzie Oct 26 '15 at 18:58
  • @PaulMcKenzie I couldn't figure it out. Now that I know it I feel slightly stupid, but all I needed was an extra set of eyes. – Kaiden Prince Oct 26 '15 at 20:53

2 Answers2

2

Ioums is correct, you are not checking to see if a cell is a mine before incrementing it. However, with the way that your code is currently set up, this will mean adding a check that the cell does not equal -1 in every single if statement. You should consider creating a function to safely increment a cell if it is within bounds and not a mine, like so:

void safeIncrement(int x, int y, board& b)
{
    if(x >= 0 && y >= 0 && x < b.width && y < b.width && b.board[x][y] != -1)
    {
        b.board[x][y]++;
    }
}

This means that you can replace your if statements with:

safeIncrement(i-1,j,board1);
safeIncrement(i-1,j-1,board1);
safeIncrement(i-1,j+1,board1);
safeIncrement(i,j-1,board1);
safeIncrement(i,j+1,board1);
safeIncrement(i+1,j,board1);
safeIncrement(i+1,j-1,board1);
safeIncrement(i+1,j+1,board1);

Which is much more readable in my opinion. Additionally, since the function doesn't increment the cell if it is a mine, you could also replace the if statements with the following code!

for(int a=-1; a<=1; a++)
{
    for(int b=-1; b<=1; b++)
    {
        safeIncrement(i+a,j+b, board1);
    }
}
JHobern
  • 866
  • 1
  • 13
  • 20
0

The problem happens when 2 mines are close together: when you're adding to the mine count, you don't check if that square has a mine.

Suppose you get a mine on (0, 0) and another on (0, 1). When you're adding to the mine count around (0, 0), you accidentally also add to the mine in (0, 1), changing it from -1 to 0. It also makes the second mine being processed disappear.

I suggest using another number to signal a mine, like -999, and check if the number is negative when looking for them. It's easier than adding another condition for all if clauses you already have.

SlySherZ
  • 1,631
  • 1
  • 16
  • 25