Введение
Целью данной расчетно-графической работы является закрепление полученных теоретических знаний в области программирования на языке C# путем написания игрового приложения «Сапер». Разрабатываемая программа является аналогом стандартной игры операционной системы Windows.
В процессе игры необходимо за отведенное время «разминировать» поле, используя подсказки в открытых клетках, указывающие на количество бомб, окружающих данную клетку. Управление игрой осуществляется с помощью мыши и главного меню программы.
1 РАЗРАБОТКА ТЕХНИЧЕСКОГО И ЭСКИЗНОГО ПРОЕКТА ПРОГРАММЫ
1.1 Назначение и область применения
Необходимо разработать игровое приложение "Сапер". Целью игры является «разминирование» всех закрытых ячеек поля за определенное время. На ячейки с бомбами необходимо установить флажки с помощью правой клавиши мыши. Открытие ячейки производится левой клавишей. Игра имеет три уровня сложности с полями различных размеров и процентным количеством мин. Распределение мин производится путем генерации псевдослучайной последовательности чисел. Игрок выигрывает, если за отведенное время удалось установить флажки на все бомбы и открыть остальные ячейки. Лучшие результаты записываются в таблицу рекордов.
1.2 Технические характеристики и постановка задачи
Поле представляет собой двумерный массив чисел, каждое значение которого определяет содержимое соответствующей ячейки. В программе применяется двойная буферизация изображений, что ускоряет работу с графикой. Минное поле отображается при помощи компонента PictureBox, на котором отрисовывается заранее созданное изображение класса Image.
Для создания таймера обратного отсчета был использован компонент timer, в обработчике которого изменяется значение времени и при достижении нуля вызывается функция завершения игры.
С помощью компонента menuStrip создано главное меню программы, содержащая основные элементы управления, выполняющие различные функции: начало новой игры, изменение уровня сложности, просмотр правил игры и сведений об авторе.
1.3 Описание алгоритма
При запуске программы происходит проверка наличия необходимых файлов, содержащих изображения и таблицу рекордов, а также запускается функция, генерирующая последовательность случайных чисел. На основе данных, полученных из этой функции, поле заполняется минами, после чего вызывается функция, заполняющая значениями оставшиеся ячейки, записывая в них количество мин, прилегающих к этой ячейки.
По нажатию мышкой на поле происходит запуск таймера, при условии, что это было первый клик с начала игры; и проверяется, какая именно клавиша была нажата. Если нажата правая клавиша мыши, то на месте ячейки отрисовывается флаг или убирается, если таковой уже присутствовал; иначе либо в ячейке отображается количество окружающих бомб, либо, если в ячейке была мина, вызывается функция завершения игры.
1.4 Выбор состава технических и программных средств
Данная программа написана на языке C# в среде программирования Microsoft Visual Studio 2010, версия 10.0.303191.1 RTMRel, Microsoft .NET Framework версия 4.0. Для запуска программы достаточно запустить исполняемый файл с расширение exe.
Минимальные системные требования:
Видеокарта 256Мб;
Оперативная память 32Мб;
Компьютерная мышь.
2 РАЗРАБОТКА РАБОЧЕГО ПРОЕКТА
2.1 Разработка программы
Для разработки игрового приложения "Сапер" использовались средства визуального программирования C# Microsoft Visual Studio.
Проект включает в себя следующие файлы:
sapper.exe |
|
Images/ |
|
|
Bomba.png |
|
Explosen.png |
|
Flag.png |
|
Question.png |
Data/ |
|
|
Info.dat |
В программе реализован один главный класс Form1, код которого представлен ниже.
public partial class Form1 : Form
{
//global variables
settings formSettings;
formStatistics formStatistics;
About formAbout;
Rules formRules;
Boolean endOfGame = true;
Boolean gamePause = false;
//поле для рисования
Bitmap fieldImg;
Graphics fieldImgGraphics;
Graphics GraphicsbombFields;
Brush
brushClearField, //пустое полу (0)
brushFlagField, //поле с флажком (-4)
brushQuestionField, //поле с вопросом (-3)
brushBombField, //поле с бомбой (-2)
brushForUse; //используемая кисть
//(-6) - разминированная бомба
LinearGradientBrush
brushStartField,
brushDigitField,
brushMouseHover;
Image
flagImage,
questionImage,
imageForUse,
animationBoomImage,
bombImage;
int explosionX, explosionY; //положение взрыва
int explosionSlideNumber = 0; //номер слайда
int explosionCountSlide = 9; //количество из-й взрыва
int explosionSlideWidth = 64; //ширина одного слайда
int explosionSlideHeight = 64; //высота одного слайда
Pen startSquarePen;
//для расстановки мин
int sizeField; //размеры минного поля (поле квадратное)
int sizeOneField; //размеры одной ячейки (тоже квадратная)
int countField; //кол-во ячеек
int[] masNumbers = new int[] { 1,2,3,4,5,6,7,8 }; //массив цифр
int countBomb; //количество бомб
int countFlag;
int[,] bombField; //поле мин
int[,] bombOpenedField; //поле с окрытыми клетками
//для подсвечивания при наведении
int
oldRow = -1,
oldCol = -1;
//таймер
int lostTime;
//для вкл таймера при первом клике
Boolean firstClick = false;
//whiteLine
int
topTransRect = -1, //top coord
whiteLineHeight = 30,
numLine = 1;
Boolean whiteLineShow = false;
Bitmap whiteLine;
Graphics whiteLineGraphics;
LinearGradientBrush transBrush = new LinearGradientBrush(new Rectangle(0, 0, 250, 30),
Color.White, Color.FromArgb(0, 255, 255, 255), 90);
//games info
int countNoteString = 9;
int[] gameInfoList;
//1:novice win
//2:novice lose
//3:master win
//4:master lose
//5:extra win
//6:extra lose
//установлено лучшее время
Boolean setBestTime = false;
//для чтения статистики из файла
StreamReader gameInfoReader;
//
public Form1()
{
InitializeComponent();
//массив чисел со статистикой
gameInfoList = new int[countNoteString];
//окно настроек
formSettings = new settings();
formStatistics = new formStatistics();
formAbout = new About();
formRules = new Rules();
brushFlagField = new SolidBrush(Color.DarkGoldenrod);
brushBombField = new SolidBrush(Color.Coral);
brushQuestionField = new SolidBrush(Color.Cyan);
brushClearField = new SolidBrush(Color.Black);
//изображения
if (!File.Exists("images/flag.png") || !File.Exists("images/question.png") ||
!File.Exists("images/bomba.png") ||
!File.Exists("images/explosen.png"))
{
MessageBox.Show("Necessary files doesnt exists");
Environment.Exit(0);
}
flagImage = Image.FromFile("images/flag.png"); //флаг
questionImage = Image.FromFile("images/question.png"); //вопрос
animationBoomImage = Image.FromFile("images/explosen.png"); //взрыв
bombImage = Image.FromFile("images/bomba.png"); //бомба
startSquarePen = new Pen(Color.Black, 1);
}
//поле рисования
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (endOfGame) return;
int row = e.X / sizeOneField;
int col = e.Y / sizeOneField;
if (col > sizeField - 1) col = sizeField - 1;
if (row > sizeField - 1) row = sizeField - 1;
if (oldCol == col && oldRow == row) return;
//если закрыта
if (bombOpenedField[row, col] == -1)
{
if (!(oldRow < 0) && !(oldCol < 0))
{
if (bombOpenedField[oldRow, oldCol] == -1)
{
GraphicsbombFields.FillRectangle(brushStartField, oldRow * sizeOneField,
oldCol * sizeOneField, sizeOneField, sizeOneField);
GraphicsbombFields.DrawRectangle(startSquarePen, oldRow * sizeOneField,
oldCol * sizeOneField, sizeOneField, sizeOneField);
}
}
oldRow = row;
oldCol = col;
//ShowFieldMines();
GraphicsbombFields.FillRectangle(brushMouseHover, row * sizeOneField,
col * sizeOneField, sizeOneField, sizeOneField);
GraphicsbombFields.DrawRectangle(startSquarePen, row * sizeOneField,
col * sizeOneField, sizeOneField, sizeOneField);
}
else
{
if (!(oldRow < 0) && !(oldCol < 0))
{
if (bombOpenedField[oldRow, oldCol] == -1)
{
GraphicsbombFields.FillRectangle(brushStartField, oldRow * sizeOneField,
oldCol * sizeOneField, sizeOneField, sizeOneField);
GraphicsbombFields.DrawRectangle(startSquarePen, oldRow * sizeOneField,
oldCol * sizeOneField, sizeOneField, sizeOneField);
oldCol = -1;
oldRow = -1;
} }}}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if (endOfGame) return;
if (!firstClick)
{
gameTimer.Enabled = true;
firstClick = true;
}
int row = e.X / sizeOneField;
int col = e.Y / sizeOneField;
if (row > sizeField-1) row = sizeField-1;
if (col > sizeField-1) col = sizeField-1;
if (e.Button == MouseButtons.Right)
{
switch (bombOpenedField[row, col])
{
//закрытая
case -1:
bombOpenedField[row, col] = -4;
countFlag--;
label2.Text = countFlag.ToString();
break;
//флаг
case -4:
bombOpenedField[row, col] = -3;
countFlag++;
label2.Text = countFlag.ToString();
break;
//вопрос
case -3:
bombOpenedField[row, col] = -1;
break;
}
oldCol = -1;
oldRow = -1;
ShowFieldMines();
}
//left mouse button
if (e.Button == MouseButtons.Left)
{
//если закрты или с вопросом
if ((bombOpenedField[row, col] == -1) || (bombOpenedField[row, col] == -3))
{
//если цифра
if (masNumbers.Contains(bombField[row, col]))
{
bombOpenedField[row, col] = bombField[row, col];
}
switch (bombField[row, col])
{
//если бомба
case -2:
explosionX = row * sizeOneField;
explosionY = col * sizeOneField;
bombAnimationTimer.Enabled = true;
//запускаем таймер, по окончании анимации показываем окошко "Конец"
endOfGame = true;
break;
//если пустая ячейка
case 0:
GraphicsbombFields.FillRectangle(brushClearField, row * 25, col * 25, 25, 25);
openClearField(row, col);
break;
}}
GraphicsbombFields.DrawRectangle(startSquarePen, row * 25, col * 25, 24, 24);
if (!endOfGame)
{
oldCol = -1;
oldRow = -1;
ShowFieldMines();
}
//если все ячейки открыты openedCountField и flagCount = кол-во бомб , тогда "you win!!!"
}}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
if (endOfGame) return;
if (!(oldRow < 0) && !(oldCol < 0))
{
GraphicsbombFields.FillRectangle(brushStartField, oldRow * sizeOneField,
oldCol * sizeOneField, sizeOneField, sizeOneField);
GraphicsbombFields.DrawRectangle(startSquarePen, oldRow * sizeOneField,
oldCol * sizeOneField, sizeOneField, sizeOneField);
oldCol = -1;
oldRow = -1;
}
}
//форма
private void Form1_Paint(object sender, PaintEventArgs e)
{
pictureBox1.Update();
ShowFieldMines();
}
private void Form1_Shown(object sender, EventArgs e)
{
//информация о предыдущих играх
if (!File.Exists("data/info.dat"))
{
for (int i = 0; i < countNoteString; i++)
gameInfoList[i] = 0;
}
else
{
gameInfoReader = new StreamReader("data/info.dat");
for (int i = 0; i < countNoteString; i++)
gameInfoList[i] = Convert.ToInt16(gameInfoReader.ReadLine());
gameInfoReader.Close();
}
setStatistics(gameInfoList, 0);
startNewGame();
pictureBox1.Update();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Shift && e.Control && e.KeyCode == Keys.R)
{
for (int i = 0; i < sizeField; i++)
for (int j = 0; j < sizeField; j++)
if (bombField[i, j] == -2)
bombOpenedField[i, j] = -4;
else
bombOpenedField[i, j] = bombField[i, j];
endOfGame = true;
ShowFieldMines();
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
StreamWriter gameInfoFles = new StreamWriter("data/info.dat");
for (int i = 0; i < countNoteString; i++)
gameInfoFles.WriteLine(gameInfoList[i]);
gameInfoFles.Close();
fieldImg.Dispose();
fieldImgGraphics.Dispose();
}
//меню
private void newGameToolStripMenuItem_Click(object sender, EventArgs e)
{
//изменять надо по-хорошему в функции bombFeldSettings, but... тама формы еще нету
startNewGame();
ActiveForm.Refresh();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
//настройки
private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
{
formSettings.StartPosition = FormStartPosition.CenterParent;
formSettings.ShowDialog();
if (formSettings.DialogResult == DialogResult.OK)
startNewGame();
}
//стастика
private void statisticsToolStripMenuItem_Click(object sender, EventArgs e)
{
formStatistics.StartPosition = FormStartPosition.CenterParent;
formStatistics.ShowDialog();
}
//обо мне
private void authorToolStripMenuItem_Click(object sender, EventArgs e)
{
formAbout.StartPosition = FormStartPosition.CenterParent;
formAbout.ShowDialog();
}
//правила
private void rulesToolStripMenuItem_Click(object sender, EventArgs e)
{
formRules.StartPosition = FormStartPosition.CenterParent;
formRules.ShowDialog();
}
//таймеры
//анимация выигрыша
private void bombAnimationTimer_Tick(object sender, EventArgs e)
{
GraphicsbombFields = pictureBox1.CreateGraphics();
if (explosionSlideNumber == explosionCountSlide - 1)
{
GraphicsbombFields.FillRectangle(brushStartField, explosionX, explosionY, sizeOneField, sizeOneField);
GraphicsbombFields.DrawRectangle(startSquarePen, explosionX, explosionY, sizeOneField, sizeOneField);
explosionSlideNumber = 0;
bombAnimationTimer.Enabled = false;
showAllBombs();
resultGame("Game over", formSettings.difficult*3+1, false);
return;
}
GraphicsbombFields.FillRectangle(brushStartField, explosionX, explosionY, sizeOneField, sizeOneField);
GraphicsbombFields.DrawImage(animationBoomImage, new Rectangle(explosionX, explosionY, sizeOneField, sizeOneField),
new Rectangle(explosionSlideNumber * explosionSlideWidth, 0, explosionSlideHeight, explosionSlideWidth), GraphicsUnit.Pixel);
GraphicsbombFields.DrawRectangle(startSquarePen, explosionX, explosionY, sizeOneField, sizeOneField);
explosionSlideNumber++;
}
//стаймер обратного отсчета бомбы
private void gameTimer_Tick(object sender, EventArgs e)
{
lostTime--;
label1.Text = lostTime.ToString();
if (lostTime == 0)
{
resultGame("You lose.", formSettings.difficult * 3 + 1, false);
}
}
//functions
private void resultGame(string mesText, int numberString, bool victory)
{
int
timeComplete = 0,
showTimeComplete;
string textToMessage = "";
showTimeComplete = formSettings.timeLevel - lostTime;
if (victory)
timeComplete = showTimeComplete;
gameInfoList[numberString] += 1;
setStatistics(gameInfoList, timeComplete);
gameTimer.Enabled = false;
endOfGame = true;
textToMessage = mesText;
if (!setBestTime)
textToMessage += "\nGame time: ";
else
{
if (formStatistics.extraBestTime != 0)
textToMessage += "\nYou are ZADROT, odnako\n";
textToMessage += "\nYou have best time!\nNew record: ";
}
MessageBox.Show(textToMessage + showTimeComplete.ToString());
startNewGame();
}
private void ShowFieldMines()
{
Boolean showDigit, paintWithBrush, bombFounded;
int countFlags = 0, countOpened = 0;
for (int i = 0; i < sizeField; i++)
for (int j = 0; j < sizeField; j++)
{
showDigit = false;
paintWithBrush = true;
bombFounded = false;
//если число
if (masNumbers.Contains(bombOpenedField[i, j]))
{
brushForUse = brushDigitField;
showDigit = true;
countOpened++;
}
switch (bombOpenedField[i, j])
{
//если пустое поле
case 0:
brushForUse = brushClearField;
countOpened++;
break;
//если закрытое поле
case -1:
brushForUse = brushStartField;
break;
//если бомба
case -2:
imageForUse = bombImage;
paintWithBrush = false;
break;
//если вопрос
case -3:
imageForUse = questionImage;
paintWithBrush = false;
break;
//если флаг
case -4:
imageForUse = flagImage;
paintWithBrush = false;
countFlags++;
break;
//если под курсором
case -5:
brushForUse = brushMouseHover;
break;
//разминированная мина (show при проигрыше)
case -6:
fieldImgGraphics.FillRectangle(brushStartField, i * sizeOneField, j * sizeOneField, sizeOneField, sizeOneField);
fieldImgGraphics.DrawImage(bombImage, new Rectangle(i * sizeOneField, j * sizeOneField, sizeOneField, sizeOneField));
fieldImgGraphics.DrawImage(flagImage, new Rectangle(i * sizeOneField, j * sizeOneField, sizeOneField, sizeOneField));
bombFounded = true;
break;
}
//фон
if (!bombFounded)
{
if (paintWithBrush)
{
fieldImgGraphics.FillRectangle(brushForUse, i * sizeOneField,
j * sizeOneField, sizeOneField, sizeOneField);
}
else
{
fieldImgGraphics.FillRectangle(brushStartField, i * sizeOneField, j * sizeOneField, sizeOneField, sizeOneField);
fieldImgGraphics.DrawImage(imageForUse, new Rectangle(i * sizeOneField, j * sizeOneField, sizeOneField, sizeOneField));
}
}
//цифра
if (showDigit)
{
fieldImgGraphics.DrawString(
Convert.ToString(bombOpenedField[i, j]),
new Font(FontFamily.GenericSerif, 12.0F, FontStyle.Bold),
new SolidBrush(Color.White),
i * sizeOneField + 6, j * sizeOneField + 3);
showDigit = false;
}
//рамка
fieldImgGraphics.DrawRectangle(startSquarePen, i * sizeOneField,
j * sizeOneField, sizeOneField, sizeOneField);
}
if (!(topTransRect < 0))
fieldImgGraphics.DrawImage(whiteLine, 0, topTransRect);
if (topTransRect > numLine * sizeOneField)
{
for (int j = 0; j < sizeField; j++)
if (bombField[j, numLine - 1] == -2)
if (bombOpenedField[j, numLine - 1] == -4)
bombOpenedField[j, numLine - 1] = -6;
else
bombOpenedField[j, numLine - 1] = bombField[j, numLine - 1];
numLine++;
}
pictureBox1.Image = fieldImg;
//если все поля открыты и флаги установлены
if (!whiteLineShow)
{
if (countFlags == countBomb && countOpened == (countField - countBomb))
{
whiteLineShow = true; //пошла полоска
gameTimer.Enabled = false; //выкл таймер бомбы
whiteLineTimer.Enabled = true; //таймер полоски вкл
}
}
}
public void startNewGame()
{
pictureBox1.Width = formSettings.defFieldWidth + 1;
pictureBox1.Height = pictureBox1.Width;
panel1.Top = pictureBox1.Bottom;
panel1.Left = pictureBox1.Width / 2 - panel1.Width / 2;
//fvfvfvffgfggfgfvfvf O_j never use ActiveForm.Height & Width
ActiveForm.Width = pictureBox1.Width + pictureBox1.Left * 2 + 8;
ActiveForm.Height = pictureBox1.Width + 21 * 2 + 40 + panel1.Height;
lostTime = formSettings.timeLevel;
label1.Text = lostTime.ToString();
countFlag = formSettings.countBombs;
label2.Text = countFlag.ToString();
bombFieldSettings(sizeField, sizeOneField, countBomb);
ShowFieldMines();
setBestTime = false;
endOfGame = false;
firstClick = false;
gameTimer.Enabled = false;
}
private void showAllBombs()
{
for (int i = 0; i < sizeField; i++)
for (int j = 0; j < sizeField; j++)
if (bombField[i, j] == -2)
if (bombOpenedField[i, j] == -4)
bombOpenedField[i, j] = -6;
else
bombOpenedField[i, j] = bombField[i, j];
ShowFieldMines();
}
//рекурсивная функция обработки пустой ячейки
private void openClearField(int row, int col)
{
//передается пустая ячейка
bombOpenedField[row, col] = bombField[row, col]; //открываем ее на поле
for (int x = row - 1; x <= row + 1; x++)
{
if ((x < 0) || (x > sizeField - 1)) continue; //проверка на границы поля
for (int y = col - 1; y <= col + 1; y++)
{
if ((y < 0) || (y > sizeField - 1)) continue; //проверка на границы поля
if (bombOpenedField[x, y] == -1) //если закрыта
{
if (bombField[x, y] == 0) //если пустая
openClearField(x, y); //вызываем сами себя
if (masNumbers.Contains(bombField[x, y])) //если это число
bombOpenedField[x, y] = bombField[x, y];
}}}}
//расставнока мин
private void setRandomMines()
{
//для случайного выбора
Random rand = new Random();
//массив с псевдослуч послед-ю
int[] listNumberBomb;
listNumberBomb = new int[countField];
//последовательность чисел от 0 до мах кол-ва бомб
List<int> listDigits = new List<int>();
//заполняем массив с посл-ю чисел значенимя -1 - не выбрано
for (int i = 0; i < countField; i++)
{
listNumberBomb[i] = -1;
listDigits.Add(i); //заполняем числа 0-countField
}
//выбираем случаный элемент из списка и заносим число в массив с минами
for (int i = 0; i < countBomb; i++)
{
int pos = rand.Next(0, listDigits.Count);
listNumberBomb[i] = listDigits[pos];
listDigits.Remove(listNumberBomb[i]);
}
//заполняем матрицу нулями
for (int i = 0; i < sizeField; i++)
for (int j = 0; j < sizeField; j++)
bombField[i, j] = 0;
//расставляем бомбы на поле
for (int i = 0; i < countBomb; i++)
{
//if (matBomb[i] < 0) continue;
int col = listNumberBomb[i] / sizeField;
int row = listNumberBomb[i] % sizeField;
bombField[col, row] = -2; //-2 - бомба
}
//расчет количества прилегающих бомб
//mat[i, j] - матрица бомб
for (int i = 0; i < sizeField; i++)
for (int j = 0; j < sizeField; j++)
{
if (bombField[i, j] == -2)
{
for (int k = i - 1; k <= i + 1; k++)
{
if ((k < 0) || (k > sizeField - 1)) continue;
for (int l = j - 1; l <= j + 1; l++)
{
if ((l < 0) || (l > sizeField - 1) || (bombField[k, l] == -2))
continue;
bombField[k, l] = bombField[k, l] + 1;
} }}}}
//изменение размера поля
private void bombFieldSettings(int newSizeField, int sizeOne, int newCountBombs)
{
newSizeField = formSettings.countFields; //кол-во ячеек в строке
sizeOne = formSettings.sizeOneField; //ширина одной ячейки
newCountBombs = formSettings.countBombs; //количество бомб
//канвас для рисования
GraphicsbombFields = pictureBox1.CreateGraphics();
//кисть градиентной заливка для поля
brushMouseHover = new LinearGradientBrush(new Rectangle(0, 0, pictureBox1.ClientSize.Width,
pictureBox1.ClientSize.Height),
Color.LightCyan, Color.White, 30);
brushStartField = new LinearGradientBrush(new Rectangle(0, 0, pictureBox1.ClientSize.Width,
pictureBox1.ClientSize.Height),
Color.GhostWhite, Color.Gray, 30);
brushDigitField = new LinearGradientBrush(new Rectangle(0, 0, pictureBox1.ClientSize.Width,
pictureBox1.ClientSize.Height), Color.Green, Color.Indigo, 60);
//размеры поля
sizeField = newSizeField;
sizeOneField = sizeOne; //размеры ячейки
//создаем поле для рисования
fieldImg = new Bitmap(sizeOneField * sizeField, sizeOneField * sizeField);
fieldImgGraphics = Graphics.FromImage(fieldImg);
//кол-во ячеек
countField = newSizeField * newSizeField;
//кол-во бомб
countBomb = newCountBombs; //20-25-30%
bombField = new int[sizeField, sizeField];
bombOpenedField = new int[sizeField, sizeField];
//whiteLne
whiteLine = new Bitmap(sizeOneField * countField, whiteLineHeight);
whiteLineGraphics = Graphics.FromImage(whiteLine);
whiteLineGraphics.FillRectangle(transBrush, 0, 0, sizeOneField * countField, whiteLineHeight);
//установка мин
setRandomMines();
//все клетки закрыты
for (int i = 0; i < sizeField; i++)
for (int j = 0; j < sizeField; j++)
bombOpenedField[i, j] = -1;
}
//изменение статистики
private void setStatistics(int[] stat, int timeComplete)
{
formStatistics.noviceWin = stat[0];
formStatistics.noviceLose = stat[1];
formStatistics.noviceBestTime = stat[2];
formStatistics.masterWin = stat[3];
formStatistics.masterLose = stat[4];
formStatistics.masterBestTime = stat[5];
formStatistics.extraWin = stat[6];
formStatistics.extraLose = stat[7];
formStatistics.extraBestTime = stat[8];
if (timeComplete > 0)
{
switch (formSettings.difficult)
{
case 0:
if (formStatistics.noviceBestTime == 0 ||
timeComplete < formStatistics.noviceBestTime)
{
formStatistics.noviceBestTime = timeComplete;
gameInfoList[2] = timeComplete;
setBestTime = true;
}
break;
case 1:
if (formStatistics.masterBestTime == 0 ||
timeComplete < formStatistics.masterBestTime)
{
formStatistics.masterBestTime = timeComplete;
gameInfoList[5] = timeComplete;
setBestTime = true;
}
break;
case 2:
if (formStatistics.extraBestTime == 0 ||
timeComplete < formStatistics.extraBestTime)
{
formStatistics.extraBestTime = timeComplete;
gameInfoList[8] = timeComplete;
setBestTime = true;
}
break;
}}}
//полоска - сканер
private void whiteLineTimer_Tick(object sender, EventArgs e)
{
topTransRect += 4;
ShowFieldMines();
if (topTransRect > sizeOneField * sizeField)
{
ShowFieldMines();
topTransRect = -1;
numLine = 1;
whiteLineTimer.Enabled = false;
whiteLineShow = false;
resultGame("You WIN!!!", formSettings.difficult * 3, true);
}
} }}
2.2 Тестирование программы
Для проверки работоспособности программы установим сложность и пройдем игру.
Рисунок 1 - Начало игры
Рисунок 2 - Победа игрока