Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Задача 37.Compact Disk Player (версия 2)



Программа CompactDiskPlayer (Рис. 44), позволяет прослушать компакт-диск. Как можно видеть, заголовок и граница окна во время работы программы не отображаются, тем не менее пользователь может переместить окно программы, установив указатель мыши на изображение индикатора (в поле компонента shapei).

 

 

Рис 44

Вывод: В этой программе мы научились воспроизводить с помощью программы музыку с CD- дискеты.

Листинг

// нажатие кнопки мыши в поле компонента Shapei void fastcall TForml:: ShapelMouseDown(TObject *Sender,

150 Часть 1. Примерыизадачи

TMouseButton Button, TShiftState Shift, int X, int Y)

// запомнить координаты точки, в которой // пользователь нажал кнопку мыши рх = X; РУ = Y;

// нажатая в поле компонента Shapel кнопка мыши отпущена void fastcall TForml:: ShapelMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { Forml-> Left = Forml-> Left + X - px; Forml-> Top = Forml-> Top + Y - py;

// щелчок на кнопке Off (Выключить) void.fastcall TForml:: SpeedButton4Click(TObject *Sender) { // завершение работы программы MediaPlayer-> Stop(); Forml-> Close();

Задача 38.VideoPlayer

Программа VideoPlayer (Рис. 45), позволяет просмотреть видеоролик форматов AVI или MPG. Выбор клипа осуществляется в стандартном окне Открыть файл, которое становится доступным в результате щелчка на кнопке Eject (speedButtoni). Кнопка speedButton2 используется как для активизации процесса воспроизведения, так и для его приостановки. Картинки для кнопки загружаются из ресурса программы. Следует обратить внимание на то, что программа определяет размер кадров видеоролика. Это Мультимедиа 151

позволяет разместить экран в центре формы и, если размер кадров превышает размер рабочей области формы, выполнить масштабиование.

Рис 45

Вывод: В этой программе мы научились загружать и воспроизводить видео с помощью компонентов С++.

Листинг

// эти макросы обеспечивают перевод интервала времени, // выраженного в миллисекундах, в минуты и секунды #define MINUTE(ms) ((ms/1000)/60) #define SECOND(ms) ((ms/1000)%60)

// картинкидлякнопок Graphics:: TBitmap *fcmPlay; // Play Graphics:: TBitmap *fcmPause; // Pause

fastcall TForml:: TForml(TComponent* Owner): TForm(Owner)

{

kmPlay = new Graphics:: TBitmap(); fcmPause = new Graphics:: TBitmap();

// загрузитькартинкидлякнопки Play/Stop bmPlay-> LoadFromResourceID((int)HInstance, 101); bmPause-> LoadFromResourceID((int)HInstance, 102); // отобразитькартинку SpeedButton2-> Glyph-> Assign(bmPlay); MediaPlayerl-> Display = Forml;

// возвращаетразмеркадра void.fastcall GetFrameSize(AnsiString f, int *w, int *h) { if ( f.Pos(".avi" ) == 0 ) { // пользовательвыбрал mpg-файл *w = 352; *h = 240; return;

// *** Пользователь выбрал AVI-файл ***

Мультимедиа 153

// В заголовке AVI-файла есть информация о размере кадра struct { char RIFF[4]; // строка RIFF long int nu_l15]; //не используется char AVIH[4]; // строка AVIH long int nu_2[9]; // не используется long int w; // ширина кадра long int h; // высота кадра } header;

TFileStream *fs; // поток для чтения заголовка файла

/* операторы объявления потока и его создания можно объединить: TFileStream *fs = new TFileStreamff, fmOpenRead); */

fs = new TFileStream(f, fmOpenRead); г

fs-> Read(& header, sizeof(header));

*w = header.w; *h = header.h; delete fs;

// открыть поток для // чтения // прочитать // заголовок файла

// щелчок на кнопке Eject (выбор видеоклипа) void fastcall TForml:: SpeedButtonlClick(TObject *Sender) { int fw, fh; // размер кадра клипа int top, left; // левый верхний угол экрана int sw, sh; /, / размер экрана (ширина, высота)

int mw, mh; // максимально возможный размер экрана // (определяется текущим размером формы)

154 Часть 1. Примеры и задачи

float kw, kh; // коэф-ты масштабирования кадра // по ширине и высоте float к; // коэффициент масштабирования кадра

OpenDialogl-> Title = " Выбор клипа"; OpenDialogl-> InitialDir = " "; OpenDialogl-> Filter = " Все форматы|*.avi; *.mpg; *.mpegI" " AVI|*.avi|MPG|*.mpg|MGEG|*.mpeg";

if (! OpenDialogl-> Execute() ) return; // пользователь нажал кнопку Отмена

/* При попытке открыть файл клипа, который уже открыт, возникает ошибка. */

if ( MediaPlayerl-> FileName == OpenDialogl-> FileName ) return;

/* Пользователь выбрал клип. Зададим размер и положение " экрана", на котором будет выведен клип. Для этого надо, знать размер кадров клипа. */

II получить размер кадра GetFrameSize(OpenDialogl-> FileName, & fw, & fh);

// вычислим максимально возможный размер кадра mw = Forml-> ClientWidth; mh = Forml-> Panell-> Top-10;

if ( fw < mw ) kw = 1; // кадр по ширине меньше размера экрана else kw = (float) mw / fw;

if ( fh < mh ) kh = 1; // кадр по высоте меньше размера экрана else kh = (float) mh / fh;

Мультимедиа 155

// масштабирование должно быть пропорциональным if ( kw < kh ) к = kw; else к = kh;

// здесь масштаб определен sw = fw * к, - // ширина экрана sh = fh * к; // высота экрана

left = (Forml-> ClientWidth - sw) / 2; top = (Panell-> Top - sh) / 2;

MediaPlayerl-> FileName = OpenDialogl-> FileName;

MediaPlayerl-> Open(); MediaPlayerl-> DisplayRect = Rect(left, top, sw, sh); /* еслиразмеркадравыбранногоклипаменьшеразмеракадрапредыдущегоклипа, тоэкран (областьформы) надоочистить */ Forml-> Canvas-> FillRect(Rect(0, 0, ClientWidth, Panell-> Top));

SpeedButton2-> Enabled = true; // теперькнопка Play // доступна

// вывести информацию о времени воспроизведения MediaPlayerl-> TimeFormat = tfMillisec

int ms = MediaPlayerl-> Length; AnsiString st = IntToStr(SECOND(ms)); if ( st.Length() == 1) st = " 0" + st; st = IntToStr(MINUTE(ms)) + ": " + st; Labell-> Caption = st; Label3-> Caption = " 0: 00";

// активизируемпроцессвоспроизведения SpeedButton2-> Glyph-> Assign(bmPause);

бЗак. 1241

156 Часть 1. Примерыизадачи

SpeedButton2-> Hint = " Pause"; SpeedButton2-> Tag = 1; SpeedButtonl-> Enabled = False; // кнопка Eject недоступна MediaPlayerl-> Play(); Timerl-> Eriabled = true;

// щелчокнакнопке Play/Stop (воспроизведение/стоп) void fastcall TForml:: SpeedButton2Click(TObject *Sender) { if (SpeedButton2-> Tag == 0) { // нажатакнопка Play SpeedButton2-> Glyph-> Assign(bmPause); SpeedButton2-> Hint = " Pause"; SpeedButton2-> Tag = 1; SpeedButtonl-> Enabled = False; // кнопка Eject // недоступна MediaPlayerl-> Play(); Timerl-> Enabled = true; } else // нажатакнопка Stop { MediaPlayerl-> Stop(); SpeedButton2-> Glyph-> Assign(bmPlay); SpeedButton2-> Hint = " Play"; SpeedButton2-> Tag = 0; SpeedButtonl-> Enabled = True; // кнопка Eject доступна Timerl-> Enabled = false;

// сигналотплеера void fastcall TForml:: MediaPlayerlNotify(TObject *Sender)

Мультимедиа 157

{

if ( ( MediaPlayerl-> Mode == mpStopped ) & & ( SpeedButton2-> Tag == 1)) { Timerl-> Enabled • false; SpeedButton2-> Glyph-> Assign(bmPlay); SpeedButton2-> Hint = " Play"; SpeedButton2-> Tag = 0; SpeedButtonl-> Enabled = True; // сделатьдоступной // кнопку Eject

/* Процедура обработки события Pain обеспечивает отображение (перерисовку) первого кадра, при появлении окна, например, после того, как пользователь отодвинет другое окно, перекрывающее окон Video Player. */ void _fastcall TForml:: FormPaint(TObject *Sender) { if ( MediaPlayerl-> Mode == mpStopped ) { MediaPlayerl-> Position = 1; MediaPlayerl-> Position = 0;

// завершениеработыпрограммы void fastcall TForml:: FormClose(TObject *Sender, TCloseAction & Action) { MediaPlayerl-> Close();

void fastcall TForml:: TimerlTimer(TObject *Sender)

158 Часть 1. Примерыизадачи

// вывестиинформациюовременивоспроизведения // MediaPlayerl-> TimeFormat = tfMilliseconds; int ms = MediaPlayerl-> Position; AnsiString st = IntToStr(SECOND(ms)); if ( st.Length() == 1) st = " 0" + st; st = IntToStr(MINUTE(ms)) + ": " + st; Label3-> Caption = st;


 

Задача 39. Анимация

Программа Анимация (Рис. 46) демонстрирует воспроизведение AVI-анимации при помощи компонента Animate. Анимация загружается из файла в начале работы работы
программы. Процесс воспроизведения активизируется автоматически, в момент появления окна программы на экране. Следует обратить внимание, что компонент Animate обеспечивает воспроизведение только простой, не сопровождаемой звуком анимации.

Рис 46


Вывод: При выполнении этого задания мы научились воспроизводить анимацию на форме, которая воспроизводится путем нажатия кнопки запуска.

Листинг

//---------------------------------------------------------------------------

 

#include < vcl.h>

#pragma hdrstop

 

#include " Unit1.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource " *.dfm"

TForm1 *Form1;

bool loaded = false; // анимация загружена

//---------------------------------------------------------------------------

__fastcall TForm1:: TForm1(TComponent* Owner)

: TForm(Owner)

{

/* если файл анимации недоступен илианимация

сопровождается звуком, возникает исключение*/

try

{

Animate1-> FileName = " delphi.avi";

}

catch (Exception & e)

{ }

Form1-> Caption = " Анимация - " + Animate1-> FileName;

loaded = true;

Label1-> Caption =

" Кадров: " + IntToStr(Animate1-> FrameCount) +

" Размеркадров: " + IntToStr(Animate1-> Width) +

" x" + IntToStr(Animate1-> Height);

// началоработыпрограммы

}

//---------------------------------------------------------------------------

 

void __fastcall TForm1:: FormActivate(TObject *Sender)

{

if ( loaded)

// воспроизвестианимацию один раз с первого по

// последнийкадр

Animate1-> Play(1, Animate1-> FrameCount, 1);

}

//---------------------------------------------------------------------------

void __fastcall TForm1:: Button1Click(TObject *Sender)

{

if ( loaded)

// воспроизвестианимацию один раз с первого по

// последнийкадр

Animate1-> Play(1, Animate1-> FrameCount, 1);

}

//---------------------------------------------------------------------------


 

Задача 40. Записная книжка

Программа Записная книжка (Рис. 47),
демонстрирует использование компонентов BDE для работы с
одноименной базой данных формата Paradox. База данных состоит из одной единственной таблицы adrbk.db.Программа работает с данными в режиме таблицы и позволяет
просматривать, редактировать, добавлять и удалять записи, а
также обеспечивает выборку (поиск) информации по содержимому поля Name. Для доступа к базе данных программа использует псевдоним adrbk.

Рис 47

Вывод: В этом задании мы научились демонстрировать использование компонентов BDE для работы с
одноименной базой данных формата Paradox

Листинг

#include " Find_.h" // эта директива вставлена вручную

// начало работы программы void fastcall TMainForm:: FormShow(TObject *Sender) { // если псевдоним adrbk не зарегистрирован, возникает ошибка try

{

Tablel-> Open();

} catch (EDBEngineError & e) { ShowMessage(" Ошибка доступа к базе данных: " " не определен псевдоним adrbk\n" + е.Message );

Button2-> Enabled = false; BitBtnl-> Enabled = false; CheckBoxl-> Enabled = false;

// щелчокнакнопкепоискаинформации void fastcall TMainForm:: BitBtnlClick(TObject *Sender)

Базыданных 165

{

FindForm-> Tag = 0; FindForm-> ShowModal(); // отобразитьокноЗапрос if ( FindForm-> Tag ) { // пользовательзакрылокнопоиска // щелчкомнакнопкеОК, тоестьонввел // фамилиюилиимя Queryl-> SQL-> Text = " SELECT * FROM adrbk WHERE Name LIKE \042%" + FindForm-> Editl-> Text +" %\042"; // \042 - этовосьмеричныйкоддвойнойкавычки if ( CheckBoxl-> Checked ) ShowMessage (Queryl-> SQL-> Text);

Queryl-> Open(); // открыть (выполнить) запрос if ( Queryl-> RecordCount! = 0) DataSourcel-> DataSet = Queryl; else { ShowMessage (" Вбазеданныхнетзапрашиваемой" " информации: " + FindForm-> Editl-> Text); DataSourcel-> DataSet = Tablel;

// щелчокнакнопкеВсезаписи void fastcall TMainForm:: Button2Click(TObject *Sender) { // источникданных - таблица DataSourcel-> DataSet = Tablel;

// завершение работы программы

166 Часть 1. Примеры и задачи

void fastcall TMainForm:: FormClose(TObject *Sender, TCloseAction SAction) { Tablel-> Close();

// *** ЭтомодульформыНайти *** // окноНайтисталодоступным void fastcall TFindForm:: FormShow(TObject *Sender) { Editl-> SetFocus(); // установитькурсорвполе // редактированияУ

// ЩелчокнакнопкеОК (пользовательввелкритерийзапроса) void.fastcall TFindForm:: ButtonlClick(TObject *Sender) { Tag = 1; // пользовательщелкнулнакнопкеОК Close();

// нажатаклавиша void fastcall TFindForm:: EditlKeyPress(TObject *Sender, char & Key) { if ( Key == 13) Buttonl-> SetFocus(); // переместитьфокус // накнопкуОК

Задача 41 Магазин

Программа Магазин (Рис. 48 и 49) работает с одноименной базой данных и демонстрирует использование компонентов BDE.

Рис 48

Рис 49

Вывод: В этой программе создали окно магазина для базы данных.

Листинг

#include < vcl.h>

#pragma hdrstop

 

#include " Unit1.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource " *.dfm"

TForm1 *Form1;

//---------------------------------------------------------------------------

__fastcall TForm1:: TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

 

void __fastcall TForm1:: FormShow(TObject *Sender)

{

try {

Table1-> Open();

}

catch ( EDBEngineError & e)

{

ShowMessage(" Для доступа к базе данных надо создать " " псевдоним stock" );

}

}

//---------------------------------------------------------------------------

 

void __fastcall TForm1:: DataSource1StateChange(TObject *Sender)

{

if ( DataSource1-> State == dsBrowse) StatusBar1-> Panels-> Items[1]-> Text = " Просмотр";

else

StatusBar1-> Panels-> Items[1]-> Text = " Редактирование";

 

}

//---------------------------------------------------------------------------

void __fastcall TForm1:: Table1AfterScroll(TDataSet *DataSet)

{

AnsiString Picture;

if ( Table1-> RecNo! = -1)

{

StatusBar1-> Panels-> Items[0]-> Text = " Запись: " + IntToStr( Table1-> RecNo );

try {

Picture = Table1-> Database-> Directory + DataSet-> FieldValues[" Image" ];

}

catch (EVariantTypeCastError & e)

{

Image1-> Visible = false;

return;

}

ShowPhoto(Picture);

}

else

{

StatusBar1-> Panels-> Items[0]-> Text = " ";

StatusBar1-> Panels-> Items[1]-> Text = " Новаязапись";

Image1-> Visible = false;

}

}

//---------------------------------------------------------------------------

void __fastcall TForm1:: ShowPhoto(AnsiString Picture)

{

try

{

Image1-> Picture-> LoadFromFile(Picture);

}

catch ( EFOpenError & e)

{

Image1-> Visible = false;

return;

}

Image1-> Visible = true;

}

//---------------------------------------------------------------------------

void __fastcall TForm1:: FormClose(TObject *Sender, TCloseAction & Action)

{

if (Table1-> State == dsEdit )

Table1-> Post();

}

//---------------------------------------------------------------------------


 

Задача 42. Ежедневник

Программа Ежедневник (рис. 50) демонстрирует использование компонентов ADO для доступа к базе данных формата Microsoft Access. База данных содержит информацию о запланированных мероприятиях (дата, задача). Программа позволяет вносить в базу данных изменения (добавлять, удалять и редактировать записи), а также обеспечивает выбор информации по запросу — выводит список мероприятий, запланированных " на сегодня", " на завтра" и " на эту неделю". При запуске программа автоматически выводит список мероприятий, запланированных " на сегодня" или, если программа запущена в пятницу, субботу или воскресенье, " на сегодня и ближайшие дни”.

Рис 50

Вывод: В этом задании мы научились использовать компонентов ADO для доступа к базе данных формата Microsoft Access.

Листинг

AnsiString stDay[7] = (" воскресенье", " понедельник", " вторник", " среда", " четверг", " пятница", " суббота" };

AnsiString stMonth[12] = {" января", " февраля", " марта", " апреля", " мая", " июня", " июля", " августа", " сентября", " октября", " ноября", " декабря" };

void fastcall TForml:: FormShow(TObject *Sender)

{

TDateTime Today, // сегодня

NextDay; // следующий день (не обязательно завтра)

Word Year, Month, Day; // год, месяц, день

Today п Now ();

DecodeDate(Today, Year, Month, Day);

Labell-> Caption = " Сегодня " + IntToStr(Day) + " " + stMonth[Month-1] + " " + IntToStr(Year) + " года, " + stDay[DayOfWeek(Today) -1];

Label2-> Caption » " Сегодня и ближайшие дни";

/* вычислим следующий день, если сегодня пятница, то, чтобы не забыть, что запланировано на понедельник, считаем, что следующий день - понедельник */ switch ( DayOfWeek(Today) ) { case 6: NextDay = Today + 3; break; // сегодня пятница case 7: NextDay r» Today + 2; break; // сегодня суббота default: NextDay = Today + 1; break;

176 Часть 1. Примерыизадачи

ADODataSetl-> CommandText = " SELECT * FROM schedule WHERE aDate BETWEEN DateValueC" FormatDateTimeC'dd/iran/yyyy", Today) + " ') AND DateValue('" + FormatDateTime(" dd/mm/yyyy", NextDay) + " ') ORDER BY aDate";

// еслинадо, отобразить SQL-команду if ( CheckBoxl-> Checked) ShowSQLO;

// если БД не зарегистрирована как источник данных ODBC, // возникает исключение EOleException

try { // открыть набор данных (выполнить // SQL-команду ADODataSetl-> CommandText ADODataSetl-> Open();

catch ( EOleException & e) // чтобы тип EOleException был доступен, в программу // надо поместить директиву ^include < ComObj.hpp> I

ShowMessage( " Ошибка обращения к БД. База данных Planner.mdb должна" " быть зарегистрирована\пв системе как источник данных ODBC " " под именем dplaner"

Buttonl-> Enabled = false; Button2-> Enabled = false; Button3-> Enabled = false;

Базыданных 177

Button4-> Enabled = false; return;

if (! ADODataSetl-> RecordCount ) ShowMessage(" На сегодня и ближайшие дни ни каких дел " не запланировано." );

// ЩелчокнакнопкеСегодня void fastcall TForml:: ButtonlClick(TObject *Sender) { AnsiString today = FormatDateTime(" dd/inm/yyyy", Now());

Forml-> Label2-> Caption = " Сегодня";

ADODataSetl-> Close(); // закрытьнаборданных

// изменитькритерийзапроса ADODataSetl-> CommandText = " SELECT * FROM schedule WHERE aDate = DateValue('" + today +" ')";

if ( CheckBoxl-> Checked) ShowSQLf); // отобразитьзапрос

ADODataSetl-> Open(); // открыть набор данных с новым // запросом

// щелчокнакнопкеЗавтра void fastcall TForml:: Button2Click(TObject *Sender) { AnsiString tomorrow = FormatDateTime(" dd/mm/yyyy" Now () +1 );

Label2-> Caption = " Завтра";

178 Часть 1. Примеры и задачи

ADODataSetl-> Close();

// изменитькритерийзапроса ADODataSetl-> CornmandText = " SELECT * FROM schedule WHERE aDate = DateValue('" +

tomorrow + " ')";

if ( CheckBoxl-> Checked) ShowSQLO;

ADODataSetl-> Open(); // выполнить запрос

if (! ADODataSetl-> RecordCount )

{

ShowMessage(" На завтра никаких дел не" " запланировано! " );

// щелчокнакнопкеНаэтойнеделе void fastcall TForml:: Button3Click(TObject *Sender)

{

// " эта неделя" - от текущего дня до конца недели // (до воскресенья) TDateTime Present, eWeek;

Label2-> Caption = " На этой неделе";

Present^ Now О; // Now - возвращает текущую дату

eWeek = EndOfAWeek(YearOf(Present), WeekOf(Present));

/* длядоступак StartOfWeek, EndOfAWeek, YearOf и WeekOf надоподключить DateUtils.hpp (см. директивы iinclude ) */

Базыданных 179

ADODataSetl-> Close();

ADODataSetl-> CommandText = " SELECT * FROM schedule WHERE aDate BETWEEN DateValue('" + FormatDateTime(" dd/mm/yyyy", Present) +." •') AND DateValuef1" + FormatDateTime(" dd/mm/yyyy", eWeek)+" ') ORDER BY aDate";

if ( CheckBoxl-> Checked) ShowSQLO;

ADODataSetl-> Open();

if (! ADODataSetl-> RecordCount ) ShowMessage(" На эту неделю никаких дел " " не запланировано." );

} // ЩелчокнакнопкеВсе void fastcall TForml:: Button4Click(TObject *Sender) { ADODataSetl-> Close();

ADODataSetl-> CommandText = " SELECT * FROM schedule ORDER BY aDate"; if ( CheckBoxl-> Checked) ShowSQLO; ADODataSetl-> Open(); Label2-> Caption - " Все, чтонамеченосделать";

} // отображает SQL-команду void fastcall TForml:: ShowSQL(void) { ShowMessage ( ADODataSetl-> CommandText );


 

Задача 43. Сапер

Игра Сапер (Рис. 51) — аналог одноименной игры, хорошо знакомой всем пользователем Windows. Программа демонстрирует работу с графикой, массивами, вывод
справочной информации и показывает, как можно запустить программу доступа в Internet.

Рис 51

Вывод: В этом задании с помощью функций и компонентов С++ мы создали игру “Сапёр”

Листинг

II *** модуль главной формы *** #include < stdlib.h> // для доступа к // генератору случайных чисел #include < time.h> # include " SaperAbout.h"

TMain *Main; // главное окно

#define MR 10 // кол-во клеток по вертикали #define MC 10 // кол-во клеток по горизонтали #define NM 10 // кол-во мин

int Pole[MR+2][МС+2]; // минное поле // 0..8 - количество мин в соседних клетках // 9 - в клетке мина // 100..109 - клетка открыта // 200..209 - в клетку поставлен флаг

int nMin; // кол-во найденных мин int nFlag; // кол-во поставленных флагов

int status =0; // 0 - начало игры; 1 - игра; 2 - результат

// смещение игрового поля относительно левого верхнего угла // поверхности формы #define LEFT 0 // по X #define TOP 1 // по Y

#define W 40 // ширина клетки поля #define H 40 // высота клетки поля

// новая игра - " разбрасывает" мины void fastcall NewGame(); // открывает текущую и соседние пустые клетки

Игры и другие полезные программы 183

void fastcall Open(int row, int col);

// нажатиекнопкимышинаигровомполе void fastcall TMain:: FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int x, int y) { if ( status == 2 ) return, if ( status == 0) status = 1;

x -= LEFT; у -= TOP; if (x > 0 & & у> 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] == nMin++; Pole[row][col] += 200; if (nMin == NM ScSc nFla

status =2; // игра ShowPole(status);

else Kletka(row, col,

}

Часть 1. Примеры и задачи

9 )

// поставили флаг g == NM)

закончена

status);

// Функция обработки- события OnCreate обычно используется // для инициализации глобальных переменных void fastcall TMain:: FormCreate(TObject *Sender) { // В неотображаемые эл-ты массива, которые соответствуют // клеткам по границе игрового поля, запишем число -3. // Это значение используется функцией Open для завершения // рекурсивного процесса открытия соседних пустых клеток. for ( int row=0; row < = MR+l; row++) for ( int col=0; col < = MC+l; col++) Pole[row][col] = -3;

NewGameO; // " разбросать" мины ClientWidth = W*MC; ClientHeight = H*MR+TOP+1;

// Вывод поля как результат обработки события Paint // позволяет проводить любые манипуляции с формой во время // работы программы void fastcall TMain:: FormPaint(TObject *Sender)

Игры и другие полезные программы 7S5

ShowPole(status);

// Показываетполе void fastcall TMain:: ShowPole( int status) { for ( int row = 1; row < = MR; row++ ) for ( int col = 1; col < = MC; col++ ) Kletka(row, col, status);

// рисуетнаэкранеклетку void fastcall TMain:: Kletka(int row, int col, int status) { int X = LEFT + (col-1)* W; . int у = TOP + (row-1)* H;

if (status ==0) // началоигры { // клетка - серыйквадрат Canvas-> Brush-> Color = clBtnFace; Canvas-> Rectangle(x-l, y-l, x+W, y+H); return;

}

// вовремя (status = 1) ивконце (status = 2) игры if ( Pole[row][col] < 100 ) { // клетканеоткрыта Canvas-> Brush-> Color = clBtnFace; // неоткрытые // серые Canvas-> Rectangle(x-1, у-1, x+W, у+Н); if (status == 2 & & Pole[row][col] == 9) Mina( x, y); // игразакончена, показатьмину

186 Часть 1. Примеры и задачи

return;

// клетка открыта Canvas-> Brush-> Color = clWhite; // открытые — белые Canvas-> Rectangle(х-1, у-1, x+W, у+Н); if ( Pole[row][col] == 100 ) // клетка открыта, но она // пустая return;

if ( Pole[row][col] > = 101 & & Pole[row][col] < = 108 ) { Canvas-> Font-> Size = 11; Canvas-> Font-> 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-1, y-1, x+W, y+H);

if (( Pole[row][col] % 10 == 9) & & (status Mina( x, y);

== 2)

// рекурсивная функция открывает текущую и все соседние // клетки, в которых нет мин void fastcall Open(int row, int col)

Игры и другие полезные программы 187

{

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+l; row++) for (col=0; col < = MC+l; col++) Pole[row][col] = -3; for (row=l; row < = MR; row++)

3ак. 1241

188 Часть 1, Примеры и задачи

for (col=l; col < = МС; 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;

while ( n < 10);

// вычислениекол-ваминвсоседнихклетках int к; for ( row = 1; row < = MR; row++) for ( col = 1; col < = MC; col++) if ( Pole[row][col]! = 9 ) { к =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;

Игры и другие полезные программы 189

status =0; // начало игры

riMin =0; //нет обнаруженных мин nFlag =0; // нет флагов

// рисуетмину void fastcall TMain:: Mina(int x, int y) { Canvas-> Brush-> Color = clGreen; Canvas-> Pen-> Color = clBlack; Canvas-> Rectangle(x+16, y+26, x+24, y+30);

// корпус Canvas-> Rectangle(x+8, y+3 0, 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+36); 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)

// Рисуетфлаг void fastcall TMain:: Flag( int x, int y) { TPoint p[4]; // координатыфлажкаинижнейточкидревка

// точки флажка

р[0].х=х+4; р[0] р[1].х=х+30; р[1] р[2].х=х+4; р[2]

// установим цвет

•y=y+4;

•У=У+12;

•У=У+2 О;

кистиикарандаша Canvas-> Brush-> Color = clRed; Canvas-> Pen-> Color

Canva s-> Polygon(p,

// древко Canvas-> Pen-> Color

= clRed; // чтоС // крас 2); // флажок

= clBlack;

Часть 1. Примеры и задачи

> ы контур флажка был

•НЫЙ

Canvas-> MoveTo(p[0].х, p[O].y) Canvas-> LineTo(x+4, y+36);

TPoint m[5]; // букваМ

m[0].x=x+8; m[0].y=y+14; m[l].x=x+8; m[l].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 TMain:: NlClick(TObject *Sender)

NewGame(); ShowPole(status);

Игры и другие полезные программы 191

// выбор в меню "? " команды О программе void fastcall TMain:: N4qlick(TObject *Sender)

About~> ShowModal();

// выбор в меню "? " команды Справка void fastoall TMain:: N3Click(TObject *Sender)

{

/* Отображение справочной информации обеспечивает утилита hh.exe, входящая в состав Windows. Ключ mappid задает отображаемый раздел справочной информации. */ WinExecChh.exe -mapid I saper.chm", SW_RESTORE);

// *** модуль формы О программе*** // Выбор URL-адреса (щелчок в поле компонента Label5) void fastcall TAbout:: Label5Click(TObject *Sender)

{

/* наиболее просто передать в функцию ShellExecute строку-константу (URL-адрес) так, как показано ниже ShellExecute (AboutForm-> Handle, " open", " http: \\\\www.bhv.ru", NULL, NULL) Лучше URL-адрес брать из поля метки. В функцию ShellExute надо передать указатель (char*) на null terminated строку, но свойство Caption это AnsiString. Преобразование Ansi строки в (char*) строку выполняет метод c_str () */

192 Часть 1. Примеры и задачи

// открыть файл, имя которого находится в поле Labels ShellExecute(About-> Handle, " open", Label5-> Caption.c_str(), NULL, NULL, SW_RESTORE);

}

// щелчокнакнопке OK void fastcall TAbout:: ButtonlClick(TObject *Sender)

{

ModalResult = mrOk;


 

Задача 44 Игра 15

Всем известна игра " 15" (Рис. 52). Вот ее правила. В прямоугольной
коробочке находятся 15 фишек, на которых написаны числа
от 1 до 15. Размер коробочки — 4x4, таким образом в коробочке есть одна пустая ячейка. В начале игры фишки перемешаны.

Рис 52

Вывод: В этом задании мы создали игру 15.

Листинг

#include " math.hpp" // для доступа к Randomize и RandomRange

//' размер клеток 48x48 #defineWC 48 tdefine НС 48

bytepole[4][4]; // игровое поле byteex, ey; // координаты пустой клетки

fastcall TForml:: TForml(TComponent* Owner): TForm(Owner)

{

Forml-> Font-> Size = 12;

// началоработыпрограммы void fastcall TForml:: FormShow(TObject *Sender) { NewGame();

// новаяигра void fastcall TForml:: NewGame()

// установить ClientWidth = ClientHeight

размерформы

WC * \4;

= HC * 4;

//' исходное (правильное) положение int к = 1; for (int i =

for (int

pole[

Mixer()i

ShowPole();

0; i < 4; i++)

j = 0; j < 4; j++)

i][j] = k++;

// перемешать фишки

// отобразить игровое

Часть 1. Примеры и задачи

фишек

поле

// перемешивает фишки void fastealI TForml:: Mixer()

int xl, yl; // пустая клетка int x2, y2; // эту переместить в пустую int d; // направление относительно пустой

Randomize();

xl = 3; yl = 3; // см. описание массива stp for ( int i = 0; i < 150; i++) // кол-во перестановок

do { x2 = xl; y2 = yl; /* выберем фишку, примыкающую к пустой клетке, которую переместим в пустую клетку */ d = RandomRange(1, 5); switch ( d ) {

Игры и другие полезные программы 795

case I: x2--; break; case 2: х2++; break; case 3: у2—; break; case 4: y2++; break;

} while ( (x2 < 0) | | (x2 > = 4) | | (y2 < 0) | (y2 > =

4));

/* здесь определили фишку, которую надо переместить в пустую клетку */ pole[yl][xl] = Ро1е[у2][х2]; pole[y2][x2] = 16; xl = х2; У1 = У2;

// запомним координаты пустой клетки ex = xl; еу = yl;

}

// отображает на поверхности формы игровое поле void fastcall TForml:: ShowPole()

int x, y; // координаты левого верхнего угла клетки

for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++)

x = j * HC; у = i * WC; if < pole[i][j]! = 16 ) { Canvas-> Brush-> Color = clBtnFace; Canvas-> Rectangle(x, y, x+WC-1, y+HC-1);

/96 Часть 1. Примеры и задачи

Canvas-> TextOutA(x+15, у+10, IntToStr(pole[i][j]));

} else { Canvas-> Brush-> Color = clBtnHighlight; Canvas-> Rectangle(x, y, x+WC-1, y+HC-1);

bool Finish(); // проверяет, правильно ли размещены фишки

// щелчоквклетке void fastcall TForml:: FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { int cx, cy; // координатыклетки

ex = X / WC; cy = Y / HC;

// переместитьвыбраннуюклеткувсоседнююсвободную if ( ( abs(cx - ex) == 1 & & су-еу ==0 ) || ( abs(cy - еу) == 1 & & сх-ех ==0 ) ) { // переместитьфишкуиз (сх, су) в (ех, еу) pole[ey][ex] = pole[су][сх]; pole [су] [сх] = 16, ех = сх; еу = су; ShowPole(); // отрисоватьполе if ( Finish () ) { ShowPole();

Игры и другие полезные программы 197

int r = MessageDlg (" Цель достигнута! \Еще раз? ", mtInformation, TMsgDlgButtonsО « mbYes « mbNo, 0); if ( r == mrNo ) Forml-> Close(); // завершить работу программы else { NewGame(); ShowPole();

/* проверяет, расположены ли клетки (фрагменты картинки) в нужном порядке */ bool Finish() { bool result; int row, col; int к = 1;

result = true; // пустьфишкивнужномпорядке for (row = 0; row < 4; row++)

{

for (col = 0; col < 4; col++) if ( pole[row][col] == к )

else { result = false; break; } if (! result ) break;

198 Часть 1. Примеры и задачи

return (result);

// обработкасобытия Paint void fastcall TForml:: FormPaint(TObjesct *Sender)

ShowPole();

 

 


 

Задача 45. Игра " Собери картинку" (Puzzle)

Игра Собери картинку (Рис. 53) — аналог игры " 15", но в отличие от последней, на фишках нарисованы не цифры, а фрагменты картинки. Задача игрока — расположить фишки в правильном порядке. Игра заканчивается, когда картинка будет собрана.

Рис 53

Вывод:

Листинг

#include < vcl.h>

#pragma hdrstop

#include " PuzMain.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource " *.dfm"

TForm1 *Form1;

 

 

#include " math.hpp" // длядоступак Randomize и RandomRange

 

// размер поля WxH

#define W 4

#define H 4

 

int wc, hc; // размерклетки

 

byte pole[H][W]; // игровое поле

byte ex, ey; // координаты пустой клетки

 

bool GameOver;

 

AnsiString fn; // имя bmp-файла (картинка)

TSearchRec SearchRec; // результатпоискафайла

 

__fastcall TForm1:: TForm1(TComponent* Owner)

: TForm(Owner)

{

pic = new Graphics:: TBitmap();

}

 

// началоработыпрограммы

void __fastcall TForm1:: FormShow(TObject *Sender)

{

NewGame();

}

 

// новаяигра

void __fastcall TForm1:: NewGame()

{

static int Tag = 0;

// загрузитьфайлиллюстрации

if (( ParamCount() == 0 ) & & (Tag == 0 )) Tag = 1;

 

switch ( Tag )

{

case 0: // имя файла - из командной строки

fn = ParamStr(1);

Tag = 1;

break;

 

case 1: // выбрать первый по порядку bmp-файл

{ FindFirst(" *.bmp", faAnyFile, SearchRec);

fn = SearchRec.Name;

Tag = 2;

}

break;

 

case 2: // выбрать следующий bmp-файл

{

if ( FindNext(SearchRec)! = 0)

FindFirst(" *.bmp", faAnyFile, SearchRec);

fn = SearchRec.Name;

}

break;

}

 

// загрузитьиллюстрацию

try {

pic-> LoadFromFile(fn);

}

catch (EFOpenError & e)

{

MessageDlg(" Ошибка доступа к файлу иллюстрации",

mtWarning, TMsgDlgButtons()< < mbOK< < mbHelp, 0);

return;

}

 

// определить размер клетки

wc = pic-> Width / W;

hc = pic-> Height / H;

 

// установить размер формы

ClientWidth = wc * W;

ClientHeight = hc * H;

 

// исходное (правильное) положение фишек

int k = 1;

for (int i = 0; i < H; i++)

for (int j = 0; j < W; j++)

pole[i][j] = k++;

 

GameOver = false;

Mixer(); // перемешать фишки

ShowPole(); // отобразить игровое поле

}

 

// перемешивает фишки

void __fastcall TForm1:: Mixer()

{

int x1, y1; // пустая клетка

int x2, y2; // эту переместить в пустую

int d; // направление относительно пустой

 

Randomize();

 

x1 = 3; y1 = 3; // см. описание массива stp

for ( int i = 0; i < 150; i++) // кол-воперестановок

{

do {

x2 = x1;

y2 = y1;

// выберем фишку, примыкающую к пустой клетке,

// которую переместим в пустую клетку

d = RandomRange(1, 5);

switch ( d ) {

case 1: x2--; break;

case 2: x2++; break;

case 3: y2--; break;

case 4: y2++; break;

}

} while ((x2 < 0) || (x2 > = W) || (y2 < 0) || (y2 > = H));

 

/* здесь определили фишку, которую

надо переместить в пустую клетку */

 

pole[y1][x1] = pole[y2][x2];

pole[y2][x2] = 16;

x1 = x2;

y1 = y2;

};

// запомним координаты пустой клетки

ex = x1;

ey = y1;

}

 

// отображает на поверхности формы игровое поле

void __fastcall TForm1:: ShowPole()

{

TRect src, dst; /* фрагмен картинки и область ее

ее отображения на поверхности формы */

int sx, sy;

 

for (int i = 0; i < H; i++)

for (int j = 0; j < W; j++)

{

/* Преобразуем номер фрагмента картинки в координаты

левого верхнего угла области-источника */

sx = ((pole[i][j]-1) % W) * wc;

sy = ((pole[i][j]-1) / H) * hc;

 

src = Bounds(sx, sy, wc, hc);

dst = Bounds(j*wc, i*hc, wc, hc);

 

if (( pole[i][j]! = 16 ) || GameOver )

// фрагменткартинки

Canvas-> CopyRect(dst, pic-> Canvas, src);

else

{

// пустаяклетка

Canvas-> Brush-> Style = bsSolid;

Canvas-> Brush-> Color = clBtnFace;

Canvas-> Rectangle(dst);

}

}

if ( N6-> Checked )

{

// вывестиномерфишки

Canvas-> Brush-> Style = bsClear;

for (int i = 0; i < H; i++)

for (int j = 0; j < W; j++)

Canvas-> TextOutA(wc*j, hc*i, IntToStr(pole[i][j]));

}

}

 

// щелчоквклетке

void __fastcall TForm1:: FormMouseDown(TObject *Sender, TMouseButton Button,

TShiftState Shift, int X, int Y)

{

int cx, cy; // координатыклетки

 

cx = X / wc;

cy = Y / hc;

 

Move(cx, cy); // переместить выбранную клетку в соседнюю свободную

}

 

bool Finish(); // проверяет, правильно ли размещены фишки

 

// перемещает фишку из клетки, в которой сделан щелчок

// всвободнуюклетку

void __fastcall TForm1:: Move(int cx, int cy)

{

if ( ( abs(cx - ex) == 1 & & cy-ey == 0 ) ||

( abs(cy - ey) == 1 & & cx-ex == 0 ) )

{

// переместить фишку из (cx, cy) в (ex, ey)

pole[ey][ex] = pole[cy][cx];

pole[cy][cx] = 16;

ex = cx;

ey = cy;

// отрисовать поле

ShowPole();

if ( Finish () )

{

GameOver = true;

ShowPole();

int r = MessageDlg (" Цельдостигнута! Ещераз (другаякартинка)? ",

mtInformation, TMsgDlgButtons() < < mbYes < < mbNo, 0);

if ( r == mrNo )

Form1-> Close(); // завершить работу программы

else

{

NewGame();

ShowPole();

}

}

}

}

 

/* проверяет, расположены ли

клетки (фрагменты картинки) в нужном порядке */

bool Finish()

{

bool result;

int row, col;

int k = 1;

 

result = true; // пусть фишки в нужном порядке

for (row = 0; row < H; row++)

{

for (col = 0; col < W; col++)

if ( pole[row][col] == k )

k++;

else {

result = false;

break;

}

if (! result ) break;

}

return (result);

};

 

// обработкасобытия Paint

void __fastcall TForm1:: FormPaint(TObject *Sender)

{

ShowPole();

}

 

// выбор в строке меню команды Новая игра

void __fastcall TForm1:: N1Click(TObject *Sender)

{

NewGame();

}

 

// выбор в меню Справка команды Справка

void __fastcall TForm1:: N3Click(TObject *Sender)

{

WinExec(" hh.exe puzzle.chm", SW_RESTORE);

}

 

// выбор в меню Справка команды О программе

void __fastcall TForm1:: N4Click(TObject *Sender)

{

WinExec(" hh.exe -mapid 3 puzzle.chm", SW_RESTORE);

 

}

 

// командаПараметры/Номерфишки

void __fastcall TForm1:: N6Click(TObject *Sender)

{

N6-> Checked =! N6-> Checked;

ShowPole();

}


 

Задача 46 Игра " Парные картинки"

Игра Парные картинки (Рис. 54) развивает внимание. Вот ее правила. Игровое поле разделено на клетки, за каждой из которых скрыта картинка. Картинки парные, т. е. на игровом поле есть две клетки, в которых находятся одинаковые картинки. В начале игры все клетки " закрыты". Щелчок левой кнопкой мыши " открывает" клетку, в клетке появляется картинка. Теперь надо найти клетку, в которой находится такая же картинка, как и в открытой клетке. Щелчок по другой клетке открывает вторую картинку (рис. 1.65). Если картинки в открытых клетках одинаковые, то эти клетки " исчезают". Если разные — то клетки остаются открытыми. Следующий щелчок закрывает открытые клетки и открывает следующую. Следует обратить внимание, что две открытые клетки закрываются даже в том случае, если открытая картинка такая же, как и одна из двух открытых. Игра заканчивается, когда игрок откроет — " найдет" все пары картинок.

Рис 54

Вывод: В этой задаче мы создали игру “Парные картинки” используя функции и компоненты программы.

Листинг

#include < vcl.h>

#pragma hdrstop

 

#include " Unit1.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource " *.dfm"

TForm1 *Form1;

intpole[5][4]={{101, 102, 103, 104}, //игровое поле

{101, 102, 103, 103}, //значения больше ста-закрытые клетки

{104, 105, 103, 104},

{102, 105, 101, 105},

{101, 102, 105, 104}};

int col=0, q1=0, q2=0; //количество кликов и значения

Graphics:: TBitmap*zakr;

Graphics:: TBitmap*pusto;

Graphics:: TBitmap*pole1;

Graphics:: TBitmap*pole2;

Graphics:: TBitmap*pole3;

Graphics:: TBitmap*pole4;

Graphics:: TBitmap*pole5;

//---------------------------------------------------------------------------

__fastcall TForm1:: TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

void __fastcall TForm1:: FormCreate(TObject *Sender)

{

Form1-> DoubleBuffered=true; //чтобнемигало

zakr=new Graphics:: TBitmap();

zakr-> LoadFromFile(" zakr.bmp" ); //загружаемзакрытоеполе

pusto=new Graphics:: TBitmap();

pusto-> LoadFromFile(" pusto.bmp" ); //пустоеполе

pole1=new Graphics:: TBitmap();

pole1-> LoadFromFile(" 1.bmp" ); //перваякартинка

pole2=new Graphics:: TBitmap();

pole2-> LoadFromFile(" 2.bmp" );

pole3=new Graphics:: TBitmap();

pole3-> LoadFromFile(" 3.bmp" );

pole4=new Graphics:: TBitmap();

pole4-> LoadFromFile(" 4.bmp" );

pole5=new Graphics:: TBitmap();

pole5-> LoadFromFile(" 5.bmp" );

FormPaint(Sender);

}

//здесь перерисовываем поле-------------------------------------------------


Поделиться:



Популярное:

Последнее изменение этой страницы: 2017-03-08; Просмотров: 780; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.682 с.)
Главная | Случайная страница | Обратная связь