Menu programu w trybie graficznym - nie wyswietla sie prawidlowo

Odpowiedz Nowy wątek
2015-01-17 23:40
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?

edytowany 1x, ostatnio: PLrc, 2015-01-17 23:43

Pozostało 580 znaków

2015-01-18 01:50
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? :|


edytowany 4x, ostatnio: Patryk27, 2015-01-18 01:53
Spóźniłem nieco... ;) - furious programming 2015-01-18 01:56

Pozostało 580 znaków

2015-01-18 01:56
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...


edytowany 1x, ostatnio: furious programming, 2015-01-18 01:56

Pozostało 580 znaków

2015-01-18 06:32

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;

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 2x, ostatnio: _13th_Dragon, 2015-01-18 06:34

Pozostało 580 znaków

2015-01-18 15:17
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.

edytowany 4x, ostatnio: PLrc, 2015-01-18 15:37
al_textout_ex(AL_SCREEN, al_font, '0'+ch, 300+7*i, 200, red, black); - _13th_Dragon 2015-01-18 15:41
al_textout_ex(AL_SCREEN, al_font, (char)('0'+ch), 300+7*i, 200, red, black); - _13th_Dragon 2015-01-18 15:42
Napisałem w procedurze: al_textout_ex(AL_SCREEN, al_font, (char)('0'+ch), 300+7*i, 200, red, black); i wyświetla mi błąd w tej linijce: <quote>Fatal: Syntax error, ")" expected, but "(" found.</quote> - PLrc 2015-01-18 16:01
Heh, pomyliło mi się z C: al_textout_ex(AL_SCREEN, al_font, Chr(Ord('0')+ch), 300+7*i, 200, red, black); - _13th_Dragon 2015-01-18 16:08
Działa :D Faktycznie znam taką funkcję jak chr, ale myślałem że ona nie będzie działać, ponieważ zwraca char. Daję plusa. - PLrc 2015-01-18 16:14

Pozostało 580 znaków

2015-01-18 15:42
0

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


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Pozostało 580 znaków

2015-01-18 17:30
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.

edytowany 1x, ostatnio: PLrc, 2015-01-18 17:31

Pozostało 580 znaków

2015-01-18 20:31
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;
edytowany 1x, ostatnio: PLrc, 2015-01-18 20:38

Pozostało 580 znaków

2015-01-19 00:15
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.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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