Menu programu w trybie graficznym - nie wyswietla sie prawidlowo

0

Próbuję napisać menu do mojej symulacji Układu Słonecznego przy użyciu biblioteki allegro. Napisałem procedurę ReadNumber, która działa w trybie graficznym analogicznie do procedury readln z trybu tekstowego. Wczytuje ona symbole (cyfry, znak -, oraz .) i wypisuje je w czasie rzeczywistym na ekranie, dopóki nie naciśnie się klawisza enter, a potem przekonwertowuje to do typu real. Procedura działa dobrze, gdy jest w oddzielnym programie, a nawet gdy jest na samym początku poniższego programu, ale gdy próbuję ją umieścić "w menu", aby uruchamiała się po wybraniu odpowiedniej opcji (konkretnie: "zmień promień Slonca"), to nie działa prawidłowo. Wyświetla mi tylko napis "Podaj liczbe". Oto kod programu:

Program MenuUkladu;

uses
allegro, graphics; 

type 
	wektor = array[1..100] of integer; 

var
	i,j: integer;
	promien, masa: real;
	
procedure KeysOff();

begin
	al_key[AL_KEY_DOWN]:=0; //wylaczam sobie wszystkie klawisze
	al_key[AL_KEY_UP]:=0;
	al_key[AL_KEY_ENTER]:=0;
end;	
	
procedure WriteMenu(i: integer); //procedura wyswietlajaca Glowne Menu i podswietlajaca ktoras z opcji w zaleznosci od parametru i

begin
	if i=1 then 
	begin
		al_clear_to_color(AL_SCREEN, black);
		al_textout_ex(AL_SCREEN, al_font, 'Menu:', 200, 200, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'START', 200, 210, black, red); //podswietlony zostanie START
		al_textout_ex(AL_SCREEN, al_font, 'Zmien predkosc Ziemi', 200, 220, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien promien Slonca', 200, 230, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien mase Jowisza', 200, 240, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zakoncz', 200, 250, red, black);
	end;
	if i=2 then	
	begin
		al_clear_to_color(AL_SCREEN, black);
		al_textout_ex(AL_SCREEN, al_font, 'Menu:', 200, 200, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'START', 200, 210, red, black); 
		al_textout_ex(AL_SCREEN, al_font, 'Zmien predkosc Ziemi', 200, 220, black, red); //podswietlona zostanie druga opcja
		al_textout_ex(AL_SCREEN, al_font, 'Zmien promien Slonca', 200, 230, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien mase Jowisza', 200, 240, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zakoncz', 200, 250, red, black);
	end;
	if i=3 then
	begin
		al_clear_to_color(AL_SCREEN, black);
		al_textout_ex(AL_SCREEN, al_font, 'Menu:', 200, 200, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'START', 200, 210, red, black); 
		al_textout_ex(AL_SCREEN, al_font, 'Zmien predkosc Ziemi', 200, 220, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien promien Slonca', 200, 230, black, red); //itd. itd.
		al_textout_ex(AL_SCREEN, al_font, 'Zmien mase Jowisza', 200, 240, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zakoncz', 200, 250, red, black);
	end;
	if i=4 then
	begin
		al_clear_to_color(AL_SCREEN, black);
		al_textout_ex(AL_SCREEN, al_font, 'Menu:', 200, 200, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'START', 200, 210, red, black); 
		al_textout_ex(AL_SCREEN, al_font, 'Zmien predkosc Ziemi', 200, 220, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien promien Slonca', 200, 230, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien mase Jowisza', 200, 240, black, red);
		al_textout_ex(AL_SCREEN, al_font, 'Zakoncz', 200, 250, red, black);
	end;
	if i=5 then	
	begin
		al_clear_to_color(AL_SCREEN, black);
		al_textout_ex(AL_SCREEN, al_font, 'Menu:', 200, 200, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'START', 200, 210, red, black); 
		al_textout_ex(AL_SCREEN, al_font, 'Zmien predkosc Ziemi', 200, 220, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien promien Slonca', 200, 230, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien mase Jowisza', 200, 240, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zakoncz', 200, 250, black, red);
	end;
end;

function String2Real(var x: wektor; wymiar: integer): real; //funkcja przekonwertowuje liczbe wprowadzona jako tablice na liczbe typu real

var
	i,j,k: integer; 
	n, licznik: real;

//w funkcji zakladamy rozsadek uzytkownika, tzn ze minus moze wystapic tylko raz i tylko na poczatku tablicy, a kropka moze wystapic tylko raz i w srodku liczby	

begin
	k:=wymiar+1; //zakladam ze liczba jest calkowita 
	j:=1; 
	while (k=wymiar+1) and (j<>wymiar+1) do //petla sie zakonczy jak znajdzie kropke, lub "przebiegnie" cala tablice
	begin
		if x[j]=46 then
			k:=j;
		j:=j+1; 
	end;
		
	n:=0;
	licznik:=1;
	for j:=k-1 downto 2 do //ta petla "wyluskuje" czesc calkowita liczby
	begin
		n:=n+x[j]*licznik; 
		licznik:=licznik*10;
	end;
	if x[1]=45 then //jak pierwszy element tablicy to minus, to wtedy mnoze liczbe przez -1
		n:=-n
	else 
		n:=n+x[1]*licznik; //a jak nie, to normalnie zwiekszam liczbe n
	
	if k<>wymiar+1 then //ten warunek sprawdza czy liczba jest calkowita czy nie
	begin
		if x[1]<>45 then //jak liczba jest nieujemna
		begin
			licznik:=0.1;
			for j:=k+1 to wymiar do //jak liczba nie jest calkowita, to ta petla "wyluskuje" czesc ulamkowa 
			begin
				n:=n+x[j]*licznik;
				licznik:=licznik/10;
			end;
		end
		else //gdy liczba jest ujemna
		//if liczba[1]=45 then //jak liczba jest ujemna
		begin
			licznik:=0.1;
			for j:=k+1 to wymiar do 
			begin
				n:=n-x[j]*licznik;
				licznik:=licznik/10;
			end;
		end;
	end;
	String2Real:=n;

end;	
	
procedure ReadNumber(var x: real); //procedura analogiczna do readln, ktora wczytuje liczbe rzeczywista w trybie graficznym

var
	i, klawisz: integer;
	tablica: array[1..100] of integer;

begin
	KeysOff;
	al_clear_to_color(AL_SCREEN, black);
	al_textout_ex(AL_SCREEN, al_font, 'Podaj liczbe: ', 200, 200, red, black);
	i:=1; 
	repeat 
		klawisz:=al_readkey;
		case klawisz of
			6960: 
			begin
				tablica[i]:=0;
				al_textout_ex(AL_SCREEN, al_font, '0', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			7217: 
			begin
				tablica[i]:=1;
				al_textout_ex(AL_SCREEN, al_font, '1', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			7474: 
			begin
				tablica[i]:=2;
				al_textout_ex(AL_SCREEN, al_font, '2', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			7731: 
			begin
				tablica[i]:=3;
				al_textout_ex(AL_SCREEN, al_font, '3', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			7988: 
			begin
				tablica[i]:=4;
				al_textout_ex(AL_SCREEN, al_font, '4', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			8245: 
			begin
				tablica[i]:=5;
				al_textout_ex(AL_SCREEN, al_font, '5', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			8502: 
			begin
				tablica[i]:=6;
				al_textout_ex(AL_SCREEN, al_font, '6', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			8759: 
			begin
				tablica[i]:=7;
				al_textout_ex(AL_SCREEN, al_font, '7', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			9016: 
			begin
				tablica[i]:=8;
				al_textout_ex(AL_SCREEN, al_font, '8', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			9273: 
			begin
				tablica[i]:=9;
				al_textout_ex(AL_SCREEN, al_font, '9', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			18734: //gdy zostanie wcisnieta kropka
			begin
				tablica[i]:=46; //kod kropki w ASCII
				al_textout_ex(AL_SCREEN, al_font, '.', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			15661: //gdy zostanie wcisniety znak minus
			begin
				tablica[i]:=45;
				al_textout_ex(AL_SCREEN, al_font, '-', 300+7*i, 200, red, black);
				i:=i+1;
			end;
			16136: //gdy wcisniety zostanie back space
			begin
				i:=i-1; //cofamy sie o jeden
				al_textout_ex(AL_SCREEN, al_font, ' ', 300+7*i, 200, black, black); //zamazuje niechciana cyfre
			end;
		end;
	until klawisz=17165; //jak wcisniemy enter, to petla sie zakonczy
	
	x:=String2Real(tablica, i-1);
end;



	
begin
	inicjalizuj;
	i:=0; 
	al_key[AL_KEY_DOWN]:=1; //to dlatego, ze warunkiem pierwszego ifa jest wcisniecie UP lub DOWN
	while (i<>5) or (al_key[AL_KEY_ENTER]=0) do //program ma sie zakonczyc, gdy (i=5) and (al_key[AL_KEY_ENTER]<>0) w while musi byc warunek dzialania, a wiec nalezy tu wstawic zaprzeczenie tego wyrazenie
	begin
		//al_key[AL_KEY_DOWN]:=1;
		if (al_key[AL_KEY_DOWN]<>0) or (al_key[AL_KEY_UP]<>0) then //gdy zostanie wcisniety DOWN albo UP... 
		begin
			if al_key[AL_KEY_DOWN]<>0 then
				if i>5 then //dodawanie (modulo 5) gdy zostanie wcisniety klawisz down 
					i:=1 
				else 
					i:=i+1;
			if al_key[AL_KEY_UP]<>0 then
				if i<1 then
					i:=5
				else
					i:=i-1;
			if i=1 then 
			begin 
				KeysOff;
				WriteMenu(i);
				while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) and (al_key[AL_KEY_ENTER]=0) do; //czeka na wcisniecie DOWN, UP, albo enter 
			end;
			if i=2 then //zmiana predkosci Ziemi
			begin
				KeysOff;
				WriteMenu(i);
				while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) do;
				
			end;
			if i=3 then //zmiana promienia Slonca
			begin
				KeysOff;
				WriteMenu(i);
				while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) and (al_key[AL_KEY_ENTER]=0) do;
				if al_key[AL_KEY_ENTER]<>0 then //gdy zostanie wcisniety klawisz enter
					ReadNumber(promien);
			end;
			if i=4 then //zmiana masy Jowisza
			begin
				KeysOff;
				WriteMenu(i);
				while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) do;
			end;
			if i=5 then //wylaczenie programu
			begin
				KeysOff;
				WriteMenu(i);
				while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_ENTER]=0) and (al_key[AL_KEY_UP]=0) do; //tu czekna na nacisniecie klawisza down, up, albo enter
			end;
		end;
		
	end;
	al_exit;
end.


 

"Graphics" to mój moduł, w którym umieściłem procedurę inicjalizującą bibliotekę allegro, oraz funkcje red, green, blue, black. Czy możecie rzucić na to okiem i powiedzieć mi co jest nie tak?

1

Powoli, powoli.
Gdybyś miał 50 opcji w WriteMenu to też byś robił Ctrl+C/Ctrl+V 50 razy? Nie widzisz, że coś tutaj nie pasuje?
ReadNumber to również porażka.
String2Real - w imię czego ta funkcja ma w nazwie String, skoro przyjmuje wektor? :|

1

Zrób zrzut ekranu, bo sam opis i kod to za mało; Poza tym procedura WriteMenu wręcz dopomina się, aby użyć w niej instrukcji Case, a nie pięciu If, które nawet nie posiadają Else...

1

Nieco skróciłem jedną funkcje:

procedure ReadNumber(var x: real); //procedura analogiczna do readln, ktora wczytuje liczbe rzeczywista w trybie graficznym
var  i, klawisz: integer;
var  tablica: array[1..100] of integer;
 var ch:byte;
begin
    KeysOff;
    al_clear_to_color(AL_SCREEN, black);
    al_textout_ex(AL_SCREEN, al_font, 'Podaj liczbe: ', 200, 200, red, black);
    i:=1; 
    repeat 
        klawisz:=al_readkey;
        case klawisz of
            18734: //gdy zostanie wcisnieta kropka
            begin
                tablica[i]:=46; //kod kropki w ASCII
                al_textout_ex(AL_SCREEN, al_font, '.', 300+7*i, 200, red, black);
                i:=i+1;
            end;
            15661: //gdy zostanie wcisniety znak minus
            begin
                tablica[i]:=45;
                al_textout_ex(AL_SCREEN, al_font, '-', 300+7*i, 200, red, black);
                i:=i+1;
            end;
            16136: //gdy wcisniety zostanie back space
            begin
                i:=i-1; //cofamy sie o jeden
                al_textout_ex(AL_SCREEN, al_font, ' ', 300+7*i, 200, black, black); //zamazuje niechciana cyfre
            end;
            else
            begin
                ch:=((klawisz)and($FF))-Ord('0');
                if (0<=ch)and(ch<=9) then
                begin
                  tablica[i]:=ch;
                  al_textout_ex(AL_SCREEN, al_font, '0', 300+7*i, 200, red, black);
                  Inc(i);
                end;
            end;
        end;
    until klawisz=17165; //jak wcisniemy enter, to petla sie zakonczy
    x:=String2Real(tablica, i-1);
end;
0
Patryk27 napisał(a):

Powoli, powoli.
Gdybyś miał 50 opcji w WriteMenu to też byś robił Ctrl+C/Ctrl+V 50 razy? Nie widzisz, że coś tutaj nie pasuje?

Masz rację - wygląda to oczojebnie i na początku ta procedura wyglądała inaczej:

procedure WriteMenu(i: integer); //procedura wyswietlajaca Glowne Menu i podswietlajaca ktoras z opcji w zaleznosci od parametru i

begin
	if i=1 then 
	begin
		al_clear_to_color(AL_SCREEN, black);
		al_textout_ex(AL_SCREEN, al_font, 'Menu:', 200, 200, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'START', 200, 210, black, red); //podswietlony zostanie START
		al_textout_ex(AL_SCREEN, al_font, 'Zmien predkosc Ziemi', 200, 220, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien promien Slonca', 200, 230, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien mase Jowisza', 200, 240, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zakoncz', 200, 250, red, black);
	end;
	if i=2 then	
	begin
		al_textout_ex(AL_SCREEN, al_font, 'START', 200, 210, red, black); 
		al_textout_ex(AL_SCREEN, al_font, 'Zmien predkosc Ziemi', 200, 220, black, red); //podswietlona zostanie druga opcja
		al_textout_ex(AL_SCREEN, al_font, 'Zmien promien Slonca', 200, 230, red, black);
	end;
	if i=3 then
	begin
		al_textout_ex(AL_SCREEN, al_font, 'Zmien predkosc Ziemi', 200, 220, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien promien Slonca', 200, 230, black, red); //itd. itd.
		al_textout_ex(AL_SCREEN, al_font, 'Zmien mase Jowisza', 200, 240, red, black);
	end;
	if i=4 then
	begin
		al_textout_ex(AL_SCREEN, al_font, 'Zmien promien Slonca', 200, 230, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zmien mase Jowisza', 200, 240, black, red);
		al_textout_ex(AL_SCREEN, al_font, 'Zakoncz', 200, 250, red, black);
	end;
	if i=5 then	
	begin
		al_textout_ex(AL_SCREEN, al_font, 'START', 200, 210, red, black); 
		al_textout_ex(AL_SCREEN, al_font, 'Zmien mase Jowisza', 200, 240, red, black);
		al_textout_ex(AL_SCREEN, al_font, 'Zakoncz', 200, 250, black, red);
	end;
end; 

Raz wypisywała całe menu z podświetloną opcją "START", a potem tylko podświetlała nowo wybraną opcję i "zamalowywała" poprzednią (tę nad, albo tę pod). I to działało, jak menu miało tylko jeden "pziom", ale zmieniłem to, jak dodałem kolejny "poziom". Przykładowo po wpisaniu nowego promienia Slońca i wciśnieciu klawisza enter, program powienien wrócić do poprzedniego widoku menu z podświetloną opcją "Zmien promień Slonca", a żeby tak się stało to niestety musi je napisać od nowa. Mam nadzieję, że wytłumaczyłem to jasno.

Teraz wpadłem na pomysł, że w sumie można po wyjściu z podmenu dwa razy wywołać procedurę WriteMenu, raz z parametrem i=1, a raz np. z i=3:

if i=3 then //zmiana promienia Slonca
begin
    KeysOff;
    WriteMenu(1);
    WriteMenu(3);
    while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) and al_key[AL_KEY_ENTER]=0) do;
    if al_key[AL_KEY_ENTER]<>0 then //gdy zostanie wcisniety klawisz enter
        ReadNumber(promien);
end;

Może tak jest bardziej elegancko?

String2Real - w imię czego ta funkcja ma w nazwie String, skoro przyjmuje wektor? :|
Pomyślę jeszcze nad nazwą :)

_13th_Dragon napisał(a):

Nieco skróciłem jedną funkcje:

procedure ReadNumber(var x: real); //procedura analogiczna do readln, ktora wczytuje liczbe rzeczywista w trybie graficznym
var  i, klawisz: integer;
var  tablica: array[1..100] of integer;
 var ch:byte;
begin
    KeysOff;
    al_clear_to_color(AL_SCREEN, black);
    al_textout_ex(AL_SCREEN, al_font, 'Podaj liczbe: ', 200, 200, red, black);
    i:=1; 
    repeat 
        klawisz:=al_readkey;
        case klawisz of
            18734: //gdy zostanie wcisnieta kropka
            begin
                tablica[i]:=46; //kod kropki w ASCII
                al_textout_ex(AL_SCREEN, al_font, '.', 300+7*i, 200, red, black);
                i:=i+1;
            end;
            15661: //gdy zostanie wcisniety znak minus
            begin
                tablica[i]:=45;
                al_textout_ex(AL_SCREEN, al_font, '-', 300+7*i, 200, red, black);
                i:=i+1;
            end;
            16136: //gdy wcisniety zostanie back space
            begin
                i:=i-1; //cofamy sie o jeden
                al_textout_ex(AL_SCREEN, al_font, ' ', 300+7*i, 200, black, black); //zamazuje niechciana cyfre
            end;
            else
            begin
                ch:=((klawisz)and($FF))-Ord('0');
                if (0<=ch)and(ch<=9) then
                begin
                  tablica[i]:=ch;
                  al_textout_ex(AL_SCREEN, al_font, '0', 300+7*i, 200, red, black);
                  Inc(i);
                end;
            end;
        end;
    until klawisz=17165; //jak wcisniemy enter, to petla sie zakonczy
    x:=String2Real(tablica, i-1);
end;

Teraz procedura wygląda o wiele lepiej, ale niestety nie działa dobrze ponieważ cały czas wypisuje zero na ekranie:

al_textout_ex(AL_SCREEN, al_font, '0', 300+7*i, 200, red, black);

Procedura al_textout_ex wyświetla na ekranie tylko stringi, dlatego próbowałem na początku zadeklarować sobie tablicę stringów przechowującą cyfry (oraz - i .) i napisać tak:

 al_textout_ex(AL_SCREEN, al_font, tablica[i], 300+7*i, 200, red, black);

, ale to nie działa i nie wiem dlaczego.

Wiecie co, zauwazyłem, że jeżeli zamiast

if i=3 then //zmiana promienia Slonca
begin
    KeysOff;
    WriteMenu(1);
    WriteMenu(i);
    while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) and (al_key[AL_KEY_ENTER]=0) do;
    if al_key[AL_KEY_ENTER]<>0 then //gdy zostanie wcisniety klawisz enter
        ReadNumber(promien);
end;

Mam:

if i=3 then //zmiana promienia Slonca
begin
    KeysOff;
    WriteMenu(1);
    WriteMenu(i);
    while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) and (al_key[AL_KEY_ENTER]=0) do;
    ReadNumber(promien);
end;

Tzn, gdy procedura ReadNumber nie czeka na wciśnięcie klawisza enter, to działa prawidłowo! Tzn wyświetla mi na bieżąco cyfry które wpisuję. I nie wiem dlaczego. Tylko, że wtedy menu nie działa prawidłowo.

0

Może przerób to menu wg tego: http://4programmers.net/Forum/1100492

0

Dziwne, bardzo dziwne, procedura zaczęła działać, gdy umieściłem ją w pętli while:

 
if i=3 then //zmiana promienia Slonca
begin
    KeysOff;
    WriteMenu(i);
    while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) and (al_key[AL_KEY_ENTER]=0) do;
    if al_key[AL_KEY_ENTER]<>0 then //gdy zostanie wcisniety klawisz enter
    begin
        al_key[AL_KEY_ENTER]:=0; //wylaczam enter
	while al_key[AL_KEY_ENTER]=0 do 
	    ReadNumber(promien);
    end;
end;

Teraz program wyświetla mi na bieżąco wpisywane cyfry, a potem wraca do menu głównego. Sprawdziłem, czy też dobrze zapamiętuje wpisaną liczbę i dodałem do definicji procedury ReadNumber linijkę:

writeln('Wprowadziels liczbe: ',x:0:4);

tak aby wypisał mi w konsoli wprowadzoną liczbę. I program przy każdym uruchomieniu wypisuje mi w konsoli 2 RAZY:

Wprowadziles liczbę: 1.0000
Wprowadziles liczbe: xxx
. xxx to jest ta liczba, którą mu wpisuję, ale przed nią zawsze wyświetla mi 1. Nie wiem dlaczego. To wygląda tak jak by procedura ReadNumber(promien) wykonywala się dwa razy, przy czym za pierwszym razem wczytuje promien nie wiadomo skąd.

0

Przerobiłem program. Dalej nie działa prawidłowo, ale jest zapisany dużo czytelniej. Może teraz będziecie mi wstanie pomóc.

Oto część zasadnicza programu:

begin
	clrscr;
	inicjalizuj;
	i:=1; 
	while (i<>5) or (al_key[AL_KEY_ENTER]=0) do //program ma sie zakonczyc, gdy (i=5) and (al_key[AL_KEY_ENTER]<>0) w while musi byc warunek dzialania, a wiec nalezy tu wstawic zaprzeczenie tego wyrazenia
	begin
		while i=1 do //opcja START bedzie podswietlona dopoki i bedzie rowne 1
		begin 
			KeysOff;
			WriteMenu(i);
			while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) do; //czeka w pustej petli na wcisniecie DOWN, albo UP 
			Liczi(i); //Obliczam nowe i za pomocą specjalnej procedury
		end;
			
		while i=2 do //zmiana predkosci Ziemi
		begin
			KeysOff;
			WriteMenu(i);
			while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) do;
			Liczi(i);
		end;
		while i=3 do //zmiana promienia Slonca
		begin
			KeysOff;
			WriteMenu(i);
			while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) and (al_key[AL_KEY_ENTER]=0) do;
			if al_key[AL_KEY_ENTER]=0 then //gdy enter nie zostanie wcisniety to zwiekszam lub zmniejszam i  
				Liczi(i);
			if al_key[AL_KEY_ENTER]<>0 then //gdy enter zostanie wcisniety 
				ReadNumber(promien);
		end;
		while i=4 do //zmiana masy Jowisza
		begin
			KeysOff;
			WriteMenu(i);
			while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_UP]=0) do;
			Liczi(i);
		end;
			
			//wylaczenie programu
		while (i=5) and (al_key[AL_KEY_ENTER]=0) do //to po to aby program sie zakonczyl po wybraniu opcji Zakoncz
		begin
			KeysOff;
			WriteMenu(i);
			while (al_key[AL_KEY_DOWN]=0) and (al_key[AL_KEY_ENTER]=0) and (al_key[AL_KEY_UP]=0) do; //tu czekna na nacisniecie klawisza down, up, albo enter
			if al_key[AL_KEY_ENTER]=0 then //tzn gdy enter NIE zostanie wcisniety to normalnie zwiekszam, lub zmniejszam i 
				Liczi(i);
		end;
	end;
	al_exit;
end.

Do skakania po tych różnych opcjach (czyli while'ach) wykorzystuję i, które zmieniam oddzielną procedurą:

procedure LiczI(var i: integer);
begin	
	if al_key[AL_KEY_DOWN]<>0 then //gdy wcisniety zostanie klawisz DOWN
		if i>4 then //jezeli i>4 to procedura zamiast je zwiekszyc to przypisuje mu wartosc rowna 1 
			i:=1 
		else 
			i:=i+1; //w przeciwnym wypadku zwieksza i o 1
	if al_key[AL_KEY_UP]<>0 then //gdy wcisniety zostanie klawisz UP
		if i<2 then //jezeli i jest mniejsze od 2 to zamiast je zmniejszyc przypisuje mu wartosc 5
			i:=5
		else
			i:=i-1; //w przeciwnym razie zmniejsza i o 1
end;

Program po wybraniu opcji "Zmien promien Slonca" powinien uruchomić procedurę ReadNumber(promien) i zacząć czytywać promień jednocześnie wyświetlając go na ekranie, ale tego nie robi. Zamiast tego nic się nie dzieje. Dalej wyświetla mi sie główne menu, ale w konsoli wypisuje mi się wartość promienia równa 1.0000. Procedurę ReadNumber mam taką jaką mi pomógł napisać Dragon:

procedure ReadNumber(var x: real); //procedura analogiczna do readln, ktora wczytuje liczbe rzeczywista w trybie graficznym

var  
	i, klawisz: integer;
	tablica: array[1..100] of integer;
	ch: byte;
	
begin
    KeysOff;
    al_clear_to_color(AL_SCREEN, black);
    al_textout_ex(AL_SCREEN, al_font, 'Podaj liczbe: ', 200, 200, red, black);
    i:=1; 
    repeat 
        klawisz:=al_readkey;
        case klawisz of
            18734: //gdy zostanie wcisnieta kropka
            begin
                tablica[i]:=46; //kod kropki w ASCII
                al_textout_ex(AL_SCREEN, al_font, '.', 300+7*i, 200, red, black);
                i:=i+1;
            end;
            15661: //gdy zostanie wcisniety znak minus
            begin
                tablica[i]:=45;
                al_textout_ex(AL_SCREEN, al_font, '-', 300+7*i, 200, red, black);
                i:=i+1;
            end;
            16136: //gdy wcisniety zostanie back space
            begin
                i:=i-1; //cofamy sie o jeden
                al_textout_ex(AL_SCREEN, al_font, ' ', 300+7*i, 200, black, black); //zamazuje niechciana cyfre
            end;
            else
            begin
                ch:=((klawisz)and($FF))-Ord('0');
                if (0<=ch)and(ch<=9) then
                begin
                  tablica[i]:=ch;
                  al_textout_ex(AL_SCREEN, al_font, Chr(Ord('0')+ch), 300+7*i, 200, red, black); 
                  Inc(i);
                end;
            end;
        end;
    until klawisz=17165; //jak wcisniemy enter, to petla sie zakonczy
    x:=String2Real(tablica, i-1);
	writeln('Wprowadziles liczbe: ',x:0:4);
end;
0

Wiecie co napisałem tę procedurę wczytującą jeszcze raz, bezpośrednio w kodzie programu i teraz jest OK. Pisząc, sprawdzałem na bieżąco, czy wszystko działa prawidłowo i doszedłem do wniosku, że prawdopodobnie to al_readkey w połączeniu z al_key[ ] powodowało błędy. Tak samo nie należy używać writeln w trybie graficznym, bo dzieją się dziwne rzeczy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1