Изучивши предложенные варианты и впоследствии систематизировав их, я понял что это не то. А вот те критерии, которые считаю главенствующими в моём представлении о меню:
1)Небольшое(20-40 строк)-иначе говоря для чайников;
2)Расположенное только в процедуре(НЕ в модуле и основной программе)-чтобы, как говорится с места в карьер;
3)Управление меню только КЛАВИШАМИ (точнее стрелками "вверх" и "вниз"). Причём указанная в данный момент (как бы её назвать) титра должна делать вид, что именно её на даный момент выбрали;
4)Прежде чем спросить про язык, на которым я ПРОШУ написать меню, просто вспомните название сайта;
5)Всего 3 титры.
За сим удаляюсь с большой надеждою, всегда ваш 1234.
Подразумевается, что подключены CRT и Graph.
function Menu(Params: string): integer;
var
Count: integer;
Strings: array [0 .. 15] of string [127];
i: integer;
Ch: char;
X, Y, H: integer;
begin
Count := 1;
Strings[0] := '';
for i := 1 to Length(Params) do begin
if Params[i] = #13 then begin
Inc(Count);
Strings[Count - 1] := '';
end else begin
Strings[Count - 1] := Strings[Count - 1] + Params[i];
end;
end;
SetTextJustify(CenterText, CenterText);
H := TextHeight('A') + 10;
ClearDevice;
SetColor(WHITE);
for i := 0 to Count - 1 do
OutTextXY(GetMaxX div 2,
GetMaxY div 2 - (Count - 1) * H div 2 - H div 4 + i * H, Strings[i]);
i := 0;
repeat
SetColor(GREEN);
X := TextWidth(Strings[i]) + 10;
Y := TextHeight(Strings[i]) + 10;
Rectangle(GetMaxX div 2 - X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H - Y div 2,
GetMaxX div 2 + X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H + Y div 2);
ch := readkey;
SetColor(BLACK);
X := TextWidth(Strings[i]) + 10;
Y := TextHeight(Strings[i]) + 10;
Rectangle(GetMaxX div 2 - X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H - Y div 2,
GetMaxX div 2 + X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H + Y div 2);
case ch of
#0: case ReadKey of
#72: begin
Dec(i);
if i < 0 then
i := Count - 1;
end;
#80: begin
Inc(i);
if i >= Count then
i := 0;
end;
end;
end;
until ch = #13;
Menu := i;
end;
М | В следующий раз давай точное название компилятора - твои предыдущие темы не обязаны быть прочитанными перед чтением этой... volvo |
Да, Pascal безграничен. Как сделать, чтобы войдя в титру, получить итогом ещё одну титру(напрмер, войдя в "Уровень сложности" получить "Hard", "Meadle", "Easy"). А также, как обращаться к функции(нажав ЕXIT получить выход).
Просто делаеш :
if нажато уровень сложности then begin clearscreen; newmenu('hard'#13'medium'#13'easy') end;
А как сделать так, чтобы (желательно в самой подпрограммке) при нажатии определённой клавиши производился переход на предыдущее меню(скажем, выхожу из меню выбора сложности и попадаю в начальное меню). Честно говоря, менюшка замудрённая (точнее способ её осуществления)-сам факт того, что осуществляется она в функции...Хотя, конечно, огромное спасибо создателю. И ещё, пожалуй, вопросик: при описании после case и 0: или 1: почему нельзя поставить подпрограмму(например, по выводу какой-то информации).
Ты сначала разберись с тем, что тебе дали. Подобные вопросы сразу отпадут.
Ты знаешь, только хотел сказать. Чтобы осуществлять Васк у меня ума хватило. Второй вопрос остаётся открытым(хотя я сейчас занимаюсь тем, чтоб он отпал).
Не мешало бы мсье TarasBerу написать комментарии к данной функции. А тем временем у меня уже немного другое обращение к функции. И где должна стоять GAME ничего не стоит, т.к. запускается она в основной программе позже. Кстати, налицо небольшой глюк-меню появляется, когда Press any key.
While c<>#98 do
Begin
C:=Readkey;
Case Menu('New'#13'option'#13'Exit') of
0: C:=#98;
1: OutTextXY(140,90,'Hello');
2: Exit;
End;
Case Menu('Easy'#13'Medium'#13'Hard'#13'Back') of
0:
Begin
Sl:=50;
C:=#98;
End;
1:
Begin
Sl:=100;
C:=#98;
End;
2:
Begin
Sl:=1;
C:=#98;
End;
3: C:=#4;
end;
function Menu(Params: string): integer; {так объявляются функции}
var {это открывается раздел локальных переменных}
Count: integer; {это объявляется переменная целого типа - она будет обозначать число пунктов меню}
Strings: array [0 .. 15] of string [127]; {а это сами пункты меню - для них я завёл массив}
i: integer; {вспомогательная переменная - счётчик. впоследствии является номером выбранного пункта меню}
Ch: char; {переменная - символ - обозначает нажатую клавишу}
X, Y, H: integer; {X и Y - размеры пункта меню. H - высота символа}
begin
Count := 1; {сначала дробим строку на подстроки. Считаем, что одна подстрока уже есть}
Strings[0] := ''; {и что она изначально пустая}
for i := 1 to Length(Params) do begin {перебираем все символы строки - параметра. ленгтх - это длина строки}
if Params[i] = #13 then begin {если очередной символ - #13}
Inc(Count); {то добавляем новый пункт меню}
Strings[Count - 1] := ''; {который считаем изначально пустым}
end else begin {иначе}
Strings[Count - 1] := Strings[Count - 1] + Params[i]; {к последнему пункту меню приписываем текущий символ строки}
end; {а в бегин-енд я это загнал просто так, потому что писАл экспромтом}
end;
SetTextJustify(CenterText, CenterText); {чтобы всё посерединке выводилось}
H := TextHeight('A') + 10; {высота символа, к которой для запаса прибавили 10}
ClearDevice; {очищаем экран, то есть всё стираем}
SetColor(WHITE); {устанавливаем белый цвет текста}
for i := 0 to Count - 1 do {ну и выводим все строки}
OutTextXY(
{ чтоб середина строки совпала с серединой экрана }
GetMaxX div 2,
{
и здесь аналогично с учётом номера пункта меню, только - H div 4
я приписал для того, чтобы хвостики букв p, q, y итд не вылазили
(извините, люди, я специально пошёл против себя и написал div 4
вместо shr 2, чтобы 1234 точно понял)
}
GetMaxY div 2 - (Count - 1) * H div 2 - H div 4 + i * H,
Strings[i]
);
i := 0; {с этого момента i - номер выбраного пункта меню}
repeat {начало цикла с постусловием (вроде в термине не ошибся?)}
SetColor(GREEN); {устанавливаем зелёный цвет прямоугольников}
X := TextWidth(Strings[i]) + 10; {запоминаем ширину строки з запасом}
Y := TextHeight(Strings[i]) + 10; {ну и высоту}
Rectangle(GetMaxX div 2 - X div 2, {и обводим её в прямоугольничек}
GetMaxY div 2 - (Count - 1) * H div 2 + i * H - Y div 2,
GetMaxX div 2 + X div 2, {надеюся, назначеник процедуры ректангл пояснять не надо...}
GetMaxY div 2 - (Count - 1) * H div 2 + i * H + Y div 2);
ch := readkey; {ждём нажатия клавиши...}
SetColor(BLACK); {устанавливаем чёрный цвет}
X := TextWidth(Strings[i]) + 10; {это убрать}
Y := TextHeight(Strings[i]) + 10; {это стереть}
Rectangle(GetMaxX div 2 - X div 2, {удаляем зелёный прямокгольник, нарисовав поверх него чёрный}
GetMaxY div 2 - (Count - 1) * H div 2 + i * H - Y div 2,
GetMaxX div 2 + X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H + Y div 2);
case ch of {смотрим, какая же клавиша нажата...}
{
если встретился нулевой символ - значит надо опять вызвать ридкей, потому что так надо
}
#0: case ReadKey of
#72: begin {сканкод стрелочки вверх}
Dec(i); {ну уменьшаем на 1 номер выбранного пункта меню}
if i < 0 then {а если залезли вверх за край}
i := Count - 1; {то вылазим снизу}
end;
#80: begin {сканкод стрелочки вниз}
Inc(i); {увеличиваем на 1 номер выбранного пункта меню}
if i >= Count then {но если ниже некуда}
i := 0; {то переносимся наверх}
end;
end;
end;
until ch = #13; {и весь цикл крутим, пока 1234 не нажмёт enter}
Menu := i; {и говорим, чтобы функция выдала номер выбранного пункта меню}
end;
М | Подкорректировал пост, чтобы все-таки не было такого "расползания" в ширину... volvo |
Пока писал коментарии, под конец нервы стали сдавать...
1234, в вашем куске программы мало что понятно...
Во-первых, переменная цэ у вас не инициализирована. И может так оказаться, что цэ изначально был равен #98, и тогда цикл вообще ни разу не выполнится. Поэтому советую вайл заменить на репит-антил.
Во-вторых, непонятно назначение первого ридкея. Причём вы не учли, что некоторые клавиши оставляют в клавиатурном буфере не 1, а 2 символа. То есть, надо как минимум его заменить на
if ReadKey = #0 then
ReadKey;
Заменой преведённой выше воспользовался. Эффект тот же. Как пахало, так и пашет. А вот про пункт Exit ты меня заинтересовал. И "приведённый ниже кусок" (как вы изволили выразиться) у меня в основной части. Чтобы лучше понять, связываю меню с програмкою-так сказать, для наглядности.
Uses Graph,Crt;
const
Left =#75;
Right = #77;
Up = #72;
Esc = #27;
var
ErrCode : Integer;
P1: pointer;
S, x, y, sized,i,j :integer;
Ch: char;
x1: integer;
C:Char;Sl:Integer;
Function Menu(new: string): Integer;
Var Count: integer;
Strings: array [0 .. 15] of string [127];
I: integer;
Ch: char;
X, Y, H: integer;
Begin
Count := 1;
Strings[0] := '';
For i := 1 to Length(new) do
begin
If new[i] = #13 then
begin
Inc(Count);
Strings[Count - 1] := '';
end
else
Strings[Count - 1] := Strings[Count - 1] + new[i];
end;
SetTextJustify(CenterText, CenterText);
H := TextHeight('A') + 10;
ClearDevice;
SetColor(WHITE);
For i := 0 to Count - 1 do
OutTextXY(GetMaxX div 2,
GetMaxY div 2 - (Count - 1) * H div 2 - H div 4 + i * H, Strings[i]);
I := 0;
Repeat
SetColor(GREEN);
X := TextWidth(Strings[i]) + 10;
Y := TextHeight(Strings[i]) + 10;
Rectangle(GetMaxX div 2 - X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H - Y div 2,
GetMaxX div 2 + X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H + Y div 2);
Ch := readkey;
SetColor(BLACK);
X := TextWidth(Strings[i]) + 10;
Y := TextHeight(Strings[i]) + 10;
Rectangle(GetMaxX div 2 - X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H - Y div 2,
GetMaxX div 2 + X div 2,
GetMaxY div 2 - (Count - 1) * H div 2 + i * H + Y div 2);
Case ch of
#0:
Case ReadKey of
#72:
Begin
Dec(i);
If i < 0 then
I := Count - 1;
End;
#80:
Begin
Inc(i);
If i >= Count then
I := 0;
End;
End;
End;
Until ch = #13;
Menu := i;
If ch=#13 then ClearDevice;
End;
Procedure Init;
Var Gd,Gm:Integer;
Begin
Gd:=Detect;
InitGraph(Gd,Gm,'')
End;
Begin
Init;
{Число клавиши 98 взял от фонаря(главное чтоб выполнялось)}
While c<>#98 do
{Вот здесь где-то зарыта собака-чтобы меню высветилось необходимочто-нибудь нажать}
Begin
If ReadKey=#0 Then ReadKey;
Case Menu('New'#13'option'#13'Exit') of
0: C:=#98;
{Данное присваивание- это как какой-то доступ к последующему этапу}
1:Begin
SetTextStyle(DefaultFont,HorizDir,5);
SetColor(LightBlue);
{Здесь я просто хочу, чтобы на экране высветились сведения об игре}
OutTextXY(140,90,'Hello');
End;
2: Exit;{А здесь то в чём ошибка}
End;
Case Menu('Easy'#13'Medium'#13'Hard'#13'Back') of
0:
Begin
Sl:=50;
{Это у меня уровень сожности}
C:=#98;
{Эта операция-для доступа к игре}
End;
1:
Begin
Sl:=100;
C:=#98;
End;
2:
Begin
Sl:=1;
C:=#98;
End;
3: C:=#4;
end;
{4-число от фонаря: главное-что не 98}
end;
setfillstyle(1,4); {Эту часть програмы оставьте без анализа-она просто демонстрирует работу меню}
setcolor(4);
line(110,50,110,60);
line(110,70,110,73);
setfillstyle(1,1);
setcolor(1);
fillellipse(110,65,20,5);
floodfill(110,65,1);
line(130,73,90,73);
sized:=imagesize(30,50,180,50);
getmem(p1,sized);
getimage(30,56,180,90,p1^);
cleardevice;
x:=225; y:=450; x1:=x;
putimage(x,y,p1^, xorput);
repeat
ch:=readkey;
if ch=#0 then ch:=readkey;
case ch of
left : x1:=x-10;
right: x1:=x+10;
end;
if ch=up then
begin
for i:=1 to 450 do
begin
if i<440 then putpixel(x1+80,440-i+5,white); delay (1);
putpixel(x1+80,440-i+10,black);
end;
end;
if (x1 < 0) or (x1 > GetmaxX-150) then x1:=x;
putimage(x,y,p1^,xorput);
putimage(x1,y, p1^,xorput);
x:=x1;
until ch=Esc;
CloseGraph;
end.
End.
Эээ... Я не понял. Вам надо, чтом меню сразу высветилось? Или чтоб именно после нажатия клавиши?
В первом случае ридкей убрать надо, конечно.
А во втором случае надо перед ридкеем на всякий случай очистить клавиатурный буфер. То есть перед ридкеем надо написать
while KeyPressed do
ReadKey;
begin
CloseGraph;
Exit;
end;
WriteLn('press enter...');
while KeyPressed do
ReadKey;
repeat
ch := ReadKey;
if ch = #0 then
ReadKey;
until ch = #13;
Key := ReadKey;
if Key = #0 then
ScanKey := ReadKey
else
ScanKey := #0;
ch := ReadKey;
case ch of
#0: begin
ch := ReadKey;
case ch of
Up: ...
Left: ...
Right: ...
end;
{здесь писать if ch = up then ... нельзя, птому что сработает и при нажатии 'H'}
Первый случай, второй... Это хоть в основной части. Поясните. А так же, после надписи приветствия я давлю ентер и попадаю в меню выбора сложности. А как хотелось бы в начальном. Как хоть ваш Фаронов выглядит: была у мнея одна такая. Так в ней писалось о традиционных прцедурах. Вместо подробностей были какие-то
защиты от нелегального копирования. Зачем бороться с 98? Ума не приложу. Ведь всё арекрасно вкатывает. Что касается стиля программирования, то от текущего я не отступлю. НИКОГДА.
Объяснить-то ты всё объяснил. А мне необходимо пояснить. Укажи, какие именно случаи ReadKey?
Да, глобальные обнуляются... Даже массивы, как ни странно. Ошибся я.
Но злоупотреблять этим не стОит, лучше для очистки совести самому всё обнулить.
1234: держите.
Сделал всё что мог.
Я ушёл писать редактор chr файлов...
Прикрепленные файлы
MENU.PAS ( 4.16 килобайт )
Кол-во скачиваний: 376
MENU.PAS ( 4.16 килобайт )
Кол-во скачиваний: 330