2D Matrix prints extra row?

62 Views Asked by At

I was coding a minesweeper game in c, and it works just fine most of the time, but I found an strange bug in which when I play the cell in the first column of the first row and it is a 0 the board has either an extra row or a row has changed positions and moved to the top. I think this comes from my expand function, as it wasn't happening before I implemented it.

This is my code:

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define DIM 8
#define DENSITY 0.2

void print_matrix(int (*)[DIM], int);
void generate_map(float, int(*)[DIM], int);
void generate_numbers(int(*)[DIM], int(*)[DIM], int, int*);
void minesweeper(int (*)[DIM], int(*)[DIM], int(*)[DIM], int*, int, int, int);
int win(int (*)[DIM], int, int);
void expand(int (*)[DIM], int (*)[DIM], int, int, int, int, int);

int main(void) {
    int map[DIM][DIM], numbers[DIM][DIM], row, column, game, mines = 0;
    char exit;

    do {
        game = 1; mines = 0;
        int visible[DIM][DIM] = { [0 ... DIM-1][0 ... DIM-1] = -1 };
        srand(time(NULL));
        do generate_map(DENSITY, map, DIM); while (mines < DIM);
        generate_numbers(numbers, map, DIM, &mines);
        do {
            print_matrix(numbers, DIM);
            puts("Map");
            print_matrix(map, DIM);
            printf("\nNumber of mines: %d", mines);
            do {
                printf("\nEnter the selected row (MAX. %d): ", DIM);
                scanf("%d", &row);
            } while (row <= 0 || row > DIM);
            do {
                printf("\nEnter the selected column (MAX. %d): ", DIM);
                scanf("%d", &column);
            } while (column <= 0 || column > DIM);
            system("cls");

            minesweeper(numbers, map, visible, &game, row - 1, column - 1, DIM);
            print_matrix(visible, DIM);
            puts("Numbers");

            if (win(visible, DIM, mines)) {
                printf("CONGRATULATIONS, YOU WON!!");
                game = 0;
            }
        } while (game);

        printf("\nEND OF THE GAME");
        printf("\nDo you want to play again? (Y/N): ");
        fflush(stdout);
        scanf(" %c", &exit);

    } while (toupper(exit) == 'Y');
}

void generate_map(float density, int(*map)[DIM], int dim) {
    int r, c;
    for (r = 0; r < dim; r++) {
        for (c = 0; c < dim; c++) {
            map[r][c] = (float)rand() / RAND_MAX > density ? 0 : 1;
        }
    }
}

void generate_numbers(int (*numbers)[DIM], int (*map)[DIM], int dim, int *mines) {
    int counter, r, c, i, j;
    for (r = 0; r < dim; r++) {
        for (c = 0; c < dim; c++) {
            counter = 0;
            for (i = r - 1; i <= r + 1; i++) {
                if (i > -1 && i < dim) {
                    for (j = c - 1; j <= c + 1; j++) {
                        if (j > -1 && j < dim) {
                            if (map[i][j] != 0) {
                                counter++;
                            }
                        }
                    }
                }
            }
            numbers[r][c] = counter;
            if (map[r][c] != 0) *mines += 1;
        }
    }
}

void minesweeper(int (*numbers)[DIM], int (*map)[DIM], int (*visible)[DIM], int *game, int row, int column, int dim) {
    if (map[row][column] == 0) {
        if (numbers[row][column] == 0) {
            expand(numbers, visible, dim, row, column, row, column);
        } else {
            visible[row][column] = numbers[row][column];
        }
    } else {
        visible[row][column] = -2;
        *game = 0;
    }
}

void print_matrix(int (*m)[DIM], int dim) {
    int r, c;
    for (r = 0; r < dim; r++) {
        for (c = 0; c < dim; c++) {
            if (m[r][c] == -1) {
                printf("| x ");
            } else if (m[r][c] == -2) {
                printf("| * ");
            } else {
                printf("| %d ", m[r][c]);
            }
        }
        printf("|\n");
    }
}

int win(int (*visible)[DIM], int dim, int mines) {
    int c, r, counter;
    for (r = 0; r < dim; r++) {
        for (c = 0; c < dim; c++) {
            if (visible[r][c] == -1) {
                counter++;
            }
        }
    }
    return (counter == mines) ? 1 : 0;
}

void expand(int (*numbers)[DIM], int (*visible)[DIM], int dim, int row, int column, int i_o, int j_o) {
    int i, j;
    for (i = row - 1; i <= row + 1; i++) {
        if (i > -1 && i < dim) {
            for (j = column - 1; j <= column + 1; j++) {
                if (j > -1 && j < dim) {
                    if ((i == i_o && j == j_o) || (i == row && j == column)) {
                        continue;
                    } else if (numbers[i][j] == 0 && visible[i][j] == -1) {
                        visible[i][j] = numbers[i][j];
                        expand(numbers, visible, dim, i, j, row, column);
                    } else {
                        visible[i][j] = numbers[i][j];
                    }
                }
            }
        }
    }
}

Firstly I create the map matrix, which has the positions of the mines, then I create another matrix with the number of mines surrounding that cell and then I use the matrix visible to print what the player can see. The expand() function is activated when the number is 0 in a given cell, and it makes visible all surrounding cells as none of them are mines, if one of those numbers is 0 it is called again with the coordenates of the 0 from the last iteration (io, jo), so it doesn't create infinite recursion. minesweeper() is the funcion that plays a given cell. I don't think it is a limit problem because it always checks for them.

In the attatchment you can see the problem I was talking about, it printed 9 rows instead of 8 and the top one is just a visible copy of the seventh one. The only move I did prior to the screenshot was playing the cell (1,1), which is a 0, so the expand function was called and it works as expected except that it created and extra row above it and the cell (1,1) is still invisible, it only became visible once i played the cell (1,2). (It is from an earlier Spanish version)

It all worked out when I added visible[i][j] = numbers[i][j]; before the continue; in the expand function. But I still want to know why it printed and extra row. Does anybody know why this could happend?

0

There are 0 best solutions below