
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define bombs 10
#define SIZE 9

struct cell {
   int value;
   int show;
};

void initializeBoard(struct cell B[][SIZE]);
void showBoard(struct cell B[][SIZE]);
void getMove(struct cell B[][SIZE], int *, int *);
void uncover(struct cell B[][SIZE], int, int, int*);
void uncoverAll(struct cell B[][SIZE]);
int valid(struct cell B[][SIZE], int, int);

int main()
{
   struct cell board[SIZE][SIZE];
   int i, j, count, quit = 0 ;

   srand(time(NULL));

   initializeBoard(board);
   count = SIZE * SIZE - bombs;
   fflush(stdin);

   do {
	  showBoard(board);
	  getMove(board, &i, &j);
	  if (board[i][j].value < 0){   // hit a bomb
		 quit = 1;
      }
	  else
		 uncover(board, i, j, &count);
   } while (!quit && count);
  
   uncoverAll(board);
   showBoard(board);
   if (quit)
	  printf("\nOoops! You hit a bomb...\n");
   else
	  printf("\nYou have located all bombs. Congratulations!\n");
   printf("\nGame is over !\n\n");
}

void initializeBoard(struct cell B[][SIZE])
{
   int i, j, k;
   int x, y, count;

   /* Initialize all cell values to zero and hide all of them */
   for (i=0; i < SIZE; i++)
	  for (j=0; j < SIZE; j++){
		 B[i][j].value = 0;
		 B[i][j].show = 0;
      }
   
   /* Place bombs randomly on the board */
   for (k = 1; k <= bombs; ){
	  i = rand()% SIZE;
	  j = rand() % SIZE;
	  if (B[i][j].value != -1){
		 B[i][j].value = -1;
		 k ++;
      }
   }

   /* for each safe cell on the board count the number of 
	  adjacent bombs and update the cell value */
   for (i=0; i < SIZE; i++)
	  for(j=0; j < SIZE; j++){
		 count = 0;
		 if (B[i][j].value == 0){ // safe cell
	       for (x = i-1; x <= i+1; x++){    // count adjacent bombs
		      for (y = j-1; y <= j+1; y++)
                 if (x >= 0 && x < SIZE && y>=0 && y<SIZE)
			        if (B[x][y].value == -1)
			           count ++;
           }
		   B[i][j].value = count;
         }
      }
}

void showBoard(struct cell B[][SIZE])
{
   int i, j;
   char c;
   
   printf("\n\n  ");
   for (i = 0; i < SIZE; i++)
	  printf("%2d", i);
   printf("\n--");
   for(i = 0; i < SIZE; i++)
	  printf("--");
   printf("\n");

   for (i = 0; i < SIZE; i++){
	  printf("%d|", i);
	  for (j = 0; j < SIZE; j++){
		 if (B[i][j].show == 1){
			if (B[i][j].value == -1) c = '*';
			else if (B[i][j].value == 0) c =' ';
			else if (B[i][j].value > 0) 
			   c = (char)(B[i][j].value+(int)'0');
         }
		 else c = '_';
		 printf("%2c", c);
      }
	  printf("\n");
   }
}

void getMove(struct cell B[][SIZE], int *i, int *j)
{ 
   int valid = 1;
   
   printf("\nEnter cell coordinates:");
   do{
	  scanf("%d%d",i,j);
	  if (*i >= SIZE || *i < 0 || *j < 0 || *j >= SIZE)
	     valid = 0;
      else if (B[*i][*j].show == 1)
		 valid = 0;
      else
		 valid = 1;
      if (!valid)
		 printf("Invalid cell. Re-enter:");
   } while (!valid);
}
   
void uncoverAll(struct cell B[][SIZE])
{
   int i, j;

   for(i=0; i < SIZE; i++)
	  for (j=0; j < SIZE; j++)
		 B[i][j].show = 1;

}

void uncover(struct cell B[][SIZE], int i, int j, int *count)
{
   if (!valid(B,i,j))
	  return;
   B[i][j].show = 1;
   (*count)--;
   if (B[i][j].value == 0){
	  uncover(B, i-1, j-1, count);
	  uncover(B, i-1, j, count);
	  uncover(B, i-1, j+1, count);
	  uncover(B, i, j+1, count);
	  uncover(B, i+1, j+1, count);
	  uncover(B, i+1, j, count);
	  uncover(B, i+1, j-1, count);
 	  uncover(B, i, j-1, count);
   }
}

int valid(struct cell B[][SIZE], int i, int j)
{
   if (i >= SIZE || i < 0 || j >= SIZE || j < 0)
	  return 0;
   if (B[i][j].show == 1)
	  return 0;
   if (B[i][j].value == -1)
	  return 0;
   return 1;
}


