Заголовочный файл главной формы (Sареr_.h)
#ifndef saper_Н
#define saper_Н
#include <С1asses.hpp>
# include <Controls..hpp>
# include <StdCtrls.hpp>
# include <Forms.hpp>
# include <ExtCtrls.hpp>
# include <Menus.hpp >
class TForm1 : public TForm
{
published:
__ TMainMenu *MainMenu1;
команды главного меню
TMenuItem *N1; // Новая игра
TMenuItem *N2; // команда "? "
//команды меню "? "
TMenuItem *N3; // Справка
TMenuItem *N4; // О программе
void _fastcall FormMauseDown (TObject *Sender, TMouseButton, TshiftState Shift, int X, int Y);
void _fastcall FormPaint (TObject *Sender);
void _fastcall FormCreate (TObject *Sender);
// выбор команды в меню
void _fastcall N1Click (TObject *Sender); // Новая игра
void _fastcall N3Click (TObject *Sender); // Справка
void _fastcall N4Click (TObject *Sender); // О программе
private:
void _fastcall ShowPole (int status); // отображает поле // отображает содержимое клетки
void _fastcall Kletka (int row, int col, int status);
void _fastcall Mina (int x, int y); // рисует мину
void_fastcall Flag (int x, int y); // рисует флаг
public;
_fastcall TForm1 (TComponent* Owner);
};
extern PACKAGE TForm1 *Form1;
#endif
Модуль главной формы (saper_.cpp)
/*
Игра Сапер демонстрирует работу с графикой использованием рекурсии, доступ к файлу справочной информации.
/*
#include <vcl.h>
ttinclude <stdlib.h> // для доступа к ГСЧ
#include <time.h>
#include <stdio.h>
#pragma hdrstop
#include "saper_.h"
#include "saper_2.cpp"
ttpragma package (smart_init)
ttpragma resource "*.dfm"
TForm1 *Form1; // главное окно
_fastcall TForm1: : TForm1 (TComponent*Owner)
: TForm (Owner)
{
}
#define MR 10 // количество клеток по вертикали
#define MC 10 // количество клеток по горизонтали
Idefine NM 10 // количество мин
int Pole [MR+2] [MC+2]; // минное поле
// 0..8 – количество мин в соседних клетках
// 9 – в клетке мина
// 100..109 – клетка открыта
//200..209 – в клетку поставлен флаг
int nMin; // количество найденных мин
int nFlag; // количество поставленных флагов
int status = 0; // 0 – начало игры; 1 – игра; 2 – результат
// смещение игрового поля относительно левого верхнего угла
// поверхности формы
ttdefine LEFT 0 // по X
fdefine TOP 1 // по Y
Idefine W 40 // ширина клетки поля
#define H 40 // высота клетки поля
void_fastcall NewGame( ) ; // новая игра – «разбрасывает» мины
void_fastcall Open (int row, int col); /* открывает текущую и соседние пустые клетки */
// нажатие кнопки мыши на игровом поле
void_fastcall TForm1 : : FormMouseDown (TObject *Sender, TMouseButton , Button, TSiftState Shift, int x, int y)
if (status ==2) return;
if (status ==0) status = 1, -
x= LEFT;
y= TOP;
if (x>0 && y>0)
{
// преобразуем координаты мыши
// в индексы клетки поля
int row = y/H + 1;
int col = x/W + 1;
if (Button == mbLeft)
{
if (Pole [row] [col] == 9 )
{
Pole[row] [col] +=100;
status = 2 ; // игра закончена
ShowPole (status) ;
}
else if (Pole[row] [col] < 9 )
{
Open (row,col);
ShowPole(status);
}
else if (Button == mbRight)
{
nFlag++;
if (Pole [row] [col] == 9)
nMin++;
Pole[row] [col] +=200; // поставили флаг
if (nMin == NM && nFlag == NM)
{
status = 2; // игра закончена
ShowPole(status);
)
else Kletka (row, col, status);
}
}
}
// Функция обработки события OnCreate обычно используется
// для инициализации глобальных переменных
void___fastcall TForm1 :: FormCreate(TObject *Sender)
{
// В неотображаемые элементы массива, которые соответствуют
// клеткам по границе игрового поля, запишем число -3.
// Это значение используется функцией Open для завершения
// рекурсивного процесса открытия соседних пустых клеток.
for (int row=0; row<=MC+1; col++)
Pole [row] [col] = -3;
NewGame( ) ; // «разбросать» мины
Form1->ClientWidth = W*Mc;
Form1->ClientHeight = H*MR+TOP+1;
}
// Вывод поля как результат обработки события Paint
// позволяет проводить любые манипуляции с формой
// во время работы программы
void_fastcall TForm1 : : FormPaint (TObject*Sender)
{
ShowPole(status);
}
// показывает поле
void_fastcall TForm1 : : ShowPole (int status)
{
for (int row = 1; row<=MR; row++)
for (int col = 1; col<=MC; col++)
Kletka (row, col, status);
}
// рисует на экране клетку
void_fastcall TForm1: :Kletka (int row, int col, int status)
{
int x=LEFT+(col-1)*W;
int y=TOP+(row-1)*H;
if (status == 0 ) // начало игры
(
// клетка – серый квадрат
Canvas->Brush->Color=clLtGray;
Canvas->Rectangle(x-1,y-1,x+W,y+H);
return;
}
// во время (status = 1) и в конце (status = 2) игр
if (Pole [row] [col] < 100)
{
// клетка не открыта
Canvas->Brush->Color=clLtGray; // не открытые – серые
Canvas->Rectangle)x-1,y-1,x+W,y+H);
if (status == 2 && Pole [row] [col] == 9)
Mina (x,y) ; // игра закончена, показать мину
return;
}
// клетка открыта
Canavas->Brush->Color = clWhite; // открытые – белые
Canvas->Rectangle(x-1,y-1,x+w,y+H);
if (Pole [row] [col] == 100) // клетка открыта, но она пустая
return;
if (Pole[row] [col] >= 101 && Pole [row] [col]<=108)
{
Canvas->Font->Size=14;
Canvas->Fon->Color=clBlue;
Canvas->TextOutA(x+3,y+2,IntToStr(Pole[row] [col] – 100));
return;
}
if (Pole[row] [col]>=200)
Flag (x,y);
if (Pole[row] [col] == 109) // на этой мине подорвались!
(
Canvas->Brush->Color=clred;
Canvas->rectangle(x,y,x+w,y+H);
}
if ((Pole[row] [col] % 10 == 9) && (status == 2))
Mina (x,y);
}
// рекурсивная функция открывает текущую и все соседние
// клетки, в которых нет мин
void_fastcall Open(int row, int col)
{
if (Pole[row] [col] == 0)
{
Pole [row] [col] = 100;
// открываем клетки слева, справа, снизу и сверху
Open (row, col-1);
Open (row-1,col);
Open (row,col+1);
Open (row+1,col);
// открываем примыкающие диагонально
Open (row-1,col-1);
Open (row-1,col+1);
Open (row+1,col-1);
Open (row+1,col+1);
}
else
// -3 – это граница игрового поля
if (Pole[row] [col] < 100 && Pole [row] [col] !=-3)
Pole [row] [col] += 100;
}
// новая игра – генерирует новое поле
void_fastcall NewGame ( )
{
// Очистим элементы массива, соответствующие отображаемым
// Клеткам, а в неотображаемые (по границе игрового поля)
// запишем число -3. Уникальное значение клеток границы
// используется функцией Open для завершения рекурсивного
// процесса открытия соседних пустых клеток.
int row, col;
for (row=0; row<=MR+1; row++)
for (col=0; col <= MC; col++)
Pole [row] [col] = 0;
// расставим мины
time_t t; // используется ГСЧ
srand ( (unsigned) time (&t); // инициализация ГСЧ
int n=0; // количество мин
do
{
row=rand ( ) % MR +1;
col=rand ( ) % MC +1;
if ( Pole[row] [col] !=9;
{
Pole [row] [col] =9;
n++;
}
}
while (n<10);
// вычисление количества мин в соседних клетках
int k;
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; // нет флагов
}
// рисует мину
void_fastcall TForm1: :Mina (int x, int e )
{
Canvas->Brush->Color=ClGreen;
Canvas->Pen->Color=clBlack;
Canvas->Rectangle (x+16, y+26, x+24, y+30);
// корпус
Canvas->Rectangle (x+8,y+30,x+32,y+34);
Canvas->Pie (x+6,y+28,x+34,y+44,x+34,y+36,x+6,y+36);
// полоса на корпусе
Canvas->MoveTo (x+12,y+32); Canvas->LineTo(x+28,y+32);
// основание
Canvas->MoveTo(x+8,y+32); Canvas->LineTo(x+32,y+36);
// вертикальный «ус»
Canvas->MoveTo(x+20,y+22); Canvas->LineTo(x+20,y+26);
// боковые «усы№
Canvas->MoveTo(x+8,y+30); Canvas->LineTo (x+6,y+28);
Canvas->Moveto(x+32,y+30); Canvas->LineTo(x+34,y+28);
// рисует флаг
TForm1 : : Flag (int x, int y)
{
TPoint p[4]; // координаты флажка и нижней древка
// точки флажка
p[0].x=x+4; p[0].y=y+4;
p[1].x=x+30; p[1].y=y+12;
p[2].x=x+4; p[2].y=y+20;
// установим цвет кисти и карандаша
Canvas-.Brush->Color = clRed;
Canvas->Pen->Color = clRed; // чтобы контур флажка был красный
Canvas->Polygon(p, 2); // флажок
// древко
Canvas->Pen->Color = clBlack;
Canvas->MoveTo(p[0].x, p[0].y);
Canvas->LineTo(x+4,y+36);
TPoint m[5]; // буква M
m[0] .x=x+8; m[0] .y=y+14;
m[1] .x=x+8; m[1] .y=y+8;
m[2] .x=x+10; m[2] .y=y+10;
m[3] .x=x+12; m[3] .y=y+8;
m[4] .x=x+12; m[4] .y=y+14;
Canvas->Pen->Color = clwhite;
Canvas->Polyline(m,4);
Canvas->Pen->Color = clBlack;
}
// команда главного меню Новая игра
void_fastcall TForm: :N1Click(TObject *Sender)
{
Newame ( );
ShowPole (status);
}
// выбор в меню "?" команды о программе
void_fastcall TForm1: :N4click (TObject *Sender)
{
AboutForm->Top = Form!->Top + Form!->Height/2
- AboutForm->Height/2;
AbotForm->Left = Form1->Left + Form1->Width/2
- AboutForm->Width/2;
AboutForm->showModal ( ) ;
}
// выбор в меню "?" команды Справка
void_fastcall Tform1: :N3click (TObject *sender)
(
WinHelp (Form1->Handle, "saper.hlp", HELP_CONTEXT, 1);
}
Изменил(а) Kest, 02-06-2010 20:08 |