Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Создаем диалоговое окно. Создание новой формы






У вас может возникнуть желание играть с компьютером не до 100 очков, а до произвольного числа. Для этого целесообразно сделать данный параметр настраиваемым, а настройку выполнять в отдельном диалоговом окне.Добавить в программу новое окно можно командой File -> NewForm (Файл - > Новая форма). Сразу же в визуальном проектировщике появится новая форма под названием Form2.Эту форму можно проектировать, размещать на ней различные элементы управления и работать с ней точно так же, как и с главной формой. Однако при запуске программы она не будет отображаться на экране — ее надо вызывать специальным методом.Однако показывать вторую форму надо, только если игра закончена, в противном случае (партия продолжается) следует сообщить об этом игроку и завершить работу метода.Проверку завершения игры мы выполняли методом Referee.GameFinish(). Но теперь блок условного оператора должен быть выполнен, только если игра не завершена.

2.1 Новую форму назовите InputFor m (свойство Name), а ее заголовкомсделать строку Ввод игрового порога (свойство Caption). Щелчком на командной кнопке SaveAll файл с текстомреализации работы этой формы надо сохранить с названием v_Unit.cpp., в начале файла DiceUnit.cpp, надо включить заголовочный файл v_Unit.h: #include " v_Unit.h"

Рисунок 1. Окно формы 2

На форме потребуется разместить одно поле ввода с названием Input и начальным показываемым значением 100 (свойство Text), поле надписи-подсказки и две кнопки ОК и Cancel (Отмена). Подобные кнопки стандартны для многих приложений, и в C++Builder на панели Additional можно найти удобный компонент BitBtn (кнопка с картинкой), которому соответствует класс TBitBtn.Разместите две такие кнопки на форме. Для первой из них в свойстве Kind (Тип кнопки) выберите значение bkOk (стандартная кнопка ОК), а для второй — bkCancel. При этом картинки на кнопках появятся автоматически.

Рисунок 2 Окно ввода игрового порога

2.2 Добавьте в главное меню новый пункт: Пункт & Порог с названием PUnit (свойство Name в Инспекторе объектов). Для него не надо создавать вложенного подменю.Дважды щелкните на этом пункте — C++Builder автоматически создаст метод реакции на его выбор, а уже из этого метода будет вызываться форма InputForm.

Рисунок 3. Вид главного меню

 

 

 

Теперь программу можно запустить, и при выборе пункта меню Порог на экране появится новое окно.

2.3 Теперь новое окно не позволяет вернуться к главному окну (такие окна, не допускающие перехода на другие окна своего приложения, называются модальными. Они больше известны как диалоговые), эту функцию реализует метод ShowModal() (показать как модальное окно):

Только при работе с подобными диалоговыми окнами обычно не разрешается менять их размеры. Чтобы сделать границы вспомогательного окна неизменяемыми, задайте свойству BorderStyle (Стиль границ) формы InputForm значение bsDialog (Стиль диалогового окна).

 

Текст метода допишите самостоятельно последующимшагам.

void __fastcall TForm1:: PUnitClick(TObject *Sender)

{

}

1. Метод ShowModal() возвращает одно из предопределенных значений mrOk или mrCancel. С помощью условного оператора можно проверить, какое значение возвращено:

// если была нажата кнопка ОК

if(InputForm-> ShowModal() == mrOk)

 

2. В логическом блоке условного оператора надо перевести введенное в поле ввода Input текстовое значение в число и проверить его на «разумность величины» (допустим, от 50 до 1000). Это можно сделать с помощью другого условного оператора, как бы вложенного в предыдущий, а нужное число удобно сохранить во временной переменной input:

// если после показа InputForm нажата кнопка- ОК:

if(InputForm-> ShowModal() == mrOk)

{ int input;

input = StrToInt(InputForm-> Input-> Text); // преобразовать введенный пользователем текст в

//число проверить его на допустимый диапазон:

if(input> = 50 & & input< = 1000) return;

}

 

Но где сохранить новое значение? Ведь в качестве игрового порога используется константа GAME_FINISH_SCORE, а значения констант менять нельзя.Это действительно проблема, и она наглядно показывает, как плохо, когда какие-то требования к будущей программе не были сразу сформулированы, и потому не были учтены при проектировании приложения. Если бы сразу удалось додуматься до потребности в-изменении игрового порога, то можно было бы исходно вместо константы использовать переменную.Трудоемкость проекта можно оценить формально. Для этого есть специальные технологии (например, метод функциональных точек), однако они сложны в использовании и применяются в основном при создании больших программных комплексов. Но далеко не всегда исходные требования удается сформулировать с самого начала. Часто бывает так, что при создании заказной программы у заказчика по ходу работы возникают новые пожелания, подчас требующие почти полной переделки всей внутренней структуры приложения. Люди, незнакомые с программированием, как правило, не способны оценить трудоемкость тех или иных модификаций готового продукта. Некоторые, на их взгляд, несущественные дополнения на самом деле требуют огромного труда и наоборот, самые сложные изменения пользовательского интерфейса могут потребовать всего лишь изменения нескольких свойств в Инспекторе объектов.Поэтому все требования к будущей программе желательно формулировать заранее, а в дальнейшем любые дополнения рассматривать как другой проект, например, по выпуску новой версии.

2.4 Наилучший в этой ситуации способ — сделать переменную из константыGAME_FINISH_SCORE.

Для этого ее описание в файле Game.h надо убрать, а в класс TReferee добавить новую переменную:

int GAME_FINISH_SCORE;

Ее название, выглядящее как название константы, менять не надо, потому что оно встречается в разных местах программы. Надо только проинициализировать ее начальное значение — создать конструктор TReferee и в его реализации записать один оператор:

GAME_FINISH_SCORE = 100; // Сделать это надо аналогично конструктору TPlayer

 

После внесенных изменений, сохраните весь проект. Но если теперь откомпилировать программу, то для оператора

if(Referee.Human.Scores > = GAME_FINISH_SCORE)

появится сообщениеоб ошибке Undefinedsymbol " GAME_FINISH_SCORE" (символ GAME_FINISH_SCORE не определен).

Действительно, ведь мы превратили константу GAME_FINISH_SCORE, доступную во всех частях программы (как и должно быть) во внутреннюю переменную, и для обращения к ней надо указать содержащую ее переменную Referee: Referee.GAME_FINISH_SCORE,

а ошибочный оператор надо изменить на

if(Referee.Human.Scores> = Referee.GAME_FINISH_SCORE)

2.5 Если игровой порог менялся, но при последующих вызовах формы InputForm в поле ввода будет по-прежнему показываться число 100, это значит, что интерфейс сделан неправильно. Так даже нельзя понять, до какого количества очков ведется игра. Прежде всего в главную форму надо добавить новое поле надписи (назвать его можно GameFinish), а в реализацию метода Showlnfo() надо добавить вывод в это поле текущего порога:

GameFinish-> Caption = POROG_STR + IntToStr(Referee.GAME_FINISH_SCORE);

Константа POROG_STR описывается, как обычно, в файле Text.h:

const AnsiString POROG_STR = " Играведетсядо ";

Для того чтобы значение Referee.GAME_FINISH_SCORE исходно показывалось в поле ввода Input формы InputForm, надо в методе PUnitClick() перед вызовом формы присвоить свойству Text поля Input соответствующее число, преобразованное в текстовый вид:

InputForm-> Input-> Text =IntToStr(Referee.GAME_FINISH_SCORE);

Теперь понятно, где надо сохранить введенное значение — впеременной Referee.GAME_FINISH_SCORE. И здесь же надо начать новую игру — ведь при проверке методом Referee. GameFinish() используется переменная Referee.GAME_FINISH_SCORE, и если ее увеличить по сравнению с текущимпорогом, то в дальнейшем уже законченная партия может неожиданно продолжиться до нового числа очков, что не соответствует правилам.

if(input > = 50 & & input < = 1000) {

Referee.GAME_FINISH_SCORE = input;

Referee.NewGame();

Showlnfo();

}

В противном случае, когда значение input не укладывается в допустимые рамки, пользователь должен увидеть предупреждение о том, что введенное число не соответствует диапазону:

else ShowMessage(BAD_NUMBER_STR);

Избегайте глубокой вложенности условных операторов. Это значительно усложняет логику работы программы и процесс отладки. Оптимально использовать не более одного уровня такой вложенности. В принципе любой код всегда можно переделать так, чтобы он вообще не допускал вложенных операторов if. Например, кусочек данного метода, где обрабатывается нажатие ОК, можно переписать следующим образом:

// если НЕ нажата кнопка ОК, то завершить работу метода

if(InputForm-> ShowModal()! = mrOk) return;

intinput;

input = StrToInt(InputForm-> Input-> Text);

if(input > = 50 & & input < = 1000)

Referee.GAME_FINISH_SCORE = input;

else ShowMessage(BAD_NUMBER_STR);

Теперь вложенных операторов if удалось избежать, а структура исходного текста стала более очевидной.

3. Интерфейс программы. Чтобы программа при запуске выглядела красиво, неплохо, чтобы главное окно (да и остальные тоже) располагалось в центре экрана (по умолчаниюони будут располагаться в той точке, куда были помещены в визуальном проектировщике). Для такой настройки в Инспекторе объектов в выпадающем списке выбирается объект Form1 и его свойству Position (Положение) задается значение poScreenCenter из списка готовых значений.

В качестве заголовка окна (свойство Caption) можно указать строку Игра в кости.


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.009 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал