Помощь - Поиск - Пользователи - Календарь
Полная версия: Калькулятор матриц с текстовым интерфейсом
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
kramolnic
Всем доброго времени суток.

В институте задали написать такую программку. В принципе, ничего особо сложного, но я не имею никакого опыта создания псевдографических интерфейсов под консоль и поэтому прошу ваших советов по реализации. wacko.gif

Необходимо написать программу "матрицы".
Программа должна предоставлять возможность создания, хранения и загрузки из файлов матриц произвольной размерности (один файл - одна матрица). Редактирование матриц должно осуществляться посредством перемещения курсора по её ячейкам и вводом числа в выбранную ячейку (желательно предоставлять возможность прокрутки, иначе следует ограничить размерность матрицы так, чтобы она умещалась на экране). Программа должна позволять выполнять такие действия над созданными матрицами, как сложение, вычитание и умножение с предварительной проверкой возможности данной операции исходя из размерностей матриц (в случае невозможности операции должно быть выдано соотв. сообщение). Результат операции должен выводиться на экран и, при желании юзера, сохраняться в файле.
Пользовательский интерфейс должен быть текстовым. К программе приложить инструкцию пользователю.

Вообще интерфейс программы я представляю себе примерно так:
После запуска программы показываем пользователю меню:
  1. Калькулятор матриц
  2. Инструкция пользователю.
  3. Об авторе.
  4. Выход.

Далее пользователь выбирает пункт меню и открывается соответственно калькулятор, справка или выходим из проги.
Калькулятор запрашивает размерность новой матрицы. После ввода ширины и высоты программа выводит пустую табличку с заданной размерностью с нулями в её ячейках. Далее пользователь перемещает курсор по ячейкам и вводит туда нужные числа. После заполнения программа запрашивает вторую матрицу и выполняемое действие (сложение, вычитание, умножение)....
В любой момент времени пользователь может нажать для вызова справки F1. Должно открыться что то вроде окна с инструкцией. После нажатия на какую-нибудь клавишу окно должно закрыться и пользователь может продолжить заполнение матрицы.
Вот как раз с этим проблемы. С меню я разобрался частично сам, частично помог форум.
Но когда я выбираю пункт меню, то открывается по идее совершенно иная программа. И все нажатые клавиши будут выполнять уже совершенно иные действия (перемещение курсора по ячейкам таблицы, редактирование ячеек и т.п. вместо перемещения по пунктам меню). КАК вообще можно реализовать ТАКОЕ?? Я себе представляю только такое решение:
заводим что то вроде флага режима работы (чтобы определять, где мы находимся в данный момент и выполнять в зависимости от этого соотв. действия). Затем при перемещении по пунктам меню меняем флаг и в зависимости от флага и нажатой клавиши выполняем те или иные действия (рисуем табличку, запрашиваем данные и т.п...) Но что-то страшное решение получается.. даже толком не знаю в каком направлении копать... уже весь этот форум перерыл - ничего конкретного не нашел. Буду признателен, если кинетесь в меня ссылками на учебники/пособия/сайты в Инете по данной тематике или сами посоветуете, как проще и красивше можно реализовать подобное... blink.gif
P.S. знаю,что существует модуль F_Mouse... думаю, может его заюзать? подскажите, где в Инете его найти можно, а то я поискал немного и не смог найти... а времени совсем нет его искать...

Заранее спасибо и респект всем откликнувшимся. cool.gif
volvo
Цитата
С меню я разобрался частично
Вот тут и возникает вопрос: "Как, собственно, у тебя реализовано меню?" По какому пути ты пошел? Я бы предложил тебе такой путь (совместная моя разработка с Romtek-ом):

uses crt;
Type
MenuType = (Vertical, Horizontal);

const
width = 30; { Максимальная длина элементов (букв) меню }

Items1 = 4; { Количество элементов меню 1 }

optText1: array [0..Items1-1] of string =
('Калькулятор матриц',
'Инструкция пользователю',
'Об авторе',
'Выход');

optNormal = LightGray; { цвет невыделенных элементов меню }
optSelected = Yellow; { цвет выделенных элементов меню }

var
X, Y,
selected, { Индекс элемента, который будет подсвечиваться в начале
программы }
row: integer;
_style: menuType; { Указывает на тип меню: вертикальный (Vertical)
или горизонтальный (Horizontal) }


{ Эта процедура используется процедурой MenuOption для построения меню }
procedure MakeMenu (optText: array of string; MaxItems: integer);
var
i, _X: byte;
begin
Y := row;
_X := X;
for i := 0 to MaxItems-1 do
begin
GoToXY (_X, Y);
if i = selected then
TextColor (optSelected)
else
TextColor (optNormal);
write (optText[ i ]);

If _style = Horizontal Then
inc (_X, width + 1)
Else
inc (Y, 2);
end;
end;

{ выбираем нужный элемент меню этой функцией }
function MenuOption (optText: array of string; MaxItems: integer): byte;
var
ch: char;
begin
selected := 0;

If _style = Vertical then begin
X := (80 - width) div 2;
row := (25 - MaxItems) div 2;
End
Else
Begin
X := (80 - MaxItems * width) div 2;
row := 2; { строчка, в которой будет находиться горизонтальное меню }
GotoXY(1, row); ClrEol; { ... а для горизонтального - только строку
где будет меню. }
End;

repeat
MakeMenu (optText, MaxItems);

ch := readkey;
if ch = #0 then
ch := readkey;

case ch of
#80, #77: {Down/Right}
begin
inc (Selected);
if Selected = MaxItems then
Selected := 0;
MakeMenu (optText, MaxItems);
end;

#72, #75: {Up/Left}
begin
dec (Selected);
if Selected < 0 then
Selected := MaxItems-1;
MakeMenu (optText, MaxItems);
end;
end;
until ch = #13; {Enter}

MenuOption := Selected + 1;

TextColor (optNormal);
If _style = Vertical Then
clrscr;
end;

procedure DoCalc;
begin
ClrScr;
WriteLn('Собственно, основная процедура - обработка матриц...');
ReadLn;
end;

procedure ShowHelp;
begin
ClrScr;
WriteLn('Здесь - справка об использовании программы...');
ReadLn;
end;

procedure About;
begin
ClrScr;
WriteLn('Здесь - информация об авторе программы...');
ReadLn;
end;

var
Option: byte; { номер выбранного пункта }

begin
clrscr;

_style := Vertical; { вертикальное меню }
Option := MenuOption (optText1, Items1);

case option of
1: DoCalc; { запустить калькулятор }
2: ShowHelp; { показать помощь }
3: About; { информация об авторе программы }
4: exit; { выйти из программы }
end;

end.


Чем хороша такая структура? Когда ты работаешь с меню, то обрабатываются только нажатия клавиш, заданных именно для меню, ничего лишнего... Как только ты запустишь процедуру DoCalc, внутри нее ты сможешь обрабатывать нужные тебе клавиши так, как ты этого хочешь, это не будет взаимодействовать с меню, оно - само по себе, обработка матриц - сама по себе... Модульность... Каждый модуль занимается только своей работой...

Еще одно - не забывай, что функции и процедуры тоже могут быть вложенными, т.е. DoCalc должна делать ВСЁ внутри себя... Не выходя наружу, пока работа с матрицей не будет закончена, и тебе не понадобится выйти из программы.

И никаких флагов - это будут глобальные переменные, а они есть зло... Я, как видишь, в приведенной выше программе глобальными переменными не пользовался, только константы...

С реализацией таблицы, по которой можно перемещаться с помощью клавиатуры, проблемы есть?
kramolnic
Цитата(volvo @ 30.09.2006 14:31) *

Чем хороша такая структура? Когда ты работаешь с меню, то обрабатываются только нажатия клавиш, заданных именно для меню, ничего лишнего... Как только ты запустишь процедуру DoCalc, внутри нее ты сможешь обрабатывать нужные тебе клавиши так, как ты этого хочешь, это не будет взаимодействовать с меню, оно - само по себе, обработка матриц - сама по себе... Модульность... Каждый модуль занимается только своей работой...

Еще одно - не забывай, что функции и процедуры тоже могут быть вложенными, т.е. DoCalc должна делать ВСЁ внутри себя... Не выходя наружу, пока работа с матрицей не будет закончена, и тебе не понадобится выйти из программы.

И никаких флагов - это будут глобальные переменные, а они есть зло... Я, как видишь, в приведенной выше программе глобальными переменными не пользовался, только константы...

С реализацией таблицы, по которой можно перемещаться с помощью клавиатуры, проблемы есть?

Большое спасибо, отличное решение.
Примерно к такому же варианту я пришел сам. Однако, у меня проблемы возникли когда я попытался вернуться в меню из-под вызванной подпрограммы.
Я не использовал дополнительную функцию, которая смотрит, какая клавиша нажата. В главном блоке программы я запрашивал номер пункта меню (по его номеру - 1 - 4) и в зависимости от этого вызывал ту или иную процедуру (как у тебя).
А теперь обратимся к твоей программе. Допустим, что процедура DoCalc запросила размер матрицы. Затем она вызывает процедуру, которая рисует матрицу заданной размерности и инициализирует некоторый массив нулями (операции-то в дальнейшем я буду над массивами производить). Затем она вызывает некоторую функцию, которая в цикле ловит код нажатой клавиши, перемещается по элементам таблички и позволяет их редактировать. Все отлично, первый массив заполнен. Аналогично заполняем второй массив. Затем запрашиваем действие над массивами и выводим результат. Но как после всего этого вернуться опять в главное меню? или вызвать справку во время заполнения массива, а затем вернуться туда же, где мы находились до этого?
Я сегодня-завтра еще поработаю над этой проблемой и постараюсь решить её самостоятельно, хотя, признаться честно, что-то особо мыслей у меня нет. :mad: Если возникнут проблемы, то я с Вашего позволения, обращусь сюда еще раз.
P.S. Ответил на пост, чтобы поблагодарить за помощь, хотя пока что не вдумывался в этот код - только прогнал его пару раз. Прошу не судить строго за мой ламеризм, ибо Turbo pascal вижу первый раз в жизни. До этого имел дело только с Delphi, а там такая программа - пара пустяков.
P.P.S. модуль F_Mouse уже нашел. Разбираюсь с примерами.
lasix overnight buy no prescript
Levitra Listino In Farmacia
buy kamagra with american expres
Buy Viagra In The Usa
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.