start     Articole     Despre mine     Contact     Cursul ABCprog    

Cum desenezi tabla de sah prin programare

Exercitiul din mini-ghidul meu de introducere in programare care a dat nastere la cele mai multe intrebari este cel in care ti se cere sa “desenezi” o tabla de sah (de 10×10 patratele).

Despre lectia asta vorbesc.

Am observat ca a provocat multe intrebari, asa ca am facut aici un “joculet” care iti arata cum functioneaza un while atunci cand e pus in interiorul unui alt while.

Vazand ca intrebarile legate de problema construirii “tablei de sah” pe ecranul de 10×10 puncte din simulator continua, am decis sa adun aici o parte din explicatiile pe care le-am dat celor care mi-au scris.

Cum suna problema

Problema era asa:

(1) Iti dadeam un mic program care aprindea toate cele 10×10 puncte ale ecranului virtual.

E vorba de un clasic while intr-un while, de genul urmator:

var y;
var x;
y = 1;
while (y <= 10)
{
       x = 1;
       while (x <= 10)
       {
              Aprinde(x, y);
              x = x+1;
       }
       y = y+1;
}

(2) Apoi te intrebam daca ai putea sa il modifici astfel incat sa nu-ti aprinda toate punctele, ci sa “deseneze” un soi de “tabla de sah” formata din 10×10 patratele. (Si iti dadeam ca indiciu sa folosesti if-uri, eventual unele in interiorul altora.)

Si cum ai putea gasi solutia

OK, hai sa vedem cum ai putea aborda aceasta problema!

Hai sa pornim de la a observa ca programul de la punctul (1) de mai sus este, de fapt, urmatorul:

    pentru fiecare linie din ecran, y, de la 1 pana la 10
    {
        pentru fiecare coloana din ecran, x, de la 1 pana la 10
        {
            aprinde punctul de pe coloana x si linia y, adica punctul (x, y)
        }
    }

Esti de acord ca e vorba de acelasi program — doar ca aici l-am scris in cuvinte (si nu in limbajul de programare pe care il intelege simulatorul)? (Se cheama ca l-am scris in “pseudocod” — adica intr-un fel de limbaj de programare foarte intuitiv, fara reguli stricte.)

Daca da, hai sa mergem mai departe!

Ce face programul pana aici

Pana aici, programul iti parcurge punctele (x, y) de pe ecranul virtual in ordinea: (1, 1), (2, 1), (3, 1), …,, (10, 1), (1, 2), (2, 2), (3, 2), …, (10, 2), …, (1, 10), (2, 10), (3, 10), …, (10, 10).

Si, pentru fiecare punct (x, y) in parte, iti “aprinde” (colorandu-l cu negru) acel patratel de pe ecranul virtual.

Dar, ca sa faci tabla de sah, nu trebuie sa aprinzi toate punctele, ci doar jumatate dintre ele.

Ce puncte aprinzi pe linia 1

Daca alegi sa incepi prin a aprinde punctul (1, 1), inseamna ca urmatorul punct aprins va fi (3, 1). Apoi: (5, 1), (7, 1) si (9, 1).

Adica pe linia 1 trebuie sa aprinzi toate punctele de pe coloane impare.
Sau, altfel spus, punctul (x, 1) trebuie sa il aprinzi doar daca x este impar.

Cum ai zice asta intr-un program?…

daca x este impar
{
    Aprinde(x, 1)
}

Cum verifici daca valoarea din variabila x este impara?
Bineinteles, poti calcula restul impartirii ei la 2, dupa care verifici daca rezultatul acestei operatii este egal cu 1.

if ( (x%2) == 1)
{
    Aprinde(x, y);
}

Pentru linia 1 e in regula. Adica:

daca y este egal cu 1
    ... // fa lucrurile pe care le-am zis mai sus

Dar pentru linia 2, ce faci?…

Ce puncte aprinzi pe liniile impare

Vorbim imediat despre linia 2, dar hai sa observam, mai intai, ca pentru linia 3 e la fel ca pentru linia 1 — adica trebuie sa aprinzi toate punctele de pe coloane impare.

Adica, pana aici am avea asa:

if ( y == 1 )
{
    if ( (x%2) == 1)
    {
        Aprinde(x, y);
    }
}

if ( y == 3 )
{
    if ( (x%2) == 1)
    {
        Aprinde(x, y);
    }
}

Dar si pentru y egal cu 5 (sau 7, sau 9) va trebui sa faci la fel.
N-ar fi fost mai simplu sa zici asa?:

daca y este impar
    daca x este impar
        aprinde punctul (x, y)

Bineinteles ca da. Si cred ca iti e clar ca ceea ce am scris in pseudocod aici s-ar putea traduce asa intr-un program pe care il poti rula in simulatorul de pe site:

if ( (y%2) == 1 )
{
    if ( (x%2) == 1)
    {
        Aprinde(x, y);
    }
}

Pardon, ca sa il poti rula in simulator mai trebuie ceva.
Te-ai prins ca “bucatica” asta de program trebuie, de fapt, sa o pui in interiorul celui de-al doilea while din programul de la (1), nu-i asa?

Eu cred ca te-ai prins, dar hai sa iti scriu aici tot programul rezultat pana acum — ca sa nu fie niciun dubiu:

var y;
var x;
y = 1;
while (y <= 10)
{
        x = 1;
        while (x <= 10)
        {
            //---------------------
            if ( (y%2) == 1 )
            {
                if ( (x%2) == 1)
                {
                    Aprinde(x, y);
                }
            }
            //---------------------
            x = x+1;
        }
        y = y+1;
}

Am pus si comentariile acelea care separa foarte clar (nu-i asa?) zona din program unde am facut “insertia”.

Bun — ce face programul asta?

Daca l-ai pus in simulator si ai apasat butonul “Executa…”, ai vazut ca deja ai rezolvat problema pe jumatate.

Adica ai aprins doar jumate dintre punctele negre ale tablei de sah.
Mai precis, ai aprins doar punctele negre de pe liniile impare.

Iti reamintesc ca programul de pana aici arata cam asa in pseudocod:

pentru fiecare linie, y, de la 1 pana la 10
{
    pentru fiecare coloana, x, de la 1 pana la 10
    {
        daca y este impar
        {
            daca x este impar
            {
                Aprinde(x, y)
            }
        }
    }
}

Ce facem pe liniile pare

Ce-ar fi sa punem la “daca y este impar {…}” un “altfel”?…

Adica sa facem ceva si pentru cazul in care y este par.

Si ce ar trebui sa facem in acel caz?

E simplu acum, nu-i asa?

Daca pe liniile impare ai aprins punctele de pe coloanele impare, pe liniile pare trebuie sa aprinzi punctele de pe coloanele pare, adica:

        ....
        else   // adica "altfel"-ul de la "daca y este impar"
        {
            daca x este par
            {
                Aprinde(x, y)
            }
        }
        ....

Si cum testezi daca x este par? Evident, cu if ( (x%2) == 0 ).

Programul obtinut

Ia uite programul:

var y;
var x;
y = 1;
while (y <= 10)
{
        x = 1;
        while (x <= 10)
        {
            //---------------------
            if ( (y%2) == 1 )
            {
                if ( (x%2) == 1)
                {
                    Aprinde(x, y);
                }
            }
            else
            {
                if ( (x%2) == 0)
                {
                    Aprinde(x, y);
                }
            }
            //---------------------
            x = x+1;
        }
        y = y+1;
}

Frumos, nu? 🙂

Dar ar fi fost si mai frumos daca observam ca partea de testari conditii din interiorul celor doua while-uri o puteam face si asa:

daca x si y au aceeasi paritate (adica fie ambele pare, fie ambele impare)
{
    Aprinde(x, y)
}

Asta nu ti-o mai zic cum se face, ci iti dau doar ca indiciu intrebarea: “Cum depinde paritatea sumei x+y de paritatile celor doua variabile?” 😀

In concluzie

Nu te descuraja daca n-ai reusit sa rezolvi singur(a) problema cu “tabla de sah”. Asta e una dintre cele mai frecvent intalnite dificultati de cei care se apuca de invatat programare.

Creierul omului nu este obisnuit sa “alerge dupa doi iepuri”. (Adica dupa doua variabile, y si x, care mai si “alearga” fiecare cu viteza ei.)

Si nu ii e usor nici sa “citeasca” expresii cu multe “paranteze” in “paranteze” (sau cu if-uri in if-uri in while-uri din while-uri).

Dar treburile astea se antreneaza. Nu zic ca e neaparat usor, dar nici extraordinar de greu.

Cel mai greu e sa dai “sonorul” incet la gandurile care incep sa iti spuna ca “programarea nu e de tine; lasa-te”. Si apoi sa ai rabdare sa studiezi cu atentie exemplele de programe pe care ti le-am dat si sa le “executi” cu pixul pe hartie.

Chiar daca ti se pare ca pierzi prea mult timp cu treaba asta, sa stii ca in aceste momente, in timp ce iti fortezi creierul sa inteleaga aceste lucruri, incepe sa se formeze in tine o gandire de programator.

 

Alatura-te celor peste 8000 de oameni din armata noastra de creiere cu muschi si vei primi testul care iti va spune daca ai sau nu minte de programator.

In plus, vei fi mereu la curent cu tot ce pun la cale.

(Vei primi automat un email in care ti se va solicita acordul de prelucrare a datelor cu caracter personal.)

 

Cu drag,

Florin Bîrleanu





Loading Facebook Comments ...