// generate number tiles
 private static void GenerateNumbers()
 {
     // generate number grids
     for (int i = 0; i < _r; i++)
     {
         for (int j = 0; j < _c; j++)
         {
             MinesweeperGrid picked_grid = grid[i, j];
             if (!picked_grid.IsMine)
             {
                 int count = 0;
                 // 3 x 3 scan but clamp max and min within array
                 for (int k = Math.Max(0, i - 1); k < Math.Min(i + 2, _r); k++)
                 {
                     for (int l = Math.Max(0, j - 1); l < Math.Min(j + 2, _c); l++)
                     {
                         // count the total of adjacent mines
                         if (grid[k, l].IsMine)
                         {
                             count++;
                         }
                     }
                 }
                 picked_grid.Value = count;
             }
         }
     }
 }
        // reveal tiles based on tile state
        private static void Reveal(int i, int j)
        {
            MinesweeperGrid g = grid[i, j];
            Button          b = MinesweeperGame.GetButton(i, j);

            b.FlatStyle = FlatStyle.Flat;
            b.BackColor = System.Drawing.Color.LightGray;

            // show bomb if its a mine
            if (g.IsMine)
            {
                b.Text = "\uD83D\uDCA3";
            }
            // show number with colors
            else if (g.Value > 0)
            {
                b.Text = g.Value.ToString();
                switch (g.Value)
                {
                case 1:
                    b.ForeColor = System.Drawing.Color.Blue;
                    break;

                case 2:
                    b.ForeColor = System.Drawing.Color.Green;
                    break;

                case 3:
                    b.ForeColor = System.Drawing.Color.Red;
                    break;

                case 4:
                    b.ForeColor = System.Drawing.Color.DarkBlue;
                    break;

                case 5:
                    b.ForeColor = System.Drawing.Color.DarkRed;
                    break;

                case 6:
                    b.ForeColor = System.Drawing.Color.DarkCyan;
                    break;
                }
            }
        }
        // initialize game board
        public static void Initialize(int r, int c, int m)
        {
            _r = r;
            _c = c;
            _m = m;

            grid = new MinesweeperGrid[_r, _c];

            // create an empty r by c matrix
            for (int i = 0; i < _r; i++)
            {
                for (int j = 0; j < _c; j++)
                {
                    grid[i, j] = new MinesweeperGrid(false, 0);
                }
            }

            GenerateMines();
            GenerateNumbers();
        }
        // recursively reveal empty tiles
        private static void RevealEmpties(int i, int j)
        {
            MinesweeperGrid g = grid[i, j];

            Reveal(i, j);

            // base case of number tile --> exit
            if (g.Value != 0)
            {
                return;
            }

            // make sure recursion doesn't go back
            g.Value = -1;

            // get adjacent tiles
            List <Tuple <int, int> > adjs = new List <Tuple <int, int> >();

            if (i > 0)
            {
                MinesweeperGrid adj_g = grid[i - 1, j];
                adjs.Add(new Tuple <int, int>(i - 1, j));
            }
            if (i < grid.GetLength(0) - 1)
            {
                MinesweeperGrid adj_g = grid[i + 1, j];
                adjs.Add(new Tuple <int, int>(i + 1, j));
            }
            if (j > 0)
            {
                MinesweeperGrid adj_g = grid[i, j - 1];
                adjs.Add(new Tuple <int, int>(i, j - 1));
            }
            if (j < grid.GetLength(1) - 1)
            {
                MinesweeperGrid adj_g = grid[i, j + 1];
                adjs.Add(new Tuple <int, int>(i, j + 1));
            }
            if (i > 0 && j > 0)
            {
                MinesweeperGrid adj_g = grid[i - 1, j - 1];
                adjs.Add(new Tuple <int, int>(i - 1, j - 1));
            }
            if (i < grid.GetLength(0) - 1 && j > 0)
            {
                MinesweeperGrid adj_g = grid[i + 1, j - 1];
                adjs.Add(new Tuple <int, int>(i + 1, j - 1));
            }
            if (i > 0 && j < grid.GetLength(1) - 1)
            {
                MinesweeperGrid adj_g = grid[i - 1, j + 1];
                adjs.Add(new Tuple <int, int>(i - 1, j + 1));
            }
            if (i < grid.GetLength(0) - 1 && j < grid.GetLength(1) - 1)
            {
                MinesweeperGrid adj_g = grid[i + 1, j + 1];
                adjs.Add(new Tuple <int, int>(i + 1, j + 1));
            }

            // reveal each adjacent tiles
            foreach (Tuple <int, int> adj in adjs)
            {
                RevealEmpties(adj.Item1, adj.Item2);
            }
        }