Strony

piątek, 3 października 2014

Zabawy matematyczne w Delphi cz 1

Policz, ile to jest - wersja prosta


     Rozdział poświęcony grom i zabawom wykonanych w środowisku Delphi otwieramy, chyba najprostszym przykładem z możliwych (z punktu widzenia programistycznego), zabawą matematyczną polegającą na odgadnięciu poprawnego wyniku działania na dwóch liczbach.


Założenia i opis zabawy:

     Po naciśnięciu przycisku START program wybierze dla nas jakieś działanie matematyczne z użyciem dwóch liczb, wyświetli je i poprosi o podanie właściwego wyniku. Ponieważ zależy nam na rozwijaniu swego umysłu, wszystkie obliczenia wykonujemy w pamięci. Z uwagi na ten wymóg ograniczymy zakres używanych liczb do dwudziestu: program będzie wybierał liczby tylko z zakresu od 0 do 20. Oczywiście, programista może sobie ustalić ten zakres w sposób zupełnie indywidualny.

     Kolejnym ograniczeniem jakiego dokonamy, będzie wyeliminowanie z używanych działań, dzielenia. W ten sposób nie będziemy musieli obliczać w pamięci liczb ułamkowych. Trudno przecież w pamięci policzyć, ile to jest 19 podzielić przez 7. Nasz program będzie obsługiwał tylko dodawanie, odejmowanie i mnożenie.

     Po obliczeniu w pamięci wyniku, wpisujemy go w pole edycyjne programu i naciskamy przycisk Sprawdź. Program sprawdza poprawność wyniku i wyświetla odpowiedni komunikat informacyjny, czy dobrze, czy źle. Jeżeli odpowiedź jest poprawna, działanie jest usuwane z panelu programu. Inna sytuacja ma miejsce w przypadku podania niepoprawnej odpowiedzi. Działanie do policzenia nie znika, usuwany jest tylko podany przez nas wynik. W ten sposób możemy spróbować swoich sił jeszcze raz, a gdy się znowu nie uda, jeszcze raz i jeszcze raz. Decyzja będzie zależała od nas. Jeżeli będziemy chcieli zrezygnować z tego działania, wystarczy że naciśniemy przycisk START, a wymieni nam działanie na inne.

     Wprowadzamy do programu także tabelę wyników, która będzie pokazywała, ile do tej pory udzieliliśmy odpowiedzi poprawnych, a ile niepoprawnych. Przy zamykaniu programu, pojawi się także komunikat, w którym w zależności od uzyskanych wyników, program nam pogratuluje lub zachęci do większego zaangażowania.

     Jako rozszerzenie możliwości programu zadbamy o to, aby program informował nas, gdy nieopacznie naciśniemy przycisk Sprawdź bez wpisania wyniku w polu edycyjnym, oraz aby umożliwiał wpisywanie w tym polu tylko liczb, minusa (bo wyniki będą czasami liczbami ujemnymi), oraz pozwalał na używanie klawisza Backpace do kasowania wprowadzanych znaków w przypadku pomyłki.


Użyte komponenty:


Edit1- pole edycyjne do wpisywania odpowiedzi,
Button1- przycisk START,
Button2- przycisk Sprawdź,
Label1- wyświetla napis „Wyniki”,
Label2- wyświetla napis „Poprawne:”,
Label3- wyświetla napis „Niepoprawne:”,
Label4- wyświetla ilość poprawnych odpowiedzi,
Label5- wyświetla ilość niepoprawnych odpowiedzi,
Label6- wyświetla działanie do policzenia.

     Powyższe komponenty wstawiamy na formę i układamy względem siebie tak, jak na rysunku poniżej:

Delphi
Interfejs programu

      Należy zwrócić uwagę, że numery komponentów lub formy głównej (TForm) mogą się w Waszych projektach różnić. Należy więc poszczególny kod przypisać do właściwych komponentów i nadać im właściwe nazwy. W naszym projekcie modyfikujemy nazwy poszczególnym komponentom w następujący sposób (właściwość Caption w Inspektorze Obiektów):

                                Komponent   nazwa

Edit1       (usuwamy nazwę)
Button1    START
Button2    Sprawdź
Label1     Wyniki
Label2     Poprawne:
Label3     Niepoprawne:
Label4     0 (zero)
Label5     0 (zero)
Label6     Ile to jest:

     W dalszej kolejności, także za pomocą Inspektora Obiektów zmieniamy inne właściwości tych komponentów, a więc: kolor, rozmiar, położenie itp.


Kod programu:


unit Unit1;



interface



uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;



type

TForm1 = class(TForm)

Edit1: TEdit;

Button1: TButton;

Button2: TButton;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

Label5: TLabel;

Label6: TLabel;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Edit1KeyPress(Sender: TObject; var Key: Char);

procedure FormCreate(Sender: TObject);

procedure FormClose(Sender: TObject; var Action: TcloseAction);



private

{ Private declarations }

public

{ Public declarations }

end;



var

   Form1: TForm1;

   WYNIK: Integer;          //zmienna przechowująca wynik działania

   Poprawne: Integer;      //zmienna przechowująca ilość poprawnych odpowiedzi

   Niepoprawne: Integer;  //zmienna przechowująca ilość niepoprawnych odpowiedzi



implementation



{$R *.dfm}


                  //przy uruchomieniu programu wyzeruj punktację
 

procedure TForm1.FormCreate(Sender: TObject);

   begin

     Poprawne:=0;             //wyzeruj ilość poprawnych odpowiedzi

     Niepoprawne:=0;         //wyzeruj ilość niepoprawnych odpowiedzi

     Label4.Caption:= '0';    //wyświetl '0' poprawnych odpowiedzi

     Label5.Caption:= '0';    //wyświetl '0' niepoprawnych odpowiedzi

   end;






                 //przy zamykaniu programu oceń uzyskane wyniki


procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

   begin

     if (Poprawne<Niepoprawne) or (Poprawne=Niepoprawne) then

       begin

          ShowMessage('Musisz jeszcze trochę potrenować');

       end

        else

           ShowMessage('Gratuluję! Uzyskałeś dobry wynik');

   end;







            //pozwól na wpisywanie tylko liczb, minusa i Backpace w polu odpowiedzi


procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);

   begin

     if not (Key in ['0'..'9',#45,#8]) then

       begin

         Key:=#0;

         ShowMessage('To nie jest liczba');       //wyświetl komunikat o błędzie

       end;

   end;






           //gdy naciśniesz przycisk START


procedure TForm1.Button1Click(Sender: TObject);

  var

    Liczba1: Integer;           //zmienna przechowująca pierwszą liczbę

    Liczba2: Integer;           //zmienna przechowująca drugą liczbę

    Dzialanie: Integer;         //zmienna pomocnicza do losowania znaku działania

    Znak: String;               //zmienna przechowująca znak działania



begin

   Edit1.Clear;                         //wyczyść pole edycyjne (Do podawania Odpowiedzi)

   Randomize;                         //uruchom maszynę losującą

   Liczba1:=Random(21);          //losuj pierwszą liczbę

   Liczba2:=Random(21);          //losuj drugą liczbę

   Dzialanie:=Random(3);          //losuj znak działania matematycznego

case Dzialanie of                           //gdy zostanie wylosowana dana liczba to...

   0: WYNIK:= Liczba1+Liczba2;      //...wykonaj dodawanie

   1: WYNIK:= Liczba1-Liczba2;       //...wykonaj odejmowanie

   2: WYNIK:= Liczba1*Liczba2;       //...wykonaj mnożenie

end;


if Dzialanie=0 then

    Znak:= '+';                     //jeżeli wylosowano dodawanie to pokaż znak '+'

if Dzialanie=1 then

    Znak:= '-';                     //jeżeli wylosowano odejmowanie to pokaż znak '-'

if Dzialanie=2 then

    Znak:= 'x';                    //jeżeli wylosowano mnożenie to pokaż znak 'x'


    Label6.Caption:=('Ile jest: ' + IntToStr(Liczba1) + ' ' + znak + ' ' +IntToStr(Liczba2) + ' ?');                                  //wyświetl działanie



Edit1.SetFocus;              //ustaw focus w Polu do Odpowiedzi



end;






                   //gdy naciśniesz przycisk Sprawdź


procedure TForm1.Button2Click(Sender: TObject);

  Label KONIEC;          //Etykieta do przechodzenia w inne miejsca kodu

  var

    Odp: String;             //zmienna przechowująca naszą odpowiedź



begin

   Odp:= Edit1.Text;       //odczytaj podana odpowiedz i przypisz ja do zmiennej


     if Odp='' then           //gdy nie podano odpowiedzi monituj o wpisaniu wyniku

       begin

          ShowMessage('Wpisz najpierw wynik');    //wyświetl komunikat informujący

          Edit1.SetFocus;                                     //ustaw focus w Polu do Odpowiedzi

         goto KONIEC;       //pomiń poniższy kod i przejdź od razu na koniec procedury

end;



if Odp=(IntToStr(WYNIK)) then              //jeżeli odpowiedź jest poprawna to ...

   begin

      ShowMessage('Bardzo dobrze!');       //wyświetl komunikat o poprawnej odpowiedzi

      Label6.Caption:= 'Ile jest: ';                //wyczyść działanie

       Poprawne:=Poprawne + 1;                //dodaj punkt do poprawnych odpowiedzi

end                                                      //bez średnika



   else                                                   //w przeciwnym wypadku ...



      begin

         ShowMessage('Niestety źle');              //wyświetl komunikat o złej odpowiedzi

         Niepoprawne:=Niepoprawne + 1;          //dodaj punkt do niepoprawnych odpowiedzi

      end;



Edit1.Clear;                       //wyczyść pole do podawania Odpowiedzi)

Edit1.SetFocus;                 //ustaw focus w Polu do Odpowiedzi



Label4.Caption:= IntToStr(Poprawne);         //wyświetl ilość poprawnych odpowiedzi

Label5.Caption:= IntToStr(Niepoprawne);     //wyświetl ilość niepoprawnych odpowiedzi



KONIEC:           //etykieta do której przechodzi kod, gdy ktoś nie wpisze żadnej liczby

end;

end.


Strona    1/3    Dalej >

Artykuł pochodzi z mojej książki pt. "Delphi w przykładach dla początkujących". Zapraszam na Stronę książki.

poradnik programowania Delphi


3 komentarze:

  1. Dzień dobry
    Zakupiłem Pańską książkę, rozpoczynając samodzielną naukę programowania w Delphi, natknąłem się jednak na problem w drugim zadaniu, a więc policz ile to jest - wersja trudniejsza, zaproponowany przez Pana kod o ile się nie mylę, zlicza działanie nie-matematycznie, tzn po kolei, bez uwzględnienia kolejności wykonywania działań, ponieważ jestem kompletnie początkujący, nie bardzo wiem jak to poprawić, pisanie sekwencji dla każdej możliwości wylosowania znaku działań to zbyt mozolne, a w programowaniu chyba nie o to chodzi, czy jest jakiś sposób na odczytanie zapisu działania w string'u i przekonwertowanie tego wprost do działania matematycznego?
    pozdrawiam
    Krzysztof Krajniak

    OdpowiedzUsuń
    Odpowiedzi
    1. Ta "niematematyczność" działań, o której Pan wspomina, wynika z przyjętego założenia, że wersja ta w domyśle, jest punktem wyjścia dla wersji audio, gdzie program słownie podaje kolejne działania do wykonania w pamięci. W książce posłużyłem się wersją prostą zabawy, aby ułatwić zrozumienie kodu.

      Sposobów na uzyskanie "matematyczności" zabawy, czyli najpierw wykonanie mnożenia, a potem dodawania i odejmowania, jest kilka. Jako początkujący programista musi Pan właśnie nauczyć się analizować algorytmy wykorzystane w kodzie i - w razie czego - szukać alternatywy.

      Analizując kod zabawy widzi Pan, że algorytm, jaki wykorzystałem, realizuje dokładnie moje zamierzenie tj. zliczanie kolejnych poddziałań wg kolejności pojawienia się. Chcąc zatem uzyskać inny efekt, wystarczy najpierw wylosować wszystkie typy działań (dodawanie, odejmowanie, mnożenie), jakie zostaną w danym działaniu użyte, a następnie wprowadzić warunek, że działanie wylosowane, jako "mnożenie" program ma wykonać jako pierwsze. Nie możemy zatem w tak prosty sposób stosować zmienną WYNIK, jak ma to miejsce w kodzie zabawy.

      Ogólna koncepcja właściwego algorytmu może być następująca:

      1. wylosuj liczby, które będą wykorzystane w działaniu (w naszej zabawie będzie ich cztery) i zapisz je do osobnych zmiennych (Liczba 1...Liczba4)

      2. wylosuj wszystkie znaki działania wykorzystane w tym działaniu (będzie ich trzy) i zapisz je do osobnych zmiennych (znak1...znak3)

      3. warunek nr 1: jeśli któryś ze znaków jest mnożeniem, wtedy zmienne LiczbaX i LiczbaY (liczby wylosowane dla danego podzdziałania) pomnóż i zapisz do zmiennej "M", a następnie wykonaj całe działanie stosując zmienną "M", zamiast mnożenia dwóch liczb (czyli zamiast działania "Liczba1 + Liczba2 * Liczba 3 - Liczba4", będzie Liczba1 + M - Liczba4"), w przeciwnym razie (tzn jeśli nie ma mnożenia) zastosuj algorytm z przykładu w książce. (Ponieważ mogą wystąpić dwa znaki mnożenia, należy wprowadzić zmienną N, która zapisze wynik mnożenia kolejnych dwóch liczb, może to być nawet zmienna M, np: Liczba1 + Liczba2 * M. Otrzymamy wtedy działanie końcowe: Liczba1 + N)

      4. warunek nr 2: jeśli wszystkie trzy znaki to "mnożenie", wtedy zastosuj algorytm z przykładu w książce (bo kolejność działań będzie szła od lewej do prawej).

      Nie podaję gotowego kodu, bo w ten sposób niewiele się Pan nauczy. Tylko "kombinując" na różne sposoby, wyrobi Pan w sobie umiejętność budowania algorytmów potrzebnych w Pańskich projektach. Na tym właśnie polega nauka programowania :)

      Jeśli chodzi o mozolne pisanie warunków, to niestety jest to coś naturalnego w programowaniu. Proszę spojrzeć sobie no kod gry "HotSpot" lub programu "Jak się masz". Zadaniem programisty w takich przypadka jest tylko próba ułatwienia sobie zadania i odchudzenie kodu, stosując procedury, funkcje i inne wynalazki.

      Usuń
    2. Ja bym zaczął od najprostszej logicznie metody, czyli kodu typu: (Liczba1)(Znak1)(Liczba2)(Znak2)(Liczba3)(Znak3)(Liczba4), zakładając, że komputer jest na tyle mądry, że wykona działanie wg praw matematyki, ale to trzeba by sprawdzić.

      Usuń