Reputation: 13
I have to recreate a simple version of the game "Minefield" in C, but I'm having trouble on counting how many mines are near a certain spot in the board. My piece of code runs throughout the array (board) searching for mines. When it finds a mine, it should add up +1 in all the surrounding spots of the mine. My code only works to the surrounding spots of T[0][0]. m and n stand for the number of lines and columns on the board. Please, help!!
void mine_counting (int T[MMAX][NMAX], int m, int n)
{
int cont, i, j;
for (i = 0 ; i < m ; i++)
{
printf("\ni = %d", i);
for (j = 0 ; j < n ; j++)
printf("\nj = %d", j);
{
if (T[i][j] == -3)
{
if (i == 0)
{
printf("i=0");
if (j == 0)
{
if (T[i][j+1] != -3)
T[i][j+1] = T[i][j+1] + 1;
if (T[i+1][j] != -3)
T[i+1][j] = T[i+1][j] + 1;
if (T[i+1][j+1] != -3)
T[i+1][j+1] = T[i+1][j+1] + 1;
}
if (j == (n-1))
{
printf("j = n-1");
if (T[i][j-1] != -3)
T[i][j-1] = T[i][j-1] + 1;
if (T[i+1][j] != -3)
T[i+1][j] = T[i+1][j] + 1;
if (T[i+1][j-1] != -3)
T[i+1][j-1] = T[i+1][j-1] + 1;
}
if (j != 0 && j!= (n-1))
{
if (T[i+1][j] != -3)
T[i+1][j] = T[i+1][j] + 1;
if (T[i+1][j+1] != -3)
T[i+1][j+1] = T[i+1][j+1] + 1;
if (T[i+1][j-1] != -3)
T[i+1][j-1] = T[i+1][j-1] + 1;
if (T[i][j+1] != -3)
T[i][j+1] = T[i][j+1] + 1;
if (T[i][j-1] != -3)
T[i][j-1] = T[i][j-1] + 1;
}
}
if (i == (m-1))
{
if (j == 0)
{
if (T[i][j+1] != -3)
T[i][j+1] = T[i][j+1] + 1;
if (T[i-1][j] != -3)
T[i-1][j] = T[i-1][j] + 1;
if (T[i-1][j+1] != -3)
T[i-1][j+1] = T[i-1][j+1] + 1;
}
if (j == (n-1))
{
if (T[i-1][j] != -3)
T[i-1][j] = T[i-1][j] + 1;
if (T[i-1][j-1] != -3)
T[i-1][j-1] = T[i-1][j-1] + 1;
if (T[i][j-1] != -3)
T[i][j-1] = T[i][j-1] + 1;
}
if (j != 0 && j!= (n-1))
{
if (T[i-1][j] != -3)
T[i-1][j] = T[i-1][j] + 1;
if (T[i-1][j+1] != -3)
T[i-1][j+1] = T[i-1][j+1] + 1;
if (T[i-1][j-1] != -3)
T[i-1][j-1] = T[i-1][j-1] + 1;
if (T[i][j+1] != -3)
T[i][j+1] = T[i][j+1] + 1;
if (T[i][j-1] != -3)
T[i][j-1] = T[i][j-1] + 1;
}
}
if (j == 0 && i != 0 && i!= (m-1))
{
if (T[i-1][j] != -3)
T[i-1][j] = T[i-1][j] + 1;
if (T[i-1][j+1] != -3)
T[i-1][j+1] = T[i-1][j+1] + 1;
if (T[i][j+1] != -3)
T[i][j+1] = T[i][j+1] + 1;
if (T[i+1][j+1] != -3)
T[i+1][j+1] = T[i+1][j+1] + 1;
if (T[i+1][j] != -3)
T[i+1][j] = T[i+1][j] + 1;
}
if (j == (n-1) && i != 0 && i!= (m-1))
{
if (T[i-1][j] != -3)
T[i-1][j] = T[i-1][j] + 1;
if (T[i-1][j-1] != -3)
T[i-1][j-1] = T[i-1][j-1] + 1;
if (T[i][j-1] != -3)
T[i][j-1] = T[i][j-1] + 1;
if (T[i+1][j-1] != -3)
T[i+1][j-1] = T[i+1][j-1] + 1;
if (T[i+1][j] != -3)
T[i+1][j] = T[i+1][j] + 1;
}
if ((i != 0) && (i != (m-1)) && (j != 0) && (j != (n-1)))
{
if (T[i-1][j] != -3)
T[i-1][j] = T[i-1][j] + 1;
if (T[i-1][j-1] != -3)
T[i-1][j-1] = T[i-1][j-1] + 1;
if (T[i][j-1] != -3)
T[i][j-1] = T[i][j-1] + 1;
if (T[i+1][j-1] != -3)
T[i+1][j-1] = T[i+1][j-1] + 1;
if (T[i+1][j] != -3)
T[i+1][j] = T[i+1][j] + 1;
if (T[i+1][j+1] != -3)
T[i+1][j+1] = T[i+1][j+1] + 1;
if (T[i][j+1] != -3)
T[i][j+1] = T[i][j+1] + 1;
if (T[i-1][j+1] != -3)
T[i-1][j+1] = T[i-1][j+1] + 1;
}
Upvotes: 1
Views: 1369
Reputation: 6471
You are really making it more complex than it is..
Why not use loops? They are made for doing these jobs. Cutting the task into smaller functions makes coding much easier and faster. It will also make your code easier to read and maintain.
[edit] I've added universal all-purpose, min and max macros, they're a must have in every C programmer's toolbox. Thanks @bolov for the suggestion.
#define MINE (-3)
// lower-case min, max are defined in <windows.h>, hence the choice
// and the check.
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
int mine_detector(int board[M][N], int x, int y)
{
int result, i, j, xmin, xmax, ymin, ymax;
xmin = min(x - 1, 0); // compute your boundaries beforehand
xmax = max(x + 1, M - 1);
ymin = min(y - 1, 0);
ymax = max(y + 1, N - 1);
if (board[x][y] == MINE)
return MINE;
result = 0;
for (i = xmin; i <= xmax; ++i)
for (j = ymin; j <= ymax; ++j)
if (board[i][j] == MINE)
++result;
return result;
}
void count_mines(int board[M][N])
{
// returns detected mines on board[][] in board[][]
int i, j;
for (i = 0; i < M; ++i)
for (j = 0; j < N; ++i)
board[i][j] = mine_detector(board, i, j);
}
Upvotes: 1
Reputation: 137850
Your approach can probably be fixed to work, but it's already produced too many lines of code.
First, the data structure which holds both mines and adjacency counts is a little contrived. It does represent the visible board, but it's jamming two different kinds of information into the int
datatype.
Second, listing the adjacent spots is less elegant than finding them automatically with a loop. The edges get special cases (literal edge cases!) but you could avoid this by padding them with zeroes.
So, for instance,
// Parameter "mines" is the minefield, plus a ring of zero values around the edge.
// Parameter "adjacence" must be pre-filled with zeroes. It has no such padding.
void mine_counting (const bool mines[MMAX+2][NMAX+2], int adjacence[MMAX][NMAX],
int m, int n) {
for ( int di = -1; di <= 1; ++ di ) {
for ( int dj = -1; dj <= 1; ++ dj ) {
for ( int i = 0; i != m; ++ i ) {
for ( int j = 0; j != n; ++ j ) {
adjacence[i][j] += mines[i + di + 1][j + dj + 1];
}
}
}
}
}
If you wanted to make the coordinate systems of the two arrays match exactly, you could add the same padding to adjacence
— it would be harmless. Then the +1
's in the innermost loop would disappear.
Upvotes: 1