На этом шаге мы перечислим подготовительные действия.
В начале игры программа должна расставить мины и для каждой клетки поля подсчитать, сколько мин находится в соседних клетках. Функция newGame решает эту задачу:
// новая игра void newGame() { int row, col; // индексы клетки int n = 0; // количество поставленных мин int k; // количество мин в соседних клетках // очистить поле for (row = 1; row <= MR; row++) for (col = 1; col <= MC; col++) Pole[row,col] = 0; // генератор случайных чисел Random^ rnd = gcnew Random(); // расставим мины do { row = rnd->Next(MR) + 1; col = rnd->Next(MC) + 1; if (Pole[row,col] != 9) { Pole[row,col] = 9; n++; } } while (n != NM); // для каждой клетки вычислим количество // мин в соседних клетках for (row = 1; row <= MR; row++) for (col = 1; col <= MC; col++) if (Pole[row,col] != 9) { k = 0; if (Pole[row-1,col-1] == 9) k++; if (Pole[row-1,col] == 9) k++; if (Pole[row-1,col+1] == 9) k++; if (Pole[row,col-1] == 9) k++; if (Pole[row,col+1] == 9) k++; if (Pole[row+1,col-1] == 9) k++; if (Pole[row+1,col] == 9) k++; if (Pole[row+1,col+1] == 9) k++; Pole[row,col] = k; } status = 0; // начало игры nMin = 0; // нет обнаруженных мин nFlag = 0; // нет поставленных флагов }
Функция showPole выводит изображение поля: последовательно, одну за другой рисует клетки. Вывод изображения отдельной клетки выполняет функция Kletka. Функции showPole и Kletka приведены ниже:
// рисует поле void showPole(Graphics^ g, int status) { for (int row = 1; row <= MR; row++) for (int col = 1; col <= MC; col++) this->Kletka(g, row, col, status); } // рисует клетку void Kletka(Graphics^ g, int row, int col, int status) { int x, y; // координаты левого верхнего угла клетки x = (col - 1) * W + 1; y = (row-1)* H + 1; // неоткрытые клетки - серые if (Pole[row,col] < 100) g->FillRectangle(SystemBrushes::ControlLight, x-1, y-1, W, H); // открытые или помеченные клетки if (Pole[row,col] >= 100) { // открываем клетку, открытые - белые if (Pole[row,col] != 109) g->FillRectangle(Brushes::White, x-1, y-1, W, H); else // на этой мине подорвались! g->FillRectangle(Brushes::Red, x-1, y-1, W, H); // если в соседних клетках есть мины, // указываем их количество if ((Pole[row,col] >= 101) && (Pole[row,col] <= 108)) g->DrawString((Pole[row,col]-100).ToString(), gcnew System::Drawing::Font("Tahoma", 10, System::Drawing::FontStyle::Regular), Brushes::Blue, (float)x+3, (float)y+2); } // в клетке поставлен флаг if (Pole[row,col] >= 200) this->flag(g, x, y); // рисуем границу клетки g->DrawRectangle(Pens::Black, x-1, y-1, W, H); // если игра завершена (status = 2), показываем мины if ((status == 2) && ((Pole[row,col] % 10) == 9)) this->mina(g, x, y); }
Функция Kletka используется для вывода изображения поля в начале игры, во время игры и в ее конце. В начале игры (значение параметра status равно в этом случае нулю) функция выводит только контур клетки, во время игры — количество мин, находящихся в соседних клетках, или флажок (если в клетка была открыта щелчком правой кнопкой мыши), а в конце игры отображает исходное состояние клетки (если клетка не была открыта) или результат действия игрока. Информацию о фазе игры функция Kletka получает через параметр status.
На следующем шаге мы рассмотрим действия во время игры.