Da WIKI CoderDojo Firenze.
m (Corretto errore logico della condizione while che consentiva di prendere 5 fiammiferi)
 
(10 versioni intermedie di uno stesso utente non sono mostrate )
Riga 1: Riga 1:
 
= Tutorial C++ con le librerie Qt – Parte II =
 
= Tutorial C++ con le librerie Qt – Parte II =
 +
 
== Come superare gli schieramenti ==
 
== Come superare gli schieramenti ==
 +
 
=== Se uno ha troppi amici… ===
 
=== Se uno ha troppi amici… ===
 +
 
Ripartiamo da dov’eravamo rimasti.
 
Ripartiamo da dov’eravamo rimasti.
  
Riga 7: Riga 10:
  
 
Nella funzione ''salutaUtente'':
 
Nella funzione ''salutaUtente'':
 
 
<pre>segnale_di_ritorno = -1;</pre>
 
<pre>segnale_di_ritorno = -1;</pre>
 
 
Nella funzione interrogaUtente:
 
Nella funzione interrogaUtente:
 
 
<pre>if ( verifica == -1 ) {</pre>
 
<pre>if ( verifica == -1 ) {</pre>
 
 
A parte le varie parentesi, tonda e graffa, ci vedete qualche differenza?
 
A parte le varie parentesi, tonda e graffa, ci vedete qualche differenza?
  
Riga 20: Riga 19:
 
Visto che esiste l’equivalente in JavaScript (e anche in C, tanto per cambiare), adesso vedremo cosa significa in quel linguaggio. Però diamo prima un’occhiata a questo codice Scratch, che ci aprirà un po’ la strada:
 
Visto che esiste l’equivalente in JavaScript (e anche in C, tanto per cambiare), adesso vedremo cosa significa in quel linguaggio. Però diamo prima un’occhiata a questo codice Scratch, che ci aprirà un po’ la strada:
  
 
+
<br/>[[File:C++ Qt 02 Scratch 01.png|C++ con Qt, parte II, Scratch 01]]
[[File:C++_Qt_02_Scratch_01.png|C++ con Qt, parte II, Scratch 01]]
+
  
 
Okay, apparentemente non c’entra nulla, ma ci serve un po’ di pazienza.
 
Okay, apparentemente non c’entra nulla, ma ci serve un po’ di pazienza.
Riga 29: Riga 27:
 
Proviamo a esprimere a parole le istruzioni di questo programma, proprio come se stessimo parlando a un robottino e gli dovessimo spiegare passo passo cosa fare:
 
Proviamo a esprimere a parole le istruzioni di questo programma, proprio come se stessimo parlando a un robottino e gli dovessimo spiegare passo passo cosa fare:
  
«Quando faccio click, tu (robottino) memorizza questi due dati: Mario e Maria in due celle di memoria, amico1 e amico2; poi chiedi a chi si avvicina: “Come ti chiami?”. Dopo procedi così:
+
Quando faccio click, tu (robottino) memorizza questi due dati: Mario e Maria in due celle di memoria, amico1 e amico2; poi chiedi a chi si avvicina: “Come ti chiami?”. Dopo procedi così:
  
* se la risposta che ti hanno dato è uguale a quello che hai scritto nella variabile amico1, allora saluta;
+
*se la risposta che ti hanno dato è uguale a quello che hai scritto nella variabile amico1, allora saluta;
* altrimenti (quindi, se la risposta non è uguale a quello che è scritto in amico1), confronta la risposta con quello che è scritto in amico2; se stavolta è uguale, saluta;
+
*altrimenti (quindi, se la risposta non è uguale a quello che è scritto in amico1), confronta la risposta con quello che è scritto in amico2; se stavolta è uguale, saluta;
* altrimenti, digli che non lo conosci.
+
*altrimenti, digli che non lo conosci.
  
Wow! Faticoso, non è vero? Mi accorgo ora che ho messo un’istruzione di troppo: l’istruzione ''porta nome a risposta'' si può tranquillamente ignorare. Ma, a parte quella, direi che la vita del robottino è un po’ complicata.
+
<br/>Wow! Faticoso, non è vero? Mi accorgo ora che ho messo un’istruzione di troppo: l’istruzione ''porta nome a risposta'' si può tranquillamente ignorare. Ma, a parte quella, direi che la vita del robottino è un po’ complicata.
  
 
Pensate un po’ se voleste istruirlo a riconoscere 4 amici, anziché 2. Guardate un po’ come verrebbe:
 
Pensate un po’ se voleste istruirlo a riconoscere 4 amici, anziché 2. Guardate un po’ come verrebbe:
  
 
+
<br/>[[File:C++ Qt 02 Scratch 02.png|C++ con Qt, parte II, Scratch 02]]
[[File:C++_Qt_02_Scratch_02.png|C++ con Qt, parte II, Scratch 02"]]
+
  
 
Anche qui c’è un’istruzione di troppo, la stessa di prima, ma non è quella che ci sta complicando la vita. La domanda è: come verrebbe il programma se il robottino dovesse imparare a salutare '''tutti''' i vostri compagni di classe o tutte le persone che conoscete?
 
Anche qui c’è un’istruzione di troppo, la stessa di prima, ma non è quella che ci sta complicando la vita. La domanda è: come verrebbe il programma se il robottino dovesse imparare a salutare '''tutti''' i vostri compagni di classe o tutte le persone che conoscete?
Riga 46: Riga 43:
 
Chi ci capirebbe più niente, in tutti quei SE… ALLORA… ALTRIMENTI?
 
Chi ci capirebbe più niente, in tutti quei SE… ALLORA… ALTRIMENTI?
  
 +
<br/>Per fortuna il robottino è furbo e ci suggerisce un’alternativa:
  
Per fortuna il robottino è furbo e ci suggerisce un’alternativa:
+
<br/>[[File:C++ Qt 02 Scratch 03.png|C++ con Qt, parte II, Scratch 03]]
 
+
 
+
[[File:C++_Qt_02_Scratch_03.png|C++ con Qt, parte II, Scratch 03]]
+
  
 
Questo esempio fa la stessa cosa del precedente, ma introduce una cosa nuova, che fin qui non avevamo trattato: le liste.
 
Questo esempio fa la stessa cosa del precedente, ma introduce una cosa nuova, che fin qui non avevamo trattato: le liste.
Riga 58: Riga 53:
 
Pensiamo ai compiti da fare a casa: il maestro/a o professore/essa ci danno una serie di cose da studiare o di esercizi da fare. Certo, possono essere tutti diversi fra di loro, tipo leggere e ripetere pagine di storia; oppure condurre l’analisi logica di alcune frasi; oppure risolvere problemi di matematica; o molte altre cose. Però, anche se sono tutte diverse, per noi rientrano in un’unica categoria: sono i compiti per casa.
 
Pensiamo ai compiti da fare a casa: il maestro/a o professore/essa ci danno una serie di cose da studiare o di esercizi da fare. Certo, possono essere tutti diversi fra di loro, tipo leggere e ripetere pagine di storia; oppure condurre l’analisi logica di alcune frasi; oppure risolvere problemi di matematica; o molte altre cose. Però, anche se sono tutte diverse, per noi rientrano in un’unica categoria: sono i compiti per casa.
  
 
+
<br/>Tant’è che sul diario li scriviamo tutti insieme: a quella determinata data scriviamo tutte le materie che dobbiamo avere studiato, siano esse storia o italiano o matematica.
Tant’è che sul diario li scriviamo tutti insieme: a quella determinata data scriviamo tutte le materie che dobbiamo avere studiato, siano esse storia o italiano o matematica.
+
  
 
Altri esempi simili possono essere la lista della spesa o la rubrica del telefono: in una sono segnati oggetti che sono diversissimi fra di loro, come la verdura e i detersivi, mentre nella seconda ci possono essere nomi anche di persone che non si conoscono l’un con l’altra.
 
Altri esempi simili possono essere la lista della spesa o la rubrica del telefono: in una sono segnati oggetti che sono diversissimi fra di loro, come la verdura e i detersivi, mentre nella seconda ci possono essere nomi anche di persone che non si conoscono l’un con l’altra.
  
 +
<br/>Ma tutte queste cose hanno qualcosa in comune, che è il motivo per cui le scriviamo tutte di seguito, una dietro l’altra:
  
Ma tutte queste cose hanno qualcosa in comune, che è il motivo per cui le scriviamo tutte di seguito, una dietro l’altra:
+
*i compiti hanno in comune la data in cui devono essere svolti;
 
+
*i nomi nella rubrica hanno in comune di essere nostri amici o parenti;
* i compiti hanno in comune la data in cui devono essere svolti;
+
*gli oggetti nella lista della spesa hanno in comune di dover essere tutti acquistati oggi.
* i nomi nella rubrica hanno in comune di essere nostri amici o parenti;
+
* gli oggetti nella lista della spesa hanno in comune di dover essere tutti acquistati oggi.
+
  
 
Quindi: quando una serie di cose, simili o dissimili fra di loro, hanno un punto in comune, di solito preferiamo non considerarle come tante cose singole, ma come un’unica lista di tante cose.
 
Quindi: quando una serie di cose, simili o dissimili fra di loro, hanno un punto in comune, di solito preferiamo non considerarle come tante cose singole, ma come un’unica lista di tante cose.
  
 +
<br/>Anche quando creiamo una variabile possiamo pensare di doverci mettere un dato singolo, che non ha nessun rapporto con il contenuto delle altre variabili, oppure di doverci mettere una serie di dati che hanno qualcosa in comune.
  
Anche quando creiamo una variabile possiamo pensare di doverci mettere un dato singolo, che non ha nessun rapporto con il contenuto delle altre variabili, oppure di doverci mettere una serie di dati che hanno qualcosa in comune.
+
<br/>Nell’esempio Scratch precedente abbiamo deciso che non aveva senso creare una serie di variabili “amico1”, “amico2”, “amico3”… Abbiamo invece preferito creare un’unica lista “Amici” in cui ci fosse posto per tutti.
  
 +
<br/>Sono contento che abbiamo avuto modo di parlare di questo perché anche nel JavaScript e nel C++ abbiamo delle cose simile alle liste, ma si chiamano array, che è una parola inglese che significa ''schieramento'', oppure ''varietà'', ''gamma'' di oggetti. Come sapete, le parole ogni tanto hanno più significati e delle volte anche distanti fra di loro.
  
Nell’esempio Scratch precedente abbiamo deciso che non aveva senso creare una serie di variabili “amico1”, “amico2”, “amico3”… Abbiamo invece preferito creare un’unica lista “Amici” in cui ci fosse posto per tutti.
+
<br/>Però dobbiamo rimandare di un pochino il momento in cui affronteremo gli array in JavaScript perché ci eravamo ripromessi di guardare il significato del doppio simbolo di uguale, quella strana scritta ‘==’ che abbiamo trovato nel nostro programma.
 
+
 
+
Sono contento che abbiamo avuto modo di parlare di questo perché anche nel JavaScript e nel C++ abbiamo delle cose simile alle liste, ma si chiamano array, che è una parola inglese che significa ''schieramento'', oppure ''varietà'', ''gamma'' di oggetti. Come sapete, le parole ogni tanto hanno più significati e delle volte anche distanti fra di loro.
+
 
+
 
+
Però dobbiamo rimandare di un pochino il momento in cui affronteremo gli array in JavaScript perché ci eravamo ripromessi di guardare il significato del doppio simbolo di uguale, quella strana scritta ‘==’ che abbiamo trovato nel nostro programma.
+
  
 
<br/>Partiamo dal JavaScript:
 
<br/>Partiamo dal JavaScript:
 
 
<pre><!DOCTYPE html>
 
<pre><!DOCTYPE html>
  
Riga 125: Riga 113:
 
   <style>
 
   <style>
 
     .fraseCattiva {
 
     .fraseCattiva {
       color : red;
+
       color&nbsp;: red;
       text-decoration : underline;
+
       text-decoration&nbsp;: underline;
       text-transform : uppercase;
+
       text-transform&nbsp;: uppercase;
 
     }
 
     }
 
     </style>
 
     </style>
Riga 135: Riga 123:
  
 
   <div>
 
   <div>
     <p>Sappi che oggi sono d'umore un po&rsquo; scontroso. Pu&ograve; darsi che ti saluti e pu&ograve; darsi di <span class="fraseCattiva">no</span>.</p>
+
     <p>Sappi che oggi sono d'umore un po’ scontroso. Può darsi che ti saluti e può darsi di <span class="fraseCattiva">no</span>.</p>
     <p>Tu comunque provaci lo stesso&hellip;</p>
+
     <p>Tu comunque provaci lo stesso…</p>
 
   </div>
 
   </div>
  
Riga 145: Riga 133:
  
 
   <div>
 
   <div>
     <label for="cambiaTesto">Pulsante che modificher&agrave; il testo sottostante --></label>
+
     <label for="cambiaTesto">Pulsante che modificherà il testo sottostante --></label>
 
     <input type="button" id="cambiaTesto" value="Premimi per cambiare il testo"
 
     <input type="button" id="cambiaTesto" value="Premimi per cambiare il testo"
 
         onclick="cambioTesto();" />
 
         onclick="cambioTesto();" />
Riga 151: Riga 139:
  
 
   <div>
 
   <div>
     <p id="testoDaCambiare">Il testo contenuto in questo paragrafo cambier&agrave; quando sar&agrave; premuto il pulsante soprastante.</p>
+
     <p id="testoDaCambiare">Il testo contenuto in questo paragrafo cambierà quando sarà premuto il pulsante soprastante.</p>
 
   </div>
 
   </div>
  
Riga 157: Riga 145:
 
</html>
 
</html>
 
</pre>
 
</pre>
 
 
Come primo commento lasciatemi dire: che brutto!
 
Come primo commento lasciatemi dire: che brutto!
  
 
Lo so che ora stavamo parlando d’altro, e fra un attimo riprendo il filo, però prima o poi a questa osservazione bisognava arrivarci: adesso abbiamo un codice dove si trovano mischiati HTML5, JavaScript e CSS. Non ci si capisce più niente. Se vogliamo avventurarci nel mondo del C++ dobbiamo essere molto più precisi, perché nel C++ il codice deve stare diviso in blocchi coerenti.
 
Lo so che ora stavamo parlando d’altro, e fra un attimo riprendo il filo, però prima o poi a questa osservazione bisognava arrivarci: adesso abbiamo un codice dove si trovano mischiati HTML5, JavaScript e CSS. Non ci si capisce più niente. Se vogliamo avventurarci nel mondo del C++ dobbiamo essere molto più precisi, perché nel C++ il codice deve stare diviso in blocchi coerenti.
  
 
+
<br/>Cominciamo da questo: entriamo in una cartella dove possiamo salvare i nostri file che non sono C++ – oppure creiamone una.
Cominciamo da questo: entriamo in una cartella dove possiamo salvare i nostri file che non sono C++ – oppure creiamone una.
+
  
 
Poi facciamo il copia-incolla del codice di cui sopra e chiamiamolo BruttaRisposta.html
 
Poi facciamo il copia-incolla del codice di cui sopra e chiamiamolo BruttaRisposta.html
Riga 169: Riga 155:
 
Fin qui non ci dovrebbero essere novità. Ora però creiamo altri due file, vuoti:
 
Fin qui non ci dovrebbero essere novità. Ora però creiamo altri due file, vuoti:
  
* BruttaRisposta.js
+
*BruttaRisposta.js
* BruttaRisposta.CSS
+
*BruttaRisposta.CSS
  
 
Tagliamo dal file BruttaRisposta.html le righe
 
Tagliamo dal file BruttaRisposta.html le righe
 
 
<pre>  function cambioTesto(){
 
<pre>  function cambioTesto(){
 
     var utente = document.getElementById("risposta").value;
 
     var utente = document.getElementById("risposta").value;
Riga 201: Riga 186:
 
     }
 
     }
 
</pre>
 
</pre>
 
 
e incolliamole nel file BruttaRisposta.js.
 
e incolliamole nel file BruttaRisposta.js.
  
 
+
<br/>Nel file BruttaRisposta.html modifichiamo le righe:
Nel file BruttaRisposta.html modifichiamo le righe:
+
 
+
 
<pre><script type="text/javascript">
 
<pre><script type="text/javascript">
 
</script>
 
</script>
 
</pre>
 
</pre>
 
 
in questo modo:
 
in questo modo:
 
 
<pre><script type="text/javascript" src="BruttaRisposta.js"></script></pre>
 
<pre><script type="text/javascript" src="BruttaRisposta.js"></script></pre>
 
 
Dallo stesso file facciamo il taglia delle seguenti righe:
 
Dallo stesso file facciamo il taglia delle seguenti righe:
 
 
<pre>  .fraseCattiva {
 
<pre>  .fraseCattiva {
     color           : red;
+
     color         &nbsp;: red;
     text-decoration : underline;
+
     text-decoration&nbsp;: underline;
     text-transform : uppercase;
+
     text-transform &nbsp;: uppercase;
 
   }
 
   }
 
</pre>
 
</pre>
 
 
e incolliamole nel file BruttaRisposta.CSS
 
e incolliamole nel file BruttaRisposta.CSS
  
 
Sempre nel file BruttaRisposta.html, '''modifichiamo''' le seguenti righe:
 
Sempre nel file BruttaRisposta.html, '''modifichiamo''' le seguenti righe:
 
 
<pre> <style>
 
<pre> <style>
 
</style>
 
</style>
 
</pre>
 
</pre>
 
 
in modo che diventino così:
 
in modo che diventino così:
 
 
<pre> <link rel="stylesheet" href="BruttaRisposta.CSS" type="text/css" /></pre>
 
<pre> <link rel="stylesheet" href="BruttaRisposta.CSS" type="text/css" /></pre>
 
(di due righe ne rimane una)
 
(di due righe ne rimane una)
  
 +
<br/>A questo punto dovremmo trovarci in questa situazione:
  
A questo punto dovremmo trovarci in questa situazione:
+
<br/>Un file BruttaRisposta.html con questo codice dentro:
 
+
 
+
Un file BruttaRisposta.html con questo codice dentro:
+
 
+
 
<pre><!DOCTYPE html>
 
<pre><!DOCTYPE html>
  
Riga 259: Riga 230:
  
 
   <div>
 
   <div>
     <p>Sappi che oggi sono d'umore un po&rsquo; scontroso. Pu&ograve; darsi che ti saluti e pu&ograve; darsi di <span class="fraseCattiva">no</span>.</p>
+
     <p>Sappi che oggi sono d'umore un po’ scontroso. Può darsi che ti saluti e può darsi di <span class="fraseCattiva">no</span>.</p>
     <p>Tu comunque provaci lo stesso&hellip;</p>
+
     <p>Tu comunque provaci lo stesso…</p>
 
   </div>
 
   </div>
  
Riga 269: Riga 240:
  
 
   <div>
 
   <div>
     <label for="cambiaTesto">Pulsante che modificher&agrave; il testo sottostante --></label>
+
     <label for="cambiaTesto">Pulsante che modificherà il testo sottostante --></label>
 
     <input type="button" id="cambiaTesto" value="Premimi per cambiare il testo"
 
     <input type="button" id="cambiaTesto" value="Premimi per cambiare il testo"
 
         onclick="cambioTesto();" />
 
         onclick="cambioTesto();" />
Riga 275: Riga 246:
  
 
   <div>
 
   <div>
     <p id="testoDaCambiare">Il testo contenuto in questo paragrafo cambier&agrave; quando sar&agrave; premuto il pulsante soprastante.</p>
+
     <p id="testoDaCambiare">Il testo contenuto in questo paragrafo cambierà quando sarà premuto il pulsante soprastante.</p>
 
   </div>
 
   </div>
  
Riga 281: Riga 252:
 
</html>
 
</html>
 
</pre>
 
</pre>
 
 
Un file BruttaRisposta.js con questo codice dentro:
 
Un file BruttaRisposta.js con questo codice dentro:
 
 
<pre>function cambioTesto() {
 
<pre>function cambioTesto() {
 
     var utente = document.getElementById("risposta").value;
 
     var utente = document.getElementById("risposta").value;
Riga 310: Riga 279:
 
  }
 
  }
 
</pre>
 
</pre>
 
 
Un file BruttaRisposta.CSS con questo codice dentro:
 
Un file BruttaRisposta.CSS con questo codice dentro:
 
 
<pre>.fraseCattiva {
 
<pre>.fraseCattiva {
   color : red;
+
   color&nbsp;: red;
   text-decoration : underline;
+
   text-decoration&nbsp;: underline;
   text-transform : uppercase;
+
   text-transform&nbsp;: uppercase;
 
  }
 
  }
 
</pre>
 
</pre>
 
 
I tre file sembrano separati fra di loro, ma non lo sono: finché li avremo tutti e tre nella stessa cartella, le nuove istruzioni nel file HTML porteranno il browser a caricare tutti e tre i file e ad usarli come se fossero tutti scritti nello stesso file.
 
I tre file sembrano separati fra di loro, ma non lo sono: finché li avremo tutti e tre nella stessa cartella, le nuove istruzioni nel file HTML porteranno il browser a caricare tutti e tre i file e ad usarli come se fossero tutti scritti nello stesso file.
  
 
+
<br/>Ossia, quando il browser leggerà:
Ossia, quando il browser leggerà:
+
 
+
 
<pre><script type="text/javascript" src="BruttaRisposta.js"></script></pre>
 
<pre><script type="text/javascript" src="BruttaRisposta.js"></script></pre>
 
 
andrà a cercare il file BruttaRisposta.js e lo caricherà in memoria per intero, e solo dopo che avrà finito questa operazione proseguirà a leggere il resto del documento HTML.
 
andrà a cercare il file BruttaRisposta.js e lo caricherà in memoria per intero, e solo dopo che avrà finito questa operazione proseguirà a leggere il resto del documento HTML.
  
 
Lo stesso accadrà con il file BruttaRisposta.CSS all’istruzione:
 
Lo stesso accadrà con il file BruttaRisposta.CSS all’istruzione:
 
 
<pre><link rel="stylesheet" href="BruttaRisposta.CSS" type="text/css" /></pre>
 
<pre><link rel="stylesheet" href="BruttaRisposta.CSS" type="text/css" /></pre>
 +
Mentre osservate con gioia la chiarezza e pulizia del codice che siamo riusciti a ottenere, una vocina potrebbe suggerirvi nella testa: «Ehi! Ma è la stessa cosa che succedeva nel C++ con l’istruzione #include &lt;iostream&gt;!»
  
Mentre osservate con gioia la chiarezza e pulizia del codice che siamo riusciti a ottenere, una vocina potrebbe suggerirvi nella testa: «Ehi! Ma è la stessa cosa che succedeva nel C++ con l’istruzione #include <iostream>
+
<br/>Esatto!
 
+
 
+
Esatto!
+
  
 
A dire il vero da un punto di vista tecnico non sono la stessa cosa, ma il concetto di base è lo stesso.
 
A dire il vero da un punto di vista tecnico non sono la stessa cosa, ma il concetto di base è lo stesso.
  
 
+
<br/>Ottimo! Ora abbiamo imparato a dividere il nostro codice su più file, che è una delle cose che rende il C++ così utile e apprezzato; sarà bene che sappiate, infatti, che noi ci sforzeremo di disubbidire perché siamo appena all’inizio, ma gli ambienti di programmazione in C++ fanno di tutto per convincere i programmatori a spezzare il codice su più file.
Ottimo! Ora abbiamo imparato a dividere il nostro codice su più file, che è una delle cose che rende il C++ così utile e apprezzato; sarà bene che sappiate, infatti, che noi ci sforzeremo di disubbidire perché siamo appena all’inizio, ma gli ambienti di programmazione in C++ fanno di tutto per convincere i programmatori a spezzare il codice su più file.
+
  
 
Dividere il codice in più file è indispensabile in una forma di programmazione, che si chiama programmazione a oggetti, che ha molti estimatori.
 
Dividere il codice in più file è indispensabile in una forma di programmazione, che si chiama programmazione a oggetti, che ha molti estimatori.
  
 
+
<br/>Adesso diamo un’occhiata al nostro file JavaScript, così bello pulito, e paragoniamo queste due righe:
Adesso diamo un’occhiata al nostro file JavaScript, così bello pulito, e paragoniamo queste due righe:
+
 
+
 
<pre>if ( 1 == controllaNome(utente) ) {
 
<pre>if ( 1 == controllaNome(utente) ) {
 
     risultato = 1;
 
     risultato = 1;
 
</pre>
 
</pre>
 
 
che dovrebbero essere rispettivamente la 4 e la 19 – o giù di lì, se nell’incollare abbiamo lasciato qualche riga bianca.
 
che dovrebbero essere rispettivamente la 4 e la 19 – o giù di lì, se nell’incollare abbiamo lasciato qualche riga bianca.
  
 +
<br/>Notiamo subito che nella prima compare di nuovo il simbolo ‘==’, e immagino che per voi ormai sia chiaro cosa significa. Ma possiamo cercare ispirazione anche in ciò che abbiamo visto in Scratch:
  
Notiamo subito che nella prima compare di nuovo il simbolo ‘==’, e immagino che per voi ormai sia chiaro cosa significa. Ma possiamo cercare ispirazione anche in ciò che abbiamo visto in Scratch:
+
<br/>[[File:C++ Qt 02 Scratch 03 duerighe.png|C++ con Qt, parte II, due righe di Scratch]]
 
+
 
+
[[File:C++_Qt_02_Scratch_03_duerighe.png|C++ con Qt, parte II, due righe di Scratch"]]
+
  
 
La prima istruzione dice: prendi la risposta che ottieni e '''copiala''' in una cella di memoria a cui ho messo l’etichetta ''Nome'' (o, per brevità: ''nella variabile Nome'').
 
La prima istruzione dice: prendi la risposta che ottieni e '''copiala''' in una cella di memoria a cui ho messo l’etichetta ''Nome'' (o, per brevità: ''nella variabile Nome'').
Riga 364: Riga 318:
 
La seconda invece dice: CONFRONTA se quello che è contenuto nella variabile ''amico1'' è uguale a quello che è contenuto nella variabile ''risposta''.
 
La seconda invece dice: CONFRONTA se quello che è contenuto nella variabile ''amico1'' è uguale a quello che è contenuto nella variabile ''risposta''.
  
 +
<br/>Ecco dunque che Scratch ci offre due possibili modi di lavorare con le variabili: '''copiare''' i valori da una all’altra oppure '''confrontare''' il valore di una con il valore dell’altra.
  
Ecco dunque che Scratch ci offre due possibili modi di lavorare con le variabili: '''copiare''' i valori da una all’altra oppure '''confrontare''' il valore di una con il valore dell’altra.
+
<br/>Anche il JavaScript ci consente di compiere queste due operazioni, con l’unico difetto che la sintassi da usare è così simile, nei due casi, che può capitare di confondersi.
 
+
 
+
Anche il JavaScript ci consente di compiere queste due operazioni, con l’unico difetto che la sintassi da usare è così simile, nei due casi, che può capitare di confondersi.
+
 
+
 
+
Mettiamo che io abbia creato una variabile qualsiasi, chiamiamola “mia_variabile”. In JavaScript:
+
  
 +
<br/>Mettiamo che io abbia creato una variabile qualsiasi, chiamiamola “mia_variabile”. In JavaScript:
 
<pre>var mia_variabile;</pre>
 
<pre>var mia_variabile;</pre>
 
 
A questo punto ci posso inserire dentro dei valori:
 
A questo punto ci posso inserire dentro dei valori:
 
 
<pre>mia_variabile = 4;</pre>
 
<pre>mia_variabile = 4;</pre>
 
 
Dopo questa istruzione, dentro la cella di memoria etichettata mia_variabile si troverà il dato ‘4’.
 
Dopo questa istruzione, dentro la cella di memoria etichettata mia_variabile si troverà il dato ‘4’.
  
Riga 384: Riga 331:
  
 
Ecco qui come viene:
 
Ecco qui come viene:
 
 
<pre>if ( mia_variabile == 4) …</pre>
 
<pre>if ( mia_variabile == 4) …</pre>
 
 
Eccolo lì! Il mistero è svelato: il simbolo ‘==’ significa confronta; non serve a inserire dati dentro la variabile, bensì a leggerli e a porli in paragone con altri dati. Quindi i due simboli (‘=’ e ‘==’) somigliano, ma sono completamente diversi.
 
Eccolo lì! Il mistero è svelato: il simbolo ‘==’ significa confronta; non serve a inserire dati dentro la variabile, bensì a leggerli e a porli in paragone con altri dati. Quindi i due simboli (‘=’ e ‘==’) somigliano, ma sono completamente diversi.
  
 
Se per errore scriviamo:
 
Se per errore scriviamo:
 
 
<pre>if ( mia_variabile = 4) …</pre>
 
<pre>if ( mia_variabile = 4) …</pre>
 
 
ci facciamo del male da soli. Infatti quello che succederà dentro la parentesi sarà che il computer, ubbidendo alle nostre istruzioni, inserirà il dato ‘4’ nella variabile mia_variabile. Non solo, ma quando avrà finito, si confermerà da solo: «Tutto ok, operazione andata a buon fine», che è un segnale di ritorno positivo, ossia uguale a “vero”, e quindi potrebbe arrivare a questa brillante conclusione: il contenuto della parentesi è vero!
 
ci facciamo del male da soli. Infatti quello che succederà dentro la parentesi sarà che il computer, ubbidendo alle nostre istruzioni, inserirà il dato ‘4’ nella variabile mia_variabile. Non solo, ma quando avrà finito, si confermerà da solo: «Tutto ok, operazione andata a buon fine», che è un segnale di ritorno positivo, ossia uguale a “vero”, e quindi potrebbe arrivare a questa brillante conclusione: il contenuto della parentesi è vero!
  
 
Di conseguenza potrebbe eseguire '''sempre''' il codice SE… ALLORA, e '''mai''' quello ALTRIMENTI.
 
Di conseguenza potrebbe eseguire '''sempre''' il codice SE… ALLORA, e '''mai''' quello ALTRIMENTI.
  
 
+
<br/>Questo errore è veramente comune, tanto che c’è chi consiglia di abituarsi a scrivere alla rovescia:
Questo errore è veramente comune, tanto che c’è chi consiglia di abituarsi a scrivere alla rovescia:
+
 
+
 
<pre>if ( 4 == mia_variabile ) …</pre>
 
<pre>if ( 4 == mia_variabile ) …</pre>
 
 
che apparentemente può sembrare assurdo, ma invece funziona!
 
che apparentemente può sembrare assurdo, ma invece funziona!
  
Riga 409: Riga 349:
  
 
Il vantaggio è che, se per errore scrivessimo:
 
Il vantaggio è che, se per errore scrivessimo:
 
 
<pre>if ( 4 = mia_variabile ) …</pre>
 
<pre>if ( 4 = mia_variabile ) …</pre>
 
 
in linguaggi come il C++ il compilatore si fermerebbe e ci chiederebbe cosa cappero stiamo scrivendo. 4 è un numero, e non si può dire: scrivi il contenuto di mia_variabile in 4, non ha senso!
 
in linguaggi come il C++ il compilatore si fermerebbe e ci chiederebbe cosa cappero stiamo scrivendo. 4 è un numero, e non si può dire: scrivi il contenuto di mia_variabile in 4, non ha senso!
  
 
Nel caso del JavaScript, invece, probabilmente l’esecuzione del codice si interromperebbe, facendoci capire che da qualche parte abbiamo sbagliato qualcosa.
 
Nel caso del JavaScript, invece, probabilmente l’esecuzione del codice si interromperebbe, facendoci capire che da qualche parte abbiamo sbagliato qualcosa.
  
 
+
<br/>Possiamo ora leggere il nostro codice JavaScript per essere sicuri di averlo capito bene:
Possiamo ora leggere il nostro codice JavaScript per essere sicuri di averlo capito bene:
+
  
 
Cominciamo dalla funzione ''cambioTesto'':
 
Cominciamo dalla funzione ''cambioTesto'':
  
 
+
<br/><u>'''var utente = document.getElementById("risposta").value;'''</u>
'''var utente = document.getElementById("risposta").value;'''
+
  
 
Dovrebbe essere chiara. Vuol dire:
 
Dovrebbe essere chiara. Vuol dire:
  
* trova l’elemento HTML con id="risposta"
+
*trova l’elemento HTML con id="risposta"
* leggi il suo contenuto
+
*leggi il suo contenuto
* crea la variabile ''utente'' e inserisci questo contenuto lì dentro
+
*crea la variabile ''utente'' e inserisci questo contenuto lì dentro
  
'''if ( 1 == controllaNome(utente) ) {'''
+
<u>'''if ( 1 == controllaNome(utente) ) {'''</u>
  
 
Questa può richiedere un po’ più di ragionamento.
 
Questa può richiedere un po’ più di ragionamento.
Riga 438: Riga 374:
 
A questo punto, l’esecuzione salta da qui fin dentro la funzione ''controllaNome'' per cercare di avere il suo segnale di ritorno. Nel salto, si porta con sé il valore contenuto nella neonata variabile ‘utente’, perché dovrà inserirlo nella variabile che è lì in attesa, cioè quella che è scritta dentro la parentesi dopo il nome di funzione ''controllaNome''.
 
A questo punto, l’esecuzione salta da qui fin dentro la funzione ''controllaNome'' per cercare di avere il suo segnale di ritorno. Nel salto, si porta con sé il valore contenuto nella neonata variabile ‘utente’, perché dovrà inserirlo nella variabile che è lì in attesa, cioè quella che è scritta dentro la parentesi dopo il nome di funzione ''controllaNome''.
  
 +
<br/>Saltiamo anche noi dentro ''controllaNome'', ma ricordiamoci che poi dovremo tornare qui.
  
Saltiamo anche noi dentro ''controllaNome'', ma ricordiamoci che poi dovremo tornare qui.
+
<br/><u>'''function controllaNome(persona) {'''</u>
 
+
 
+
'''function controllaNome(persona) {'''
+
  
 
A queste punto, nella variabile ‘persona’ è stato copiato il contenuto della variabile ‘utente’.
 
A queste punto, nella variabile ‘persona’ è stato copiato il contenuto della variabile ‘utente’.
  
 
+
<br/><u>'''var risultato;'''</u>
'''var risultato;'''
+
  
 
Crea un’altra variabile.
 
Crea un’altra variabile.
  
 
+
<br/><u>'''if (persona == "Mario" || persona == "Maria" || persona == "Gianni" || persona == "Gianna") {'''</u>
'''if (persona == "Mario" || persona == "Maria" || persona == "Gianni" || persona == "Gianna") {'''
+
  
 
Ahia!
 
Ahia!
  
Questa può far male, lo ammetto :)
+
Questa può far male, lo ammetto&nbsp;:)
  
 
Leggiamola con calma. Il simbolo ‘||’ sembra una cosa molto misteriosa, ma vuol dire solo ‘oppure’.
 
Leggiamola con calma. Il simbolo ‘||’ sembra una cosa molto misteriosa, ma vuol dire solo ‘oppure’.
Riga 464: Riga 396:
 
«SE la variabile persona contiene ''Mario'' OPPURE la variabile persona contiene ''Maria'' OPPURE la variabile persona contiene ''Gianni'' OPPURE la variabile persona contiene ''Gianna'', ALLORA…»
 
«SE la variabile persona contiene ''Mario'' OPPURE la variabile persona contiene ''Maria'' OPPURE la variabile persona contiene ''Gianni'' OPPURE la variabile persona contiene ''Gianna'', ALLORA…»
  
 
+
<br/>Non è così difficile da interpretare: il simbolo || dice al computer: me ne basta una.
Non è così difficile da interpretare: il simbolo || dice al computer: me ne basta una.
+
  
 
Ossia: io ti do due possibilità, una è quella a sinistra del simbolo e una è quella a destra; se anche solo una delle due è vera, allora mi devi rispondere ‘vero!’.
 
Ossia: io ti do due possibilità, una è quella a sinistra del simbolo e una è quella a destra; se anche solo una delle due è vera, allora mi devi rispondere ‘vero!’.
Riga 471: Riga 402:
 
Da un altro punto di vista: la condizione è falsa se '''TUTTE''' le condizioni sono false.
 
Da un altro punto di vista: la condizione è falsa se '''TUTTE''' le condizioni sono false.
  
 
+
<br/><u>'''risultato = 1;'''</u>
'''risultato = 1;'''
+
  
 
Si arriva a questo punto qui solo se la variabile ‘persona’ contiene uno dei 4 nomi sopra elencati.
 
Si arriva a questo punto qui solo se la variabile ‘persona’ contiene uno dei 4 nomi sopra elencati.
  
 +
<br/><u>'''else{'''</u>
  
'''else{'''
+
<u>'''risultato = 0;'''</u>
 
+
'''risultato = 0;'''
+
  
 
(ALTRIMENTI) Si arriva qui se l’utente non ha digitato nessuno dei 4 nomi previsti.
 
(ALTRIMENTI) Si arriva qui se l’utente non ha digitato nessuno dei 4 nomi previsti.
  
 
+
<br/><u>'''return risultato;'''</u>
'''return risultato;'''
+
  
 
Se l’utente ha digitato uno dei 4 nomi, il segnale di ritorno sarà 1, altrimenti sarà 0.
 
Se l’utente ha digitato uno dei 4 nomi, il segnale di ritorno sarà 1, altrimenti sarà 0.
  
 
+
<br/><u>'''if ( 1 == controllaNome(utente) ) {'''</u>
'''if ( 1 == controllaNome(utente) ) {'''
+
  
 
Questo rigo l’avevamo già visto, ma ho preferito ritornare qui perché il processo fosse più chiaro.
 
Questo rigo l’avevamo già visto, ma ho preferito ritornare qui perché il processo fosse più chiaro.
Riga 496: Riga 423:
  
 
Le ultime due righe non sto nemmeno a spiegarle perché spero siano chiarissime.
 
Le ultime due righe non sto nemmeno a spiegarle perché spero siano chiarissime.
 +
  
  
 
=== Confessioni e paroloni ===
 
=== Confessioni e paroloni ===
 +
 
Va bene, lo ammetto: lo sto facendo apposta.
 
Va bene, lo ammetto: lo sto facendo apposta.
  
 
In effetti il codice JavaScript avrebbe potuto essere scritto così:
 
In effetti il codice JavaScript avrebbe potuto essere scritto così:
 
 
<pre>function cambioTesto() {
 
<pre>function cambioTesto() {
 
     var utente = document.getElementById("risposta").value;
 
     var utente = document.getElementById("risposta").value;
Riga 515: Riga 443:
 
  }
 
  }
 
</pre>
 
</pre>
 
 
e avrebbe funzionato lo stesso.
 
e avrebbe funzionato lo stesso.
  
 +
<br/>Il fatto è che dobbiamo abituarci a scrivere funzioni, per cui anche in questo caso in cui si sarebbe potuta saltare, non è stata una cattiva idea scriverla: adesso abbiamo una funzione che svolge un compito preciso ed è possibile che un domani ci torni comodo un’altra volta. Nel qual caso, sappiamo dove trovarla. È un pezzo di codice riutilizzabile.
  
Il fatto è che dobbiamo abituarci a scrivere funzioni, per cui anche in questo caso in cui si sarebbe potuta saltare, non è stata una cattiva idea scriverla: adesso abbiamo una funzione che svolge un compito preciso ed è possibile che un domani ci torni comodo un’altra volta. Nel qual caso, sappiamo dove trovarla. È un pezzo di codice riutilizzabile.
+
<br/>E poi avete ragione: tutte queste righe di codice solo per spiegare che ‘==’ vuol dire ‘confronta’…
 
+
 
+
E poi avete ragione: tutte queste righe di codice solo per spiegare che ‘==’ vuol dire ‘confronta’…
+
  
 
Va bene, vorrà dire che scriveremo anche il codice con gli array, ossia l’equivalente delle liste di Scratch.
 
Va bene, vorrà dire che scriveremo anche il codice con gli array, ossia l’equivalente delle liste di Scratch.
  
 
+
<br/>Ma prima del divertimento dobbiamo levarci un sassolino dalla scarpa. Finora ho usato espressioni del tipo: “il dato contenuto nella cella di memoria etichettata…”; oppure: “creare una variabile”; o anche: “la funzione che abbiamo chiamato ''nomeFunzione''”; ecc. ecc.
Ma prima del divertimento dobbiamo levarci un sassolino dalla scarpa. Finora ho usato espressioni del tipo: “il dato contenuto nella cella di memoria etichettata…”; oppure: “creare una variabile”; o anche: “la funzione che abbiamo chiamato ''nomeFunzione''”; ecc. ecc.
+
  
 
Adesso è venuto il momento di essere un gocciolino più precisi, nel senso di imparare un po’ di termini appropriati.
 
Adesso è venuto il momento di essere un gocciolino più precisi, nel senso di imparare un po’ di termini appropriati.
  
 
+
<br/>Per ora preoccupiamoci solo delle variabili.
Per ora preoccupiamoci solo delle variabili.
+
  
 
È chiaro a tutti che una variabile è una cella di memoria a cui abbiamo dato un’etichetta e che quella cella di memoria il computer non la gestisce come vuole lui, bensì ci inserisce solo i dati che decidiamo noi? Okay, allora non userò più l’espressione ‘cella di memoria’, ma parlerò solo di variabili.
 
È chiaro a tutti che una variabile è una cella di memoria a cui abbiamo dato un’etichetta e che quella cella di memoria il computer non la gestisce come vuole lui, bensì ci inserisce solo i dati che decidiamo noi? Okay, allora non userò più l’espressione ‘cella di memoria’, ma parlerò solo di variabili.
  
 
Allora, il dato contenuto in una variabile è detto '''''valore''''' della variabile. Questo non è vero solo per le variabili numeriche, bensì anche per le variabili che contengono testo. Ossia, se in C++ scrivo:
 
Allora, il dato contenuto in una variabile è detto '''''valore''''' della variabile. Questo non è vero solo per le variabili numeriche, bensì anche per le variabili che contengono testo. Ossia, se in C++ scrivo:
 
 
<pre>string amico1 = "Mario"</pre>
 
<pre>string amico1 = "Mario"</pre>
 
 
per riferirmi al dato contenuto nella variabile ‘amico1’ uno dovrò dire: «il valore della variabile ‘amico1’ di tipo string è “Mario”».
 
per riferirmi al dato contenuto nella variabile ‘amico1’ uno dovrò dire: «il valore della variabile ‘amico1’ di tipo string è “Mario”».
  
Riga 546: Riga 467:
 
Adesso, se volessimo fare una lezione barbosissima, dovremmo affrontare un argomento davvero complicato, perché in C++ non potete creare una variabile, però potete dichiararla, definirla o inizializzarla, che sono tre cose diverse fra di loro. Però per ora tralasceremo questo argomento e troveremo un compromesso fra di noi, a livello amichevole: useremo le parole dichiarare e definire come se fossero sinonimi, tenendo però presente che verrà il momento di distinguere questi due passaggi.
 
Adesso, se volessimo fare una lezione barbosissima, dovremmo affrontare un argomento davvero complicato, perché in C++ non potete creare una variabile, però potete dichiararla, definirla o inizializzarla, che sono tre cose diverse fra di loro. Però per ora tralasceremo questo argomento e troveremo un compromesso fra di noi, a livello amichevole: useremo le parole dichiarare e definire come se fossero sinonimi, tenendo però presente che verrà il momento di distinguere questi due passaggi.
  
 
+
<br/>Ancora un punto e potremo tornare al nostro codice.
Ancora un punto e potremo tornare al nostro codice.
+
  
 
Vi ricordate come siete stati bravi a scoprire che length() era una funzione perché il nome era seguito da parentesi tonde? Vi andrebbe bene se d’ora innanzi procedessimo sullo stesso sentiero, ossia se scrivessi i nomi di funzione sempre seguiti da parentesi tonde? Perché questa sarebbe la convenzione.
 
Vi ricordate come siete stati bravi a scoprire che length() era una funzione perché il nome era seguito da parentesi tonde? Vi andrebbe bene se d’ora innanzi procedessimo sullo stesso sentiero, ossia se scrivessi i nomi di funzione sempre seguiti da parentesi tonde? Perché questa sarebbe la convenzione.
Riga 553: Riga 473:
 
Ad es., poco sopra avrei dovuto scrivere: “il valore di ritorno di controllaNome(), che può essere…”. Sarebbe molto comodo perché non correremmo più il rischio di confondere una variabile con una funzione.
 
Ad es., poco sopra avrei dovuto scrivere: “il valore di ritorno di controllaNome(), che può essere…”. Sarebbe molto comodo perché non correremmo più il rischio di confondere una variabile con una funzione.
  
 
+
<br/>Chiusa la piccola parentesi sui termini, devo confessare un altro piccolo dispetto, nel caso qualcuno non se ne fosse accorto.
Chiusa la piccola parentesi sui termini, devo confessare un altro piccolo dispetto, nel caso qualcuno non se ne fosse accorto.
+
  
 
Vi avevo detto che molto spesso si usa 0 come valore di ritorno dandogli senso positivo, ossia di “zero errori”. Questa però non è assolutamente una regola, anzi! Può darsi benissimo che una funzione restituisca 0 proprio per indicare una situazione di errore o comunque problematica. In tal caso, diciamo che andrebbe interpretata come “risultati 0”.
 
Vi avevo detto che molto spesso si usa 0 come valore di ritorno dandogli senso positivo, ossia di “zero errori”. Questa però non è assolutamente una regola, anzi! Può darsi benissimo che una funzione restituisca 0 proprio per indicare una situazione di errore o comunque problematica. In tal caso, diciamo che andrebbe interpretata come “risultati 0”.
Riga 560: Riga 479:
 
Questo significa che:
 
Questo significa che:
  
* quando usate una funzione preparata da qualcun altro (vedi ''length()''), dovete andare a leggere quali segnali di ritorno ha previsto chi l’ha scritta;
+
*quando usate una funzione preparata da qualcun altro (vedi ''length()''), dovete andare a leggere quali segnali di ritorno ha previsto chi l’ha scritta;
* quando scrivete una funzione, vi potete considerare liberi di scegliere i valori di ritorno che preferite!
+
*quando scrivete una funzione, vi potete considerare liberi di scegliere i valori di ritorno che preferite!
  
 
Ad esempio, nella funzione ''controllaNome''… OPS! Volevo dire ''controllaNome()'', scusate!… Nella funzione ''controllaNome()'' abbiamo deciso di restituire 1 per significare “ho trovato una corrispondenza” e 0 per dire “nessuna corrispondenza trovata”.
 
Ad esempio, nella funzione ''controllaNome''… OPS! Volevo dire ''controllaNome()'', scusate!… Nella funzione ''controllaNome()'' abbiamo deciso di restituire 1 per significare “ho trovato una corrispondenza” e 0 per dire “nessuna corrispondenza trovata”.
  
 
+
<br/>Visto che questo è un tutorial sul C++, vediamo infine come verrebbe il nostro codice in C++. Visto che stiamo parlando delle basi del C++, quelle che sono cambiate poco rispetto al C, la somiglianza con il JavaScript è davvero tanta:
Visto che questo è un tutorial sul C++, vediamo infine come verrebbe il nostro codice in C++. Visto che stiamo parlando delle basi del C++, quelle che sono cambiate poco rispetto al C, la somiglianza con il JavaScript è davvero tanta:
+
 
+
 
<pre>#include <iostream>
 
<pre>#include <iostream>
  
Riga 610: Riga 527:
 
}
 
}
 
</pre>
 
</pre>
 
 
Direi che, se si è capito come funziona la versione JavaScript, non dovrebbe essere un problema decifrare questo codice.
 
Direi che, se si è capito come funziona la versione JavaScript, non dovrebbe essere un problema decifrare questo codice.
  
 
Anche in questo caso si può fare l’equivalente della versione breve:
 
Anche in questo caso si può fare l’equivalente della versione breve:
 
 
<pre>#include <iostream>
 
<pre>#include <iostream>
  
Riga 642: Riga 557:
 
}
 
}
 
</pre>
 
</pre>
 
 
Per poter scrivere il nostro programmino con gli array, però, dobbiamo introdurre prima un’altra novità.
 
Per poter scrivere il nostro programmino con gli array, però, dobbiamo introdurre prima un’altra novità.
  
 
Infatti Scratch ci offriva un’operazione interessante da compiere sulle liste, ossia questa qui:
 
Infatti Scratch ci offriva un’operazione interessante da compiere sulle liste, ossia questa qui:
  
 +
<br/>[[File:C++ Qt 02 Scratch 03 contiene.png|C++ con Qt, parte II, Scratch 03 contains]]
  
[[File:C++_Qt_02_Scratch_03_contiene.png|C++ con Qt, parte II, Scratch 03 contains]]
+
<br/>Bisogna ammettere che è molto comoda: se ho una lista di 100 amici, con una sola istruzione posso sapere se un nome è in quella lista o no.
 
+
 
+
Bisogna ammettere che è molto comoda: se ho una lista di 100 amici, con una sola istruzione posso sapere se un nome è in quella lista o no.
+
  
 
Purtroppo il JavaScript non ci fornisce niente di equivalente, come non ce la fornirebbe il C. Il C++ invece, vedremo, sa essere un pochino più amichevole in questo genere di operazioni, per per arrivare a quello dobbiamo perdere un po’ di tempo sulla programmazione ‘tradizionale’.
 
Purtroppo il JavaScript non ci fornisce niente di equivalente, come non ce la fornirebbe il C. Il C++ invece, vedremo, sa essere un pochino più amichevole in questo genere di operazioni, per per arrivare a quello dobbiamo perdere un po’ di tempo sulla programmazione ‘tradizionale’.
  
 
+
<br/>Vediamo di scoprire come si può risolvere il problema.
Vediamo di scoprire come si può risolvere il problema.
+
  
 
La soluzione parte dal presupposto che la lista debba per forza essere ordinata. È vero che nella vita abbiamo spesso a che fare con liste apparentemente disordinate, come ad esempio la lista della spesa, in cui scriviamo le cose via via che ci vengono in mente, ma per il computer le cose non stanno così.
 
La soluzione parte dal presupposto che la lista debba per forza essere ordinata. È vero che nella vita abbiamo spesso a che fare con liste apparentemente disordinate, come ad esempio la lista della spesa, in cui scriviamo le cose via via che ci vengono in mente, ma per il computer le cose non stanno così.
Riga 664: Riga 575:
 
Pertanto, se abbiamo inserito il nome “Gianni” per terzo, per quel che riguarda il computer quel nome rimarrà sempre in terza posizione, o almeno finché noi non gli diremo in modo esplicito di spostarlo.
 
Pertanto, se abbiamo inserito il nome “Gianni” per terzo, per quel che riguarda il computer quel nome rimarrà sempre in terza posizione, o almeno finché noi non gli diremo in modo esplicito di spostarlo.
  
 
+
<br/>Attenzione! Questo non è vero per la rubrica del cellulare perché lì il programma è stato pensato apposta per tenere i nomi in ordine alfabetico. Anche questo si può fare, ovviamente, ossia si può creare una funzione che fa in modo che, via via che si inseriscono i nomi, vengano subito spostati nella posizione corretta secondo l’alfabeto.
Attenzione! Questo non è vero per la rubrica del cellulare perché lì il programma è stato pensato apposta per tenere i nomi in ordine alfabetico. Anche questo si può fare, ovviamente, ossia si può creare una funzione che fa in modo che, via via che si inseriscono i nomi, vengano subito spostati nella posizione corretta secondo l’alfabeto.
+
  
 
Quel che è importante tenere presente, però, è che bisogna specificare al computer di compiere questa azione, altrimenti lui non la farà: terrà gli oggetti nella sequenza in cui li abbiamo inseriti anche se noi non abbiamo usato nessun criterio.
 
Quel che è importante tenere presente, però, è che bisogna specificare al computer di compiere questa azione, altrimenti lui non la farà: terrà gli oggetti nella sequenza in cui li abbiamo inseriti anche se noi non abbiamo usato nessun criterio.
  
 
+
<br/>Perché specifico tutto questo? Perché, se ci riflettete un secondo, questo implica una cosa importante: il computer usa un ordine interno per tenere in memoria i dati che gli passiamo in una lista.
Perché specifico tutto questo? Perché, se ci riflettete un secondo, questo implica una cosa importante: il computer usa un ordine interno per tenere in memoria i dati che gli passiamo in una lista.
+
  
 
In altre parole, quando scriviamo i nomi dei nostri amici, lui non memorizza in maniera confusa: «Che ha detto? Mario? Mario, okay. E poi? Maria? Mario o Maria? Si sarà mica sbagliato? E Gianna? E poi Gianni? Ma si chiamano tutti nella stessa maniera?»
 
In altre parole, quando scriviamo i nomi dei nostri amici, lui non memorizza in maniera confusa: «Che ha detto? Mario? Mario, okay. E poi? Maria? Mario o Maria? Si sarà mica sbagliato? E Gianna? E poi Gianni? Ma si chiamano tutti nella stessa maniera?»
Riga 684: Riga 593:
 
Gianna → posizione numero 4
 
Gianna → posizione numero 4
  
 
+
<br/>Secondo voi questo significa che c’è un numero associato a ogni nome?
Secondo voi questo significa che c’è un numero associato a ogni nome?
+
  
 
Beh, per ora diciamo di sì, anche se più avanti incontreremo delle buffe creature come gli array associativi oppure le ''list'' del C++ in cui questo numero, se esiste, per noi è irraggiungibile e non ci si può riferire ad esso per recuperare i nostri dati. Ma per ora useremo delle liste un po’ meno eccentriche che hanno sempre questo numero associato a ogni dato.
 
Beh, per ora diciamo di sì, anche se più avanti incontreremo delle buffe creature come gli array associativi oppure le ''list'' del C++ in cui questo numero, se esiste, per noi è irraggiungibile e non ci si può riferire ad esso per recuperare i nostri dati. Ma per ora useremo delle liste un po’ meno eccentriche che hanno sempre questo numero associato a ogni dato.
Riga 701: Riga 609:
 
Beh, se dei numeri sono in progressione, allora possiamo riferirci a loro dicendo: il '''primo''' della progressione, il '''secondo''' della progressione, il '''terzo''' della progressione, e così via. Sapete come si chiama questo numerino “primo”, “secondo”, “terzo”…? Eccolo lì: si chiama indice.
 
Beh, se dei numeri sono in progressione, allora possiamo riferirci a loro dicendo: il '''primo''' della progressione, il '''secondo''' della progressione, il '''terzo''' della progressione, e così via. Sapete come si chiama questo numerino “primo”, “secondo”, “terzo”…? Eccolo lì: si chiama indice.
  
 +
<br/>Ora, quelli di voi che la pensano come me si confermeranno nell’idea che i matematici sono proprio strani, ma la realtà è che gli informatici sono molto più strani di loro! Infatti i matematici si erano messi d’accordo su un punto che mi sembrerebbe molto sensato: un indice deve comunque essere superiore a zero. Ossia, quando si chiamano i numeri della progressione non si può dire “lo zeeresimo della progressione”, ma bisogna cominciare con “primo”!
  
Ora, quelli di voi che la pensano come me si confermeranno nell’idea che i matematici sono proprio strani, ma la realtà è che gli informatici sono molto più strani di loro! Infatti i matematici si erano messi d’accordo su un punto che mi sembrerebbe molto sensato: un indice deve comunque essere superiore a zero. Ossia, quando si chiamano i numeri della progressione non si può dire “lo zeeresimo della progressione”, ma bisogna cominciare con “primo”!
+
Quando sono arrivati gli informatici (ossia quelli che traducono ''string'' con stringa, tanto per intenderci) hanno deciso che questo limite era inutile. «&nbsp;Ma no!» si sono detti. «Le nostre liste inizieranno con 0!» ''Et voilà'', a noi ci tocca prenderle così.
 
+
Quando sono arrivati gli informatici (ossia quelli che traducono ''string'' con stringa, tanto per intenderci) hanno deciso che questo limite era inutile. « Ma no!» si sono detti. «Le nostre liste inizieranno con 0!» ''Et voilà'', a noi ci tocca prenderle così.
+
 
+
  
La conclusione è che prima non ho scritto una cosa corretta. Il computer memorizzerà i dati che gli passiamo in questa maniera:
+
<br/>La conclusione è che prima non ho scritto una cosa corretta. Il computer memorizzerà i dati che gli passiamo in questa maniera:
  
 
Mario → posizione numero 0
 
Mario → posizione numero 0
Riga 717: Riga 623:
 
Gianna → posizione numero 3
 
Gianna → posizione numero 3
  
 +
<br/>A questo punto sappiamo che:
  
A questo punto sappiamo che:
+
*in ogni lista c’è un numero associato a ogni dato che inseriamo;
 
+
*quel numero si chiama indice;
* in ogni lista c’è un numero associato a ogni dato che inseriamo;
+
*l’indice parte da 0, e non da 1 come molti potrebbero aspettarsi.
* quel numero si chiama indice;
+
* l’indice parte da 0, e non da 1 come molti potrebbero aspettarsi.
+
  
 
Bene, ma come ci aiuta tutto ciò a scoprire se un nome si trova nella lista o no?
 
Bene, ma come ci aiuta tutto ciò a scoprire se un nome si trova nella lista o no?
Riga 730: Riga 635:
 
Ora dovete sapere che esiste un’istruzione che dice al computer: compi questa operazione, sempre la stessa, un certo numero di volte. Quindi noi possiamo scorrere la lista tramite questa istruzione in questo modo:
 
Ora dovete sapere che esiste un’istruzione che dice al computer: compi questa operazione, sempre la stessa, un certo numero di volte. Quindi noi possiamo scorrere la lista tramite questa istruzione in questo modo:
  
# definisci una variabile che sia 0, chiamiamola ''indice'' per ricordarci a cosa serve;
+
#definisci una variabile che sia 0, chiamiamola ''indice'' per ricordarci a cosa serve;
# definisci una variabile che sia 0; chiamiamola ''risultato'';
+
#definisci una variabile che sia 0; chiamiamola ''risultato'';#CONFRONTA il contenuto della lista alla posizione ''indice'' con la risposta dell’utente;
# CONFRONTA il contenuto della lista alla posizione ''indice'' con la risposta dell’utente;
+
#SE il contenuto è uguale, allora cambia ''risultato'' in 1;
# SE il contenuto è uguale, allora cambia ''risultato'' in 1;
+
#aumenta il valore di ''indice'' di 1, in modo da passare alla posizione successiva;
# aumenta il valore di ''indice'' di 1, in modo da passare alla posizione successiva;
+
#riparti dal punto 1.
# riparti dal punto 1.
+
  
 
Secondo voi siamo in grado di scrivere un programma del genere?
 
Secondo voi siamo in grado di scrivere un programma del genere?
Riga 741: Riga 645:
 
Proviamo in JavaScript:
 
Proviamo in JavaScript:
  
 
+
<br/>'''1) definisci una variabile che sia 0, chiamiamola ''indice'''''
'''1) definisci una variabile che sia 0, chiamiamola ''indice'''''
+
 
+
 
<pre>var indice = 0;</pre>
 
<pre>var indice = 0;</pre>
 
+
<br/>'''2) definisci una variabile che sia 0; chiamiamola risultato;'''
 
+
'''2) definisci una variabile che sia 0; chiamiamola risultato;'''
+
 
+
 
<pre>var risultato = 0;</pre>
 
<pre>var risultato = 0;</pre>
 
+
<br/>'''3) CONFRONTA il contenuto della lista alla posizione indice con la risposta dell’utente;'''
 
+
'''3) CONFRONTA il contenuto della lista alla posizione indice con la risposta dell’utente;'''
+
  
 
Qui bisogna conoscere la sintassi. Mettiamo che la lista si chiami “amici”; per riferirci all’indice della lista bisogna usare le parentesi quadre, in questo modo:
 
Qui bisogna conoscere la sintassi. Mettiamo che la lista si chiami “amici”; per riferirci all’indice della lista bisogna usare le parentesi quadre, in questo modo:
 
 
<pre>amici[]</pre>
 
<pre>amici[]</pre>
 
 
Quindi la prima posizione di Amici (ricordiamoci che la prima posizione è 0!) sarà:
 
Quindi la prima posizione di Amici (ricordiamoci che la prima posizione è 0!) sarà:
 
 
<pre>amici[0]</pre>
 
<pre>amici[0]</pre>
 
 
La seconda posizione sarà:
 
La seconda posizione sarà:
 
 
<pre>amici[1]</pre>
 
<pre>amici[1]</pre>
 
 
eccetera.
 
eccetera.
  
 
Quindi, per dire «la posizione indicata dal valore della variabile indice», bisognerà scrivere:
 
Quindi, per dire «la posizione indicata dal valore della variabile indice», bisognerà scrivere:
 
 
<pre>amici[indice]</pre>
 
<pre>amici[indice]</pre>
 
 
Come vedete è piuttosto semplice. A questo punto possiamo occuparci dell’istruzione CONFRONTA. Se partiamo dall’ultimo programmino che abbiamo scritto, la risposta dell’utente era contenuta nella variabile ''persona'', per cui:
 
Come vedete è piuttosto semplice. A questo punto possiamo occuparci dell’istruzione CONFRONTA. Se partiamo dall’ultimo programmino che abbiamo scritto, la risposta dell’utente era contenuta nella variabile ''persona'', per cui:
 
 
<pre>amici[indice] == persona</pre>
 
<pre>amici[indice] == persona</pre>
 
+
<br/>'''4) SE il contenuto è uguale, allora cambia risultato in 1;'''
 
+
'''4) SE il contenuto è uguale, allora cambia risultato in 1;'''
+
 
+
 
<pre>if ( amici[indice] == persona ) {
 
<pre>if ( amici[indice] == persona ) {
 
   risultato = 1;
 
   risultato = 1;
 
</pre>
 
</pre>
 
+
<br/>'''5) aumenta il valore di indice di 1, in modo da passare alla posizione successiva;'''
 
+
'''5) aumenta il valore di indice di 1, in modo da passare alla posizione successiva;'''
+
  
 
Questo si scrive in maniera un po’ ridicola, ma va preso così com’è:
 
Questo si scrive in maniera un po’ ridicola, ma va preso così com’è:
 
 
<pre>indice = indice + 1;</pre>
 
<pre>indice = indice + 1;</pre>
 
+
<br/>'''riparti dal punto 1.'''
 
+
'''riparti dal punto 1.'''
+
  
 
Bene, questo ancora non lo sappiamo scrivere perché non abbiamo ancora parlato dell’istruzione che ci consente di ripetere lo stesso blocco di codice un certo numero di volte. Quest’istruzione si chiama ''for loop'' ed è arrivato il momento di andarla a conoscere.
 
Bene, questo ancora non lo sappiamo scrivere perché non abbiamo ancora parlato dell’istruzione che ci consente di ripetere lo stesso blocco di codice un certo numero di volte. Quest’istruzione si chiama ''for loop'' ed è arrivato il momento di andarla a conoscere.
  
 
+
<br/>A questo punto ci possiamo sbizzarrire con la versione con gli array. Ricordiamoci però di pronunciarli /əˈreɪ/ (ossia all’incirca come se in italiano fossero scritti eréi). Ecco il nostro codice:
A questo punto ci possiamo sbizzarrire con la versione con gli array. Ricordiamoci però di pronunciarli /əˈreɪ/ (ossia all’incirca come se in italiano fossero scritti eréi). Ecco il nostro codice:
+
 
+
 
<pre>function cambioTesto(){
 
<pre>function cambioTesto(){
 
     var utente = document.getElementById("risposta").value;
 
     var utente = document.getElementById("risposta").value;
Riga 824: Riga 702:
 
}
 
}
 
</pre>
 
</pre>
 
 
L’unica parte che potrebbe risultare misteriosa è come si scrive l’istruzione for. In effetti merita qualche chiarimento.
 
L’unica parte che potrebbe risultare misteriosa è come si scrive l’istruzione for. In effetti merita qualche chiarimento.
  
Riga 831: Riga 708:
 
Di solito servono tre cose (a dire il vero non sono sempre tutte e tre obbligatorie):
 
Di solito servono tre cose (a dire il vero non sono sempre tutte e tre obbligatorie):
  
# una condizione iniziale – nel nostro caso, si parte da 0;
+
#una condizione iniziale – nel nostro caso, si parte da 0;
# una condizione finale – nel nostro caso poniamo la condizione che il valore della variabile ''indice'' non abbia superato la dimensione (''length'') della lista, ossia ''indice'' deve essere minore (‘<’) della lunghezza della lista;
+
#una condizione finale – nel nostro caso poniamo la condizione che il valore della variabile ''indice'' non abbia superato la dimensione (''length'') della lista, ossia ''indice'' deve essere minore (‘<’) della lunghezza della lista;
# un’istruzione per decidere qual è il passo successivo – nel nostro caso, il valore di ''indice'' deve crescere continuamente di 1 per passare alla posizione successiva della lista.
+
#un’istruzione per decidere qual è il passo successivo – nel nostro caso, il valore di ''indice'' deve crescere continuamente di 1 per passare alla posizione successiva della lista.
  
 
Il codice che deve essere ripetuto deve essere contenuto tra parentesi graffe.
 
Il codice che deve essere ripetuto deve essere contenuto tra parentesi graffe.
  
 
+
<br/>''for'' può non essere subito chiara, perciò cercheremo di trovare altri esempi in cui usarla.
''for'' può non essere subito chiara, perciò cercheremo di trovare altri esempi in cui usarla.
+
  
 
Adesso però diamo un’occhiata a come si creano gli array nel JavaScript. Come vedete la sintassi è ispirata a quella della dichiarazione di variabile:
 
Adesso però diamo un’occhiata a come si creano gli array nel JavaScript. Come vedete la sintassi è ispirata a quella della dichiarazione di variabile:
 
 
<pre>var amici = ["Mario", "Maria", "Gianni", "Gianna"];</pre>
 
<pre>var amici = ["Mario", "Maria", "Gianni", "Gianna"];</pre>
 
 
Mi sembra piuttosto semplice: si scrivono i valori che si vogliono inserire usando una virgola per separarli. Il gruppo dei valori deve stare fra parentesi quadre.
 
Mi sembra piuttosto semplice: si scrivono i valori che si vogliono inserire usando una virgola per separarli. Il gruppo dei valori deve stare fra parentesi quadre.
  
 +
<br/>Adesso finalmente prendiamo il volo verso il C++.
  
Adesso finalmente prendiamo il volo verso il C++.
 
  
  
 
== Il bello di stare fra amici ==
 
== Il bello di stare fra amici ==
Il codice C++ si presenta subito con un’altra grana da risolvere, quindi tanto vale levarsi subito il dente:
 
  
 +
Il codice C++ si presenta subito con un’altra grana da risolvere, quindi tanto vale levarsi subito il dente:
 
<pre>#include <iostream>
 
<pre>#include <iostream>
  
Riga 897: Riga 771:
 
}
 
}
 
</pre>
 
</pre>
 
 
Cominciamo dagli aspetti più… innocui.
 
Cominciamo dagli aspetti più… innocui.
  
 
+
<br/><u>'''string amici[] = { "Mario", "Maria", "Gianni", "Gianna" };'''</u>
'''string amici[] = { "Mario", "Maria", "Gianni", "Gianna" };'''
+
  
 
Come possiamo vedere. il C++ insiste con la sua ‘pignoleria’: giacché un array è qualcosa di molto diverso da una variabile, non ammette che lo si possa definire usando la stessa sintassi che si usa per le variabili; al contrario, pretende che si specifichi con chiarezza che noi vogliamo '''davvero''' un array usando, dopo il nome, il simbolo ‘[]’.
 
Come possiamo vedere. il C++ insiste con la sua ‘pignoleria’: giacché un array è qualcosa di molto diverso da una variabile, non ammette che lo si possa definire usando la stessa sintassi che si usa per le variabili; al contrario, pretende che si specifichi con chiarezza che noi vogliamo '''davvero''' un array usando, dopo il nome, il simbolo ‘[]’.
Riga 909: Riga 781:
 
C’è da dire, d’altro canto, che il C++ ha una sua coerenza interna perché i blocchi di codice sono sempre identificati dalle parentesi graffe e anche in questo caso non si rinvengono eccezioni.
 
C’è da dire, d’altro canto, che il C++ ha una sua coerenza interna perché i blocchi di codice sono sempre identificati dalle parentesi graffe e anche in questo caso non si rinvengono eccezioni.
  
 
+
<br/><u>'''int amici_length = sizeof(amici) / sizeof(amici[0]);'''</u>
'''int amici_length = sizeof(amici) / sizeof(amici[0]);'''
+
  
 
Questa è la parte che mi aspetto risulti più oscura.
 
Questa è la parte che mi aspetto risulti più oscura.
Riga 922: Riga 793:
 
Arrivati al C++ ci imbattiamo in una sorpresa: nel C++ '''non''' c’è la parolina magica ''length''.
 
Arrivati al C++ ci imbattiamo in una sorpresa: nel C++ '''non''' c’è la parolina magica ''length''.
  
 
+
<br/>«Ma come?» direte voi. «L’abbiamo usata poco tempo fa per ''string''!»
«Ma come?» direte voi. «L’abbiamo usata poco tempo fa per ''string''!»
+
  
 
Esatto, ma come vi dicevo il C++ è pignolo: chi ha scritto il codice per ''string'' ha previsto anche una funzione ''length()'' per ''string'', e chi ha scritto il codice per gli array non ha previsto una funzione equivalente. E il C++ non consente di prendere la funzione scritta per string e attaccarla a array.
 
Esatto, ma come vi dicevo il C++ è pignolo: chi ha scritto il codice per ''string'' ha previsto anche una funzione ''length()'' per ''string'', e chi ha scritto il codice per gli array non ha previsto una funzione equivalente. E il C++ non consente di prendere la funzione scritta per string e attaccarla a array.
Riga 929: Riga 799:
 
Spiacente. Non c’è e basta.
 
Spiacente. Non c’è e basta.
  
 
+
<br/>Un attimo, però, sennò tra un po’ non ci capiamo più. Vi ricordate come si usava length() per string? Si usava così:
Un attimo, però, sennò tra un po’ non ci capiamo più. Vi ricordate come si usava length() per string? Si usava così:
+
 
+
 
<pre>string.length()</pre>
 
<pre>string.length()</pre>
 
 
ossia, attaccandole tramite un punto.
 
ossia, attaccandole tramite un punto.
  
 
Quel punto sta a significare qualcosa di particolare, ossia vuol dire che ''length()'' non è una funzione che si può usare ovunque, bensì è una funzione che si può applicare '''soltanto''' a ''string''. È stata scritta, si può dire, su misura. Infatti abbiamo detto che è sì una funzione, ma di solito questo tipo di funzioni vengono chiamate '''''metodi''''', così non facciamo confusione. In particolare, si dice che ''length()'' è un metodo di ''string'', e in questa maniera si chiarisce che si può ‘attaccare’ solo a una variabile di tipo ''string''.
 
Quel punto sta a significare qualcosa di particolare, ossia vuol dire che ''length()'' non è una funzione che si può usare ovunque, bensì è una funzione che si può applicare '''soltanto''' a ''string''. È stata scritta, si può dire, su misura. Infatti abbiamo detto che è sì una funzione, ma di solito questo tipo di funzioni vengono chiamate '''''metodi''''', così non facciamo confusione. In particolare, si dice che ''length()'' è un metodo di ''string'', e in questa maniera si chiarisce che si può ‘attaccare’ solo a una variabile di tipo ''string''.
  
 +
<br/>Andando avanti troveremo un sacco di paroline magiche con i loro metodi e qualche volta li attaccheremo con un punto e altre volte con la buffa combinazione ‘->’ (es., string->length()), ma ora ne sappiamo ancora troppo poco per avventurarci in questo terreno.
  
Andando avanti troveremo un sacco di paroline magiche con i loro metodi e qualche volta li attaccheremo con un punto e altre volte con la buffa combinazione ‘->’ (es., string->length()), ma ora ne sappiamo ancora troppo poco per avventurarci in questo terreno.
+
<br/>Lasciatemi finire il discorso sul pezzo di codice che abbiamo fra le mani e dopo andremo a sviscerare un po’ di misteri su queste paroline magiche e sui loro metodi e ci faremo domande del tipo: «Ma perché, se sono sempre metodi, ossia un particolare tipo di funzioni, nel C++ si deve scrivere ''length()'' e in JavaScript si scrive ''length''? Non bisogna mettere la parentesi tonda dopo il nome di funzione anche in JavaScript?»
 
+
 
+
Lasciatemi finire il discorso sul pezzo di codice che abbiamo fra le mani e dopo andremo a sviscerare un po’ di misteri su queste paroline magiche e sui loro metodi e ci faremo domande del tipo: «Ma perché, se sono sempre metodi, ossia un particolare tipo di funzioni, nel C++ si deve scrivere ''length()'' e in JavaScript si scrive ''length''? Non bisogna mettere la parentesi tonda dopo il nome di funzione anche in JavaScript?»
+
 
+
  
Abbiamo detto che in C++ non c’è un metodo per sapere quanti dati sono contenuti in un array. In questo caso noi sappiamo che sono 4, ma se è per questo sappiamo già che cosa c’è contenuto dentro. Di solito chi scrive un programma non ha tutte queste informazioni disponibili. Ad esempio, la lista dei nomi potrebbe arrivare da un database o da un’altra funzione e noi non sapremmo né quanti sono né quali sono.
+
<br/>Abbiamo detto che in C++ non c’è un metodo per sapere quanti dati sono contenuti in un array. In questo caso noi sappiamo che sono 4, ma se è per questo sappiamo già che cosa c’è contenuto dentro. Di solito chi scrive un programma non ha tutte queste informazioni disponibili. Ad esempio, la lista dei nomi potrebbe arrivare da un database o da un’altra funzione e noi non sapremmo né quanti sono né quali sono.
  
 
Il nostro obiettivo è quello di scrivere un codice che funzioni ''sempre'', non solo quando abbiamo tutta la pappa scodellata.
 
Il nostro obiettivo è quello di scrivere un codice che funzioni ''sempre'', non solo quando abbiamo tutta la pappa scodellata.
Riga 951: Riga 815:
 
Perciò ora ci dobbiamo inventare un sistema per scoprire quanto è grande questo array (ossia quanti dati contiene).
 
Perciò ora ci dobbiamo inventare un sistema per scoprire quanto è grande questo array (ossia quanti dati contiene).
  
 
+
<br/>Facciamo un esempio un po’ assurdo. Mettiamo che un giorno, per scommessa, dobbiate scoprire quanti piani ci sono dentro un’antica torre medioevale. Vi recate a darle un’occhiata e vi scoraggiate subito: la torre è altissima e senza finestre e avete scommesso che riuscirete a scoprirlo senza entrarci dentro. E non vi potete mica arrampicare lungo il muro!
Facciamo un esempio un po’ assurdo. Mettiamo che un giorno, per scommessa, dobbiate scoprire quanti piani ci sono dentro un’antica torre medioevale. Vi recate a darle un’occhiata e vi scoraggiate subito: la torre è altissima e senza finestre e avete scommesso che riuscirete a scoprirlo senza entrarci dentro. E non vi potete mica arrampicare lungo il muro!
+
  
 
Come potete fare a scoprirlo?
 
Come potete fare a scoprirlo?
  
Per fortuna in quel momento incrociate la vostra amica Leonilda, la quale vi saluta: « Ciao! Cosa ci fai qui?»
+
Per fortuna in quel momento incrociate la vostra amica Leonilda, la quale vi saluta: «&nbsp;Ciao! Cosa ci fai qui?»
  
 
A quel punto le spiegate che dovete scoprire quanti piani ha la torre, ma non sapete come fare.
 
A quel punto le spiegate che dovete scoprire quanti piani ha la torre, ma non sapete come fare.
Riga 964: Riga 827:
 
E in effetti subito intuite che la soluzione è
 
E in effetti subito intuite che la soluzione è
  
Numero di piani = Torre : Leonilda
+
Numero di piani = Torre&nbsp;: Leonilda
  
 
e in pochi secondi riuscite a calcolare:
 
e in pochi secondi riuscite a calcolare:
  
Numero di piani = 54,4 m : 1,60 m = 5540 cm : 160 cm = 34 piani
+
Numero di piani = 54,4 m&nbsp;: 1,60 m = 5540 cm&nbsp;: 160 cm = 34 piani
 
+
  
Beh, non è stato difficile, ma ora applichiamo lo stesso ragionamento qui.
+
<br/>Beh, non è stato difficile, ma ora applichiamo lo stesso ragionamento qui.
  
 
Il C++ ci offre uno strumento comodo: ''sizeof''.
 
Il C++ ci offre uno strumento comodo: ''sizeof''.
Riga 979: Riga 841:
 
Stare a definire cos’è un byte non credo ci servirebbe a molto ora, mentre invece ci è utile sapere che ''sizeof'' ci informa su quanti byte vengono occupati da cose come gli array.
 
Stare a definire cos’è un byte non credo ci servirebbe a molto ora, mentre invece ci è utile sapere che ''sizeof'' ci informa su quanti byte vengono occupati da cose come gli array.
  
 +
<br/>A questo punto, se scriviamo ''sizeof(amici)'', possiamo scoprire quanti byte totali di memoria sono occupati dall’array ''amici''. Questo è un po’ come sapere l’altezza della torre.
  
A questo punto, se scriviamo ''sizeof(amici)'', possiamo scoprire quanti byte totali di memoria sono occupati dall’array ''amici''. Questo è un po’ come sapere l’altezza della torre.
+
<br/>Se invece scriviamo ''sizeof(amici[0])'' scopriamo quanti byte sono occupati da un singolo dato inserito nell’array; nel caso particolare, il primo, quello in posizione 0 – ma noi abbiamo imparato che si dice “con indice 0”. Ma che sia il primo o l’ultimo o uno a caso non ha rilevanza: in un array tutti i dati occupano lo stesso spazio di memoria; visto che la maggior parte delle volte non siamo sicuri di quanti dati abbiamo nell’array, conviene riferirsi a quello in posizione 0, partendo dal presupposto che, se uno ha dichiarato un array, almeno un dato ce l’avrà messo!
 
+
 
+
Se invece scriviamo ''sizeof(amici[0])'' scopriamo quanti byte sono occupati da un singolo dato inserito nell’array; nel caso particolare, il primo, quello in posizione 0 – ma noi abbiamo imparato che si dice “con indice 0”. Ma che sia il primo o l’ultimo o uno a caso non ha rilevanza: in un array tutti i dati occupano lo stesso spazio di memoria; visto che la maggior parte delle volte non siamo sicuri di quanti dati abbiamo nell’array, conviene riferirsi a quello in posizione 0, partendo dal presupposto che, se uno ha dichiarato un array, almeno un dato ce l’avrà messo!
+
  
 
Comunque sia, quale che misuriamo, otterremo l’equivalente dell’altezza di un piano della torre.
 
Comunque sia, quale che misuriamo, otterremo l’equivalente dell’altezza di un piano della torre.
  
 
+
<br/>Quindi non ci resta che compiere la stessa operazione di prima, dividere l’altezza della torre per l’altezza di un piano e troveremo il numero dei piani.
Quindi non ci resta che compiere la stessa operazione di prima, dividere l’altezza della torre per l’altezza di un piano e troveremo il numero dei piani.
+
  
 
Parlando di array, dividendo la lunghezza complessiva in byte di un array per la lunghezza di un singolo dato otteniamo il numero dei dati contenuti.
 
Parlando di array, dividendo la lunghezza complessiva in byte di un array per la lunghezza di un singolo dato otteniamo il numero dei dati contenuti.
  
 +
<br/>E questo è il significato di questa riga. ''By the way'', il simbolo ‘/’ in questo caso significa DIVIDI.
  
E questo è il significato di questa riga. ''By the way'', il simbolo ‘/’ in questo caso significa DIVIDI.
+
<br/>Il risultato della divisione viene immagazzinato nella variabile ''amici_length'' (l’ho chiamata così perché fosse chiaro a cosa doveva servire).
  
 +
<br/>Beh, questo era lo soglio più grosso che dovevamo affrontare; superato questo, direi che il codice C++ è praticamente uguale a quello JavaScript.
  
Il risultato della divisione viene immagazzinato nella variabile ''amici_length'' (l’ho chiamata così perché fosse chiaro a cosa doveva servire).
 
  
  
Beh, questo era lo soglio più grosso che dovevamo affrontare; superato questo, direi che il codice C++ è praticamente uguale a quello JavaScript.
+
=== Una lista un po’ più simpatica ===
  
 
=== Una lista un po’ più simpatica ===
 
 
A questo punto, se dovessi fare un tutorial molto serioso sul C++, dovrei soffermarmi un sacco su una novità come gli array e mostrare sia l’utilità che hanno, sia i limiti che delle volte presentano. Per non parlare poi dell’istruzione for, di cui bisogna portare almeno un altro paio di esempi se vogliamo essere sicuri di averla domata.
 
A questo punto, se dovessi fare un tutorial molto serioso sul C++, dovrei soffermarmi un sacco su una novità come gli array e mostrare sia l’utilità che hanno, sia i limiti che delle volte presentano. Per non parlare poi dell’istruzione for, di cui bisogna portare almeno un altro paio di esempi se vogliamo essere sicuri di averla domata.
  
 
+
<br/>Ma il mio intento non è certo quello di dire tutto. Ci sono fior fiore di manuali, scritti da gente molto, ma molto più competente di me sul C++, e sopra tutto ci sono i mentor al vostro fianco, che sono lì per aiutarvi nei dettagli che non riusciamo a affrontare. Il mio scopo è più quello di essere chiaro che non di essere esaustivo.
Ma il mio intento non è certo quello di dire tutto. Ci sono fior fiore di manuali, scritti da gente molto, ma molto più competente di me sul C++, e sopra tutto ci sono i mentor al vostro fianco, che sono lì per aiutarvi nei dettagli che non riusciamo a affrontare. Il mio scopo è più quello di essere chiaro che non di essere esaustivo.
+
  
 
Quindi voglio affrontare subito un dubbio amletico che sicuramente sta serpeggiando fra di voi, che è: «ma chi ce lo fa fare? Scratch è così chiaro e ha pure la funzione “contiene”. JavaScript come minimo non fa tanto il difficile su ''lentgh''… Ma perché perdere tempo su questa cosa cervellotica del C++?»
 
Quindi voglio affrontare subito un dubbio amletico che sicuramente sta serpeggiando fra di voi, che è: «ma chi ce lo fa fare? Scratch è così chiaro e ha pure la funzione “contiene”. JavaScript come minimo non fa tanto il difficile su ''lentgh''… Ma perché perdere tempo su questa cosa cervellotica del C++?»
Riga 1 012: Riga 869:
 
Ebbene, sono qui a sollevare il vostro spirito: gioite perché ora andiamo a recuperare ''length'' per la coda.
 
Ebbene, sono qui a sollevare il vostro spirito: gioite perché ora andiamo a recuperare ''length'' per la coda.
  
 
+
<br/>Il motivo per cui nel JavaScript si può attaccare ''length'' a un array è che nel JavaScript un array è un '''''oggetto'''''. Lo so che la parola è così comune da far sospettare che la stia usando in modo improprio, ossia come dire un affare, una cosa, una di quegli aggeggi che…
Il motivo per cui nel JavaScript si può attaccare ''length'' a un array è che nel JavaScript un array è un '''''oggetto'''''. Lo so che la parola è così comune da far sospettare che la stia usando in modo improprio, ossia come dire un affare, una cosa, una di quegli aggeggi che…
+
  
 
Invece non è così: ''oggetto'' in informatica ha un significato molto preciso, ma finché non ne creeremo uno con le nostre mani qualunque cosa dica risulterà incomprensibile. Comunque per ora fidatevi: con il termine oggetto si intende un particolare blocco di codice che ha la sua brava etichetta, un po’ come le variabili o come ''string''. Un ''oggetto'' può avere dei metodi (ricordate? Funzioni che si attaccano con un punto o con ‘->’)
 
Invece non è così: ''oggetto'' in informatica ha un significato molto preciso, ma finché non ne creeremo uno con le nostre mani qualunque cosa dica risulterà incomprensibile. Comunque per ora fidatevi: con il termine oggetto si intende un particolare blocco di codice che ha la sua brava etichetta, un po’ come le variabili o come ''string''. Un ''oggetto'' può avere dei metodi (ricordate? Funzioni che si attaccano con un punto o con ‘->’)
Riga 1 021: Riga 877:
 
Quindi nel JavaScript possiamo usare ''length'' con un array, mentre nel C++ non possiamo farlo.
 
Quindi nel JavaScript possiamo usare ''length'' con un array, mentre nel C++ non possiamo farlo.
  
 
+
<br/>Che sfortuna, vero? È una cosa triste, lo so. Bisognerebbe che anche nel C++ ci fosse un oggetto che si potesse usare come un array… Ehi, un momento! Ma c’è! Ma certo, è un ''vector''!
Che sfortuna, vero? È una cosa triste, lo so. Bisognerebbe che anche nel C++ ci fosse un oggetto che si potesse usare come un array… Ehi, un momento! Ma c’è! Ma certo, è un ''vector''!  
+
  
 
Un ''vector'' fa le stesse cose di un array, ma, signore e signori, è un oggetto.
 
Un ''vector'' fa le stesse cose di un array, ma, signore e signori, è un oggetto.
  
 
+
<br/>Non ci resta che dare un’occhiata al nuovo codice C++ e rimandare le considerazioni a dopo.
Non ci resta che dare un’occhiata al nuovo codice C++ e rimandare le considerazioni a dopo.
+
 
+
 
<pre>#include <iostream>
 
<pre>#include <iostream>
 
#include <vector>
 
#include <vector>
Riga 1 072: Riga 925:
 
}
 
}
 
</pre>
 
</pre>
 
 
Il problema di questo codice è che, se provate a compilarlo e a farlo partire, è possibile che Qt si blocchi. Ad alcuni si bloccherà e ad altri no. Coloro cui è andata bene devono portare un po’ di pazienza perché è bene risolvere questo problema fin da subito, invece che cercare di aggirarlo.
 
Il problema di questo codice è che, se provate a compilarlo e a farlo partire, è possibile che Qt si blocchi. Ad alcuni si bloccherà e ad altri no. Coloro cui è andata bene devono portare un po’ di pazienza perché è bene risolvere questo problema fin da subito, invece che cercare di aggirarlo.
  
 
Quelli cui si è bloccato dovrebbero trovarsi davanti a una schermata come questa:
 
Quelli cui si è bloccato dovrebbero trovarsi davanti a una schermata come questa:
  
 +
<br/>[[File:Qt Saluto 02 errore.png|C++ con Qt, parte II, Saluto errore]]
  
[[File:Qt_Saluto_02_errore.png|C++ con Qt, parte II, Saluto errore]]
+
<br/>Un giorno impareremo a leggere queste schermate e scopriremo che dentro sono contenute un sacco di informazioni per migliorare il codice che stiamo scrivendo, ma non è un argomento per i primi passi nel C++.
  
 
+
<br/>Il ‘padre’ del C++ è il danese Bjarne Stroustrup, il quale fin dai primi anni ottanta stava cercando di aggiungere al linguaggio C il supporto per la programmazione a oggetti. Può quindi sembrare molto vecchio, almeno nei termini dell’informatica, ma nel corso degli anni è stato soggetto a molti miglioramenti. Anche nell’ultimo decennio ha subito molte revisioni, tra cui importantissima e molto sofferta è stata quella del 2011. Pensate un po’ che la discussione se introdurre o no le novità che molti proponevano fu iniziata nel 2008, ma erano così tanti a sollevare eccezioni e dubbi che i lavori si conclusero solo 3 anni dopo, nel 2011 appunto.
Un giorno impareremo a leggere queste schermate e scopriremo che dentro sono contenute un sacco di informazioni per migliorare il codice che stiamo scrivendo, ma non è un argomento per i primi passi nel C++.
+
 
+
 
+
Il ‘padre’ del C++ è il danese Bjarne Stroustrup, il quale fin dai primi anni ottanta stava cercando di aggiungere al linguaggio C il supporto per la programmazione a oggetti. Può quindi sembrare molto vecchio, almeno nei termini dell’informatica, ma nel corso degli anni è stato soggetto a molti miglioramenti. Anche nell’ultimo decennio ha subito molte revisioni, tra cui importantissima e molto sofferta è stata quella del 2011. Pensate un po’ che la discussione se introdurre o no le novità che molti proponevano fu iniziata nel 2008, ma erano così tanti a sollevare eccezioni e dubbi che i lavori si conclusero solo 3 anni dopo, nel 2011 appunto.
+
  
 
In seguito a quella revisione, il suo stesso ideatore arrivò a dire che la trasformazione era stata tale che aveva l'impressione di lavorare con un linguaggio del tutto nuovo.
 
In seguito a quella revisione, il suo stesso ideatore arrivò a dire che la trasformazione era stata tale che aveva l'impressione di lavorare con un linguaggio del tutto nuovo.
  
 
+
<br/>Perché vi racconto questo? Per farvi inquadrare cos’è che ci blocca in questo momento. La complicazione la pone questa riga:
Perché vi racconto questo? Per farvi inquadrare cos’è che ci blocca in questo momento. La complicazione la pone questa riga:
+
 
+
 
<pre>vector<string> amici = { "Mario", "Maria", "Gianni", "Gianna" };</pre>
 
<pre>vector<string> amici = { "Mario", "Maria", "Gianni", "Gianna" };</pre>
 
+
Anche a voi quel vector&lt;string&gt; potrebbe parere un po’ strano, ma non è quello che dà fastidio a Qt. Anzi, a dire il vero non c’è niente che dia fastidio a Qt, il piccoso è il compilatore.
Anche a voi quel vector<string> potrebbe parere un po’ strano, ma non è quello che dà fastidio a Qt. Anzi, a dire il vero non c’è niente che dia fastidio a Qt, il piccoso è il compilatore.
+
  
 
Non so se vi ricordate cosa si è detto quando si è presentato Qt: durante la fase di installazione, porta con sé un compilatore. Questo dovrebbe confermarvi che Qt è un ottimo ambiente di programmazione, ma non è di per sé un compilatore; però può ‘governare’ al posto nostro il compilatore che vogliamo usare.
 
Non so se vi ricordate cosa si è detto quando si è presentato Qt: durante la fase di installazione, porta con sé un compilatore. Questo dovrebbe confermarvi che Qt è un ottimo ambiente di programmazione, ma non è di per sé un compilatore; però può ‘governare’ al posto nostro il compilatore che vogliamo usare.
Riga 1 099: Riga 945:
 
Tanto per farvelo sapere, se avete installato la versione ‘standard’ di Qt, il compilatore che si è portato appresso è l’ottimo GCC, che nella versione per Windows si chiama MinGw.
 
Tanto per farvelo sapere, se avete installato la versione ‘standard’ di Qt, il compilatore che si è portato appresso è l’ottimo GCC, che nella versione per Windows si chiama MinGw.
  
 
+
<br/>«Tutto molto bello» starete pensando. «Ma perché è di cattivo umore, questo compilatore? Perché non fa quel che deve fare e basta?»
«Tutto molto bello» starete pensando. «Ma perché è di cattivo umore, questo compilatore? Perché non fa quel che deve fare e basta?»
+
  
 
Aspettiamo a trattarlo male, perché lui sta cercando di non farci sbagliare. Il fatto è che prima della revisione del 2001 ''vector'' non ammetteva di caricare i dati da un blocco fra parentesi graffe come fa un array. Bisognava usare un’altra sintassi con molte più righe da digitare.
 
Aspettiamo a trattarlo male, perché lui sta cercando di non farci sbagliare. Il fatto è che prima della revisione del 2001 ''vector'' non ammetteva di caricare i dati da un blocco fra parentesi graffe come fa un array. Bisognava usare un’altra sintassi con molte più righe da digitare.
Riga 1 112: Riga 957:
 
Per questo i creatori di GCC hanno deciso di fare in modo che al compilatore possa essere detto: questo codice qui lo compili secondo le regole che erano in vigore prima del 2011, e quest’altro codice secondo quelle dal 2011 in poi.
 
Per questo i creatori di GCC hanno deciso di fare in modo che al compilatore possa essere detto: questo codice qui lo compili secondo le regole che erano in vigore prima del 2011, e quest’altro codice secondo quelle dal 2011 in poi.
  
 +
<br/>Noi scriveremo tutto codice compatibile con le regole dal 2011 in poi, quindi ora ci basta informare il compilatore e la situazione si sbloccherà.
  
Noi scriveremo tutto codice compatibile con le regole dal 2011 in poi, quindi ora ci basta informare il compilatore e la situazione si sbloccherà.
+
<br/>Orbene, informare il compilatore non è difficile, ma noi perché dovremmo stare a domandarci come si fa? Non si è detto che Qt lo può governare per noi? È ovvio che può!
 
+
 
+
Orbene, informare il compilatore non è difficile, ma noi perché dovremmo stare a domandarci come si fa? Non si è detto che Qt lo può governare per noi? È ovvio che può!
+
  
 
È ora di scoprire cosa possono fare per noi quei file ‘in più’ che ci siamo ritrovati fra i piedi oltre al nostro ''main.cpp''.
 
È ora di scoprire cosa possono fare per noi quei file ‘in più’ che ci siamo ritrovati fra i piedi oltre al nostro ''main.cpp''.
Riga 1 122: Riga 965:
 
A noi interessa il file ''Saluto.pro'', per cui coraggio: fateci doppio click sopra ed apritelo:
 
A noi interessa il file ''Saluto.pro'', per cui coraggio: fateci doppio click sopra ed apritelo:
  
 +
<br/>[[File:Qt Saluto 03 trovapro freccia.png|C++ con Qt, parte II, Saluto freccia]]
  
[[File:Qt_Saluto_03_trovapro_freccia.png|C++ con Qt, parte II, Saluto freccia]]
+
<br/>Come vedete il file si apre nella colonna di destra, andando per il momento a coprire il contenuto di ''main.cpp''. Questa è una funzione molto comoda di Qt: i file si aprono uno sopra all’altro, di modo che possiamo recuperare il sottostante in ogni momento. Ancora non abbiamo cominciato a lavorare con più file contemporaneamente, però, per cui per recuperare main.cpp dovremo – DOPO, NON ORA! – fare doppio click sul suo nome.
 
+
 
+
Come vedete il file si apre nella colonna di destra, andando per il momento a coprire il contenuto di ''main.cpp''. Questa è una funzione molto comoda di Qt: i file si aprono uno sopra all’altro, di modo che possiamo recuperare il sottostante in ogni momento. Ancora non abbiamo cominciato a lavorare con più file contemporaneamente, però, per cui per recuperare main.cpp dovremo – DOPO, NON ORA! – fare doppio click sul suo nome.
+
 
+
 
+
Adesso, '''sotto''' la riga:
+
  
 +
<br/>Adesso, '''sotto''' la riga:
 
<pre>CONFIG -= qt</pre>
 
<pre>CONFIG -= qt</pre>
 
 
dobbiamo scrivere la seguente:
 
dobbiamo scrivere la seguente:
 
 
<pre>CONFIG += c++11</pre>
 
<pre>CONFIG += c++11</pre>
 
 
di modo che il file venga così:
 
di modo che il file venga così:
  
 +
<br/>[[File:Qt Saluto 04 c++11.png|C++ con Qt, parte II, Saluto c++11]]
  
[[File:Qt_Saluto_04_c++11.png|C++ con Qt, parte II, Saluto c++11]]
+
<br/>Per far riapparire il contenuto di main.cpp, fate doppio click sul suo nome. Poi compilate ed eseguite: adesso dovrebbe andare tutto liscio.
  
 +
<br/>RICORDATEVI QUESTI PASSAGGI PERCHÉ DOVREMO COMPIERLI PER OGNI PROGETTO DI QT! (almeno per ora)
  
Per far riapparire il contenuto di main.cpp, fate doppio click sul suo nome. Poi compilate ed eseguite: adesso dovrebbe andare tutto liscio.
+
<br/>Dicevamo che l’istruzione
 
+
 
+
RICORDATEVI QUESTI PASSAGGI PERCHÉ DOVREMO COMPIERLI PER OGNI PROGETTO DI QT! (almeno per ora)
+
 
+
 
+
Dicevamo che l’istruzione
+
 
+
 
<pre>vector<string> amici…</pre>
 
<pre>vector<string> amici…</pre>
 
 
potrebbe causare un po’ di perplessità a qualcuno, e sarebbe comprensibile. In realtà non c’è niente di complicato. Confrontiamola con l’istruzione equivalente che fa uso degli array:
 
potrebbe causare un po’ di perplessità a qualcuno, e sarebbe comprensibile. In realtà non c’è niente di complicato. Confrontiamola con l’istruzione equivalente che fa uso degli array:
 
 
<pre>string amici[] …</pre>
 
<pre>string amici[] …</pre>
 
 
A ben guardare le due scritte sono equivalenti, giacché contengono le stesse istruzioni, anche se scritte in ordine diverso:
 
A ben guardare le due scritte sono equivalenti, giacché contengono le stesse istruzioni, anche se scritte in ordine diverso:
  
# il nome della nostra variabile è sempre ‘amici’;
+
#il nome della nostra variabile è sempre ‘amici’;
# si tratta sempre di una variabile di tipo ''string'';
+
#si tratta sempre di una variabile di tipo ''string'';#l’unica differenza è in come si dichiara un array (‘[]’) e in come si dichiara un ''vector'' (‘vector<>’).
# l’unica differenza è in come si dichiara un array (‘[]’) e in come si dichiara un ''vector'' (‘vector<>’).
+
 
+
I ''vector'' sono oggetti di un tipo particolare, detti ''template'', i quali hanno la caratteristica di potersi adattare a diversi tipi di dati. Quindi noi avremmo potuto avere un ''vector'' di ''string'' come un ''vector'' di ''int'' e non sarebbe cambiato di una virgola il modo di usarli, solo che la dichiarazione iniziale sarebbe stata ''vector<int> amici''. Nel caso fosse stato un array, invece, avremmo scritto ''int amici[]''.
+
  
 +
I ''vector'' sono oggetti di un tipo particolare, detti ''template'', i quali hanno la caratteristica di potersi adattare a diversi tipi di dati. Quindi noi avremmo potuto avere un ''vector'' di ''string'' come un ''vector'' di ''int'' e non sarebbe cambiato di una virgola il modo di usarli, solo che la dichiarazione iniziale sarebbe stata ''vector&lt;int&gt; amici''. Nel caso fosse stato un array, invece, avremmo scritto ''int amici[]''.
  
Se la differenza fra i due fosse questa, non ci sarebbero motivi per andare a cercare i nostri amici ''vector''. Il motivo per cui abbiamo voluto presentarli è che i ''vector'', come le ''string'', portano con loro un sacco di metodi già pronti e impacchettati che ci semplificano la vita, come ad esempio il metodo ''size()'' che ci ha risparmiato di scrivere un’intera riga di codice.
+
<br/>Se la differenza fra i due fosse questa, non ci sarebbero motivi per andare a cercare i nostri amici ''vector''. Il motivo per cui abbiamo voluto presentarli è che i ''vector'', come le ''string'', portano con loro un sacco di metodi già pronti e impacchettati che ci semplificano la vita, come ad esempio il metodo ''size()'' che ci ha risparmiato di scrivere un’intera riga di codice.
  
 
Rifletteteci un po’: se avessimo usato fin da subito ''vector'', non ci sarebbe stato nemmen bisogno di cominciare a parlare di torri medievali e di altezze dei piani! Gli oggetti del C++ sono lì per semplificarci le cose e possiamo cominciare a usarli senza doverli conoscere in ogni minimo dettaglio.
 
Rifletteteci un po’: se avessimo usato fin da subito ''vector'', non ci sarebbe stato nemmen bisogno di cominciare a parlare di torri medievali e di altezze dei piani! Gli oggetti del C++ sono lì per semplificarci le cose e possiamo cominciare a usarli senza doverli conoscere in ogni minimo dettaglio.
  
 
+
<br/>Pensate che Qt ci offre un oggetto ancora più amichevole: QVector. Un QVector è un oggetto della libreria Qt che potremmo considerare un ''vector'' palestrato, giacché porta con sé un altra carrellata di metodi molto utili; uno di questi è ''contains'', il quale, indovinate un po’, ci informa se il nostro QVector contiene, tra i suoi dati, quello che stiamo cercando.
Pensate che Qt ci offre un oggetto ancora più amichevole: QVector. Un QVector è un oggetto della libreria Qt che potremmo considerare un ''vector'' palestrato, giacché porta con sé un altra carrellata di metodi molto utili; uno di questi è ''contains'', il quale, indovinate un po’, ci informa se il nostro QVector contiene, tra i suoi dati, quello che stiamo cercando.
+
  
 
Il che significa che non ci sarebbe più bisogno di un ciclo ''for'' per trovarlo.
 
Il che significa che non ci sarebbe più bisogno di un ciclo ''for'' per trovarlo.
  
 
Detto in altre parole, se avessimo utilizzato un QVector tramite questa istruzione:
 
Detto in altre parole, se avessimo utilizzato un QVector tramite questa istruzione:
 
 
<pre>QVector<string> amici…</pre>
 
<pre>QVector<string> amici…</pre>
 
 
dopo avremmo potuto procedere così:
 
dopo avremmo potuto procedere così:
 
 
<pre>if ( amici.contains("Mario") || amici.contains("Maria")…</pre>
 
<pre>if ( amici.contains("Mario") || amici.contains("Maria")…</pre>
 
+
senza preoccuparci né del ciclo for né del size di vector.
senza preoccuparci né del ciclo for né del size di vector.  
+
  
 
Questo è il motivo per cui vogliamo cominciare a conoscere fin da subito gli oggetti del C++ e anche passare appena possibile a quelli di Qt.
 
Questo è il motivo per cui vogliamo cominciare a conoscere fin da subito gli oggetti del C++ e anche passare appena possibile a quelli di Qt.
  
 
+
<br/>A proposito, l’avete notato vero il rigo:
A proposito, l’avete notato vero il rigo:
+
 
+
 
<pre>#include <vector></pre>
 
<pre>#include <vector></pre>
 +
all’inizio del nostro codice? Senza quello, il codice non funziona, chissà perché…&nbsp;;-)
  
all’inizio del nostro codice? Senza quello, il codice non funziona, chissà perché… ;-)
 
  
  
 
== Oltre l’orizzonte ==
 
== Oltre l’orizzonte ==
 +
 
Se questo fosse un tutorial serio e ben strutturato ora rimarrei qui a farvi fare un sacco di prove con gli array e i ''vector'' e proverei a dimostrarvi quanti errori di programmazione si possono prevenire usando i secondi. Un’altra cosa che mi piacerebbe sottolineare è quanto l’apparente rigidità della sintassi del C++ possa contribuire a evitare errori e di come la ‘amichevolezza’ del JavaScipt possa ogni tanto nascondere trappole insidiose, ma il problema di trattare un argomento del genere è che si corre il rischio di ferire la suscettibilità di chi ama programmare in JavaScript e questo non rientra affatto fra i miei progetti. Vorrei quindi cambiare prospettiva e proporre un’altra visione: che ogni linguaggio che si usa ha i suoi pro e i suoi contro.
 
Se questo fosse un tutorial serio e ben strutturato ora rimarrei qui a farvi fare un sacco di prove con gli array e i ''vector'' e proverei a dimostrarvi quanti errori di programmazione si possono prevenire usando i secondi. Un’altra cosa che mi piacerebbe sottolineare è quanto l’apparente rigidità della sintassi del C++ possa contribuire a evitare errori e di come la ‘amichevolezza’ del JavaScipt possa ogni tanto nascondere trappole insidiose, ma il problema di trattare un argomento del genere è che si corre il rischio di ferire la suscettibilità di chi ama programmare in JavaScript e questo non rientra affatto fra i miei progetti. Vorrei quindi cambiare prospettiva e proporre un’altra visione: che ogni linguaggio che si usa ha i suoi pro e i suoi contro.
  
Riga 1 203: Riga 1 023:
  
 
Per questo gioco avremmo bisogno di 2 sprite, che io ho chiamato Giocatore1 e Giocatore2.
 
Per questo gioco avremmo bisogno di 2 sprite, che io ho chiamato Giocatore1 e Giocatore2.
 +
  
  
Riga 1 209: Riga 1 030:
 
Le variabili:
 
Le variabili:
  
 +
<br/>[[File:Scra Fiammi 01.png|C++ con Qt, parte II, Scratch Fiammiferi 01]]
  
[[File:Scra_Fiammi_01.png|C++ con Qt, parte II, Scratch Fiammiferi 01]]
+
<br/>Tenete presente che la variabile ‘presa’ dev’essere creata con una visibilità limitata al singolo ''sprite'', come si può vedere qui sotto:
  
 +
<br/>[[File:Scra Fiammi 02.png|C++ con Qt, parte II, Scratch Fiammiferi 02]]
  
Tenete presente che la variabile ‘presa’ dev’essere creata con una visibilità limitata al singolo ''sprite'', come si può vedere qui sotto:
+
<br/>La variabile ‘Fiammiferi rimasti’ potrà invece essere lasciata “per tutti gli sprites”.
 
+
 
+
[[File:Scra_Fiammi_02.png|C++ con Qt, parte II, Scratch Fiammiferi 02]]
+
 
+
 
+
La variabile ‘Fiammiferi rimasti’ potrà invece essere lasciata “per tutti gli sprites”.
+
  
 
Questo il resto del codice:
 
Questo il resto del codice:
  
 +
<br/>[[File:Scra Fiammi 03.png|C++ con Qt, parte II, Scratch Fiammiferi 03]]
  
[[File:Scra_Fiammi_03.png|C++ con Qt, parte II, Scratch Fiammiferi 03]]
 
  
  
 
==== Il codice di Giocatore2 ====
 
==== Il codice di Giocatore2 ====
 +
 
Le variabili sono esattamente le stesse di prima, punto per punto.
 
Le variabili sono esattamente le stesse di prima, punto per punto.
  
 
Il codice è composto dai seguenti spezzoni:
 
Il codice è composto dai seguenti spezzoni:
  
 +
<br/>[[File:Scra Fiammi 04.png|C++ con Qt, parte II, Scratch Fiammiferi 04]]
  
[[File:Scra_Fiammi_04.png|C++ con Qt, parte II, Scratch Fiammiferi 04]]
+
<br/>[[File:Scra Fiammi 05.png|C++ con Qt, parte II, Scratch Fiammiferi 05]]
  
 
+
<br/>Il codice Scratch è, come al solito, autoesplicativo.
[[File:Scra_Fiammi_05.png|C++ con Qt, parte II, Scratch Fiammiferi 05]]
+
 
+
 
+
Il codice Scratch è, come al solito, autoesplicativo.
+
  
 
Metto soltanto in luce che il gioco non comincia quando si preme la bandierina verde, bensì quando si preme il tasto ‘p’. In alternativa si può premere ‘s’ per avere le spiegazioni sul gioco.
 
Metto soltanto in luce che il gioco non comincia quando si preme la bandierina verde, bensì quando si preme il tasto ‘p’. In alternativa si può premere ‘s’ per avere le spiegazioni sul gioco.
  
 +
<br/>Un tutorial in C++ non si rivolge a bambini molto piccoli, ma alcuni potrebbero non aver fatto algebra, pertanto potrebbero non capire la seguente istruzione:
  
Un tutorial in C++ non si rivolge a bambini molto piccoli, ma alcuni potrebbero non aver fatto algebra, pertanto potrebbero non capire la seguente istruzione:
+
<br/>[[File:Scra Fiammi 06 moltineg.png|C++ con Qt, parte II, Scratch numero negativo]]
  
 +
<br/>Basterà dir loro che serve a trasformare ‘presa’ in un numero negativo, ma chi vuole sperticarsi in una lezione sulla moltiplicazione fra numeri positivi e negativi faccia pure&nbsp;:)
  
[[File:Scra_Fiammi_06_moltineg.png|C++ con Qt, parte II, Scratch numero negativo]]
+
<br/>Un altro punto su cui sarebbe utile soffermarsi sarebbe questo, perché ci introdurrà al meccanismo signals/slot delle librerie Qt:
  
 +
<br/>[[File:Scra Fiammi 07 segnale.png|C++ con Qt, parte II, Scratch invia segnale]]
  
Basterà dir loro che serve a trasformare ‘presa’ in un numero negativo, ma chi vuole sperticarsi in una lezione sulla moltiplicazione fra numeri positivi e negativi faccia pure :)
 
 
 
Un altro punto su cui sarebbe utile soffermarsi sarebbe questo, perché ci introdurrà al meccanismo signals/slot delle librerie Qt:
 
 
 
[[File:Scra_Fiammi_07_segnale.png|C++ con Qt, parte II, Scratch invia segnale]]
 
  
  
 
=== Cosa dire del codice? ===
 
=== Cosa dire del codice? ===
  
Va bene, lo ammetto, sono stato cattivo. Non si può vincere mai, penso ve ne siate accorti :)
+
Va bene, lo ammetto, sono stato cattivo. Non si può vincere mai, penso ve ne siate accorti&nbsp;:)
  
 
Il motivo per cui ho scelto questo gioco non è stato però per sadismo, bensì perché ci consente di introdurre un argomento che ci sta inseguendo fin dal primo tutorial: lo ''scope resolution'', espressione che fa temere il peggio, ma gode per lo meno del raro privilegio di essere di solito tradotta in maniera intelligente con “spazio di visibilità”, immagino perché, quando gli informatici hanno cercato di forzare quello ''scope'' in un qualcosa di similare in italiano, non è venuto loro in mente niente di appropriato.
 
Il motivo per cui ho scelto questo gioco non è stato però per sadismo, bensì perché ci consente di introdurre un argomento che ci sta inseguendo fin dal primo tutorial: lo ''scope resolution'', espressione che fa temere il peggio, ma gode per lo meno del raro privilegio di essere di solito tradotta in maniera intelligente con “spazio di visibilità”, immagino perché, quando gli informatici hanno cercato di forzare quello ''scope'' in un qualcosa di similare in italiano, non è venuto loro in mente niente di appropriato.
  
 +
<br/>Per capire l’argomento torniamo alle due variabili ‘presa’ che esistono nel codice e osserviamo il loro comportamento. Ci si può rendere conto rapidamente che i loro valori si ‘muovono’ in maniera indipendente fra di loro e che ci sono istruzioni, come questa
  
Per capire l’argomento torniamo alle due variabili ‘presa’ che esistono nel codice e osserviamo il loro comportamento. Ci si può rendere conto rapidamente che i loro valori si ‘muovono’ in maniera indipendente fra di loro e che ci sono istruzioni, come questa
+
<br/>[[File:Scra Fiammi 08.png|C++ con Qt, parte II, Scratch variabile locale]]
 
+
 
+
[[File:Scra_Fiammi_08.png|C++ con Qt, parte II, Scratch variabile locale]]
+
  
 
che influiscono solo su una delle due, ma lasciano inalterata l’altra.
 
che influiscono solo su una delle due, ma lasciano inalterata l’altra.
  
 
+
<br/>Il motivo è abbastanza evidente: quando le abbiamo create abbiamo specificato che ciascuna si riferisse a un solo sprite, e non a tutti gli sprite, pertanto il codice di uno sprite non è in grado di influenzare quella dell’altro sprite.
Il motivo è abbastanza evidente: quando le abbiamo create abbiamo specificato che ciascuna si riferisse a un solo sprite, e non a tutti gli sprite, pertanto il codice di uno sprite non è in grado di influenzare quella dell’altro sprite.
+
  
 
In informatica si usa il termine ''visibilità'' per descrivere questo fenomeno e si dice, appunto, che una variabile è ''visibile'' solo dal codice dello sprite cui si riferisce.
 
In informatica si usa il termine ''visibilità'' per descrivere questo fenomeno e si dice, appunto, che una variabile è ''visibile'' solo dal codice dello sprite cui si riferisce.
  
 
+
<br/>Per fare un paragone, è possibile che sia nella rubrica del vostro smartphone sia in quella del vostro compagno di tavolo sia presente il nome Ildebrando, però, stante il gran numero di Ildebrado che popolano questa nazione, potrebbero benissimo essere due persone diverse.
Per fare un paragone, è possibile che sia nella rubrica del vostro smartphone sia in quella del vostro compagno di tavolo sia presente il nome Ildebrando, però, stante il gran numero di Ildebrado che popolano questa nazione, potrebbero benissimo essere due persone diverse.
+
  
 
Quindi il nome di una variabile è unico solo nel suo ''spazio di visibilità''.
 
Quindi il nome di una variabile è unico solo nel suo ''spazio di visibilità''.
  
 
+
<br/>«Ma perché mai tutto queste complicazioni?» a qualcuno verrà da chiedere. «Non potevamo semplicemente creare due variabili con due nomi distinti, tipo presa1 e presa2, e lasciare che fossero visibili a tutti gli sprite?»
«Ma perché mai tutto queste complicazioni?» a qualcuno verrà da chiedere. «Non potevamo semplicemente creare due variabili con due nomi distinti, tipo presa1 e presa2, e lasciare che fossero visibili a tutti gli sprite?»
+
  
 
Beh, certo, lo potevamo fare. Anche in JavaScript o in C++ potremmo, con molta sofferenza, raggiungere questo poco auspicabile traguardo.
 
Beh, certo, lo potevamo fare. Anche in JavaScript o in C++ potremmo, con molta sofferenza, raggiungere questo poco auspicabile traguardo.
Riga 1 290: Riga 1 096:
 
Anzi! Se le prese dei due giocatori sono visibili da entrambi, il codice del Giocatore2 si semplifica non poco, ossia si tagliano via i 4 ''if''. Credo che lascerò questa parte come esercizio; per chi ci vuole provare, il primo passo è cercare di capire come mai non si riesce a vincere – da qui si può partire per costruire un algoritmo di gran lunga più efficiente di quello utilizzato.
 
Anzi! Se le prese dei due giocatori sono visibili da entrambi, il codice del Giocatore2 si semplifica non poco, ossia si tagliano via i 4 ''if''. Credo che lascerò questa parte come esercizio; per chi ci vuole provare, il primo passo è cercare di capire come mai non si riesce a vincere – da qui si può partire per costruire un algoritmo di gran lunga più efficiente di quello utilizzato.
  
 +
<br/>Adesso, però, per penetrare nel mistero dello ''spazio di visibilità'', vediamo una delle possibili trasposizioni del gioco dei fiammiferi in JavaScript.
  
Adesso, però, per penetrare nel mistero dello ''spazio di visibilità'', vediamo una delle possibili trasposizioni del gioco dei fiammiferi in JavaScript.
 
  
  
 
=== Il gioco dei fiammiferi in JavaScript ===
 
=== Il gioco dei fiammiferi in JavaScript ===
Cominciamo con il file in HTML5:
 
  
 +
Cominciamo con il file in HTML5:
 
<pre><!DOCTYPE html>
 
<pre><!DOCTYPE html>
  
Riga 1 312: Riga 1 118:
  
 
   <div class="bordato">
 
   <div class="bordato">
     <p>Ci sono 21 fiammiferi. A ogni turno possiamo prenderne da 1 a 4. Chi rimane con l&rsquo;ultimo ha perso.</p>
+
     <p>Ci sono 21 fiammiferi. A ogni turno possiamo prenderne da 1 a 4. Chi rimane con l’ultimo ha perso.</p>
 
     <p>Hai la prima mossa.</p>
 
     <p>Hai la prima mossa.</p>
 
     <input type="button" value="Inizia a giocare" onclick="inizioGioco();" />
 
     <input type="button" value="Inizia a giocare" onclick="inizioGioco();" />
Riga 1 348: Riga 1 154:
 
</html>
 
</html>
 
</pre>
 
</pre>
 
 
Poi i CSS:
 
Poi i CSS:
 
 
<pre>img {
 
<pre>img {
   width         : 200px;
+
   width         &nbsp;: 200px;
   height         : 220px;
+
   height       &nbsp;: 220px;
 
}
 
}
  
 
input {
 
input {
   display       : block;
+
   display       &nbsp;: block;
 
}
 
}
  
 
label {
 
label {
   display       : block;
+
   display       &nbsp;: block;
 
}
 
}
  
 
div.sx {
 
div.sx {
   float         : left;
+
   float         &nbsp;: left;
 
}
 
}
  
 
hr.fine_float {
 
hr.fine_float {
   clear         : both;
+
   clear         &nbsp;: both;
   height         : 0;
+
   height       &nbsp;: 0;
   margin         : 0;
+
   margin       &nbsp;: 0;
   border         : none;
+
   border       &nbsp;: none;
 
}
 
}
  
 
.molto_grande {
 
.molto_grande {
   font-size     : larger;
+
   font-size     &nbsp;: larger;
   font-weight   : bold;
+
   font-weight   &nbsp;: bold;
 
}
 
}
  
 
.bordato {
 
.bordato {
   border-color   : teal;
+
   border-color &nbsp;: teal;
   border-style   : ridge;
+
   border-style &nbsp;: ridge;
   border-width   : 2;
+
   border-width &nbsp;: 2;
   padding       : 0.6em;
+
   padding       &nbsp;: 0.6em;
   width         : 40em;
+
   width         &nbsp;: 40em;
 
}
 
}
  
 
.invisibile {
 
.invisibile {
   visibility     : hidden;
+
   visibility   &nbsp;: hidden;
 
}
 
}
  
 
.visibile {
 
.visibile {
   visibility     : visible;
+
   visibility   &nbsp;: visible;
 
}
 
}
  
 
.destra {
 
.destra {
   text-align     : right;
+
   text-align   &nbsp;: right;
 
}
 
}
 
</pre>
 
</pre>
 
 
Infine il JavaScript (il file deve chiamarsi “gioco21.js”):
 
Infine il JavaScript (il file deve chiamarsi “gioco21.js”):
 
 
<pre>var fiammiferi;
 
<pre>var fiammiferi;
 
var elementi_invisibili = [];
 
var elementi_invisibili = [];
Riga 1 488: Riga 1 290:
 
}
 
}
 
</pre>
 
</pre>
 +
Le immagini da utilizzare, mettendole nella stessa cartella del progetto, sono dog.jpg e duck.jpeg, che si trovano sullo wiki nelle rispettive pagine:
  
Le immagini da utilizzare, mettendole nella stessa cartella del progetto, sono dog.jpg e duck.jpeg, che si trovano qui sullo wiki.
+
*[[Media:Dog.jpg|Media:Dog.jpg]]
 +
*[[Media:Duck.jpeg|Media:Duck.jpeg]]
  
 +
<br/>Un’altra cosa: scrivere tutte le volte il nome JavaScript per esteso mi fa un po’ fatica. Un sacco di gente lo chiama semplicemente JS, perché non lo facciamo anche noi?
  
Un’altra cosa: scrivere tutte le volte il nome JavaScript per esteso mi fa un po’ fatica. Un sacco di gente lo chiama semplicemente JS, perché non lo facciamo anche noi?
+
<br/>Tanto vale che lo ammetta fin da subito: il codice JS che vi presento è un tantino complicato. Ormai abbiamo rotto il ghiaccio con l’idea di scrivere codice, per cui è inutile che continuiamo a fare i timidi. Vedrete che riusciremo a domare anche questo programma e ci insegnerà un sacco di cose.
  
 +
<br/>Lo scopo di questo programma è parlare prima di tutto di ''scope resolution'' perché è un argomento un po’ astratto, ma ne verranno fuori tanti altri via via che scorreremo le righe. Intanto diamo un’occhiata generale al programma, che ha ben 5 funzioni:
  
Tanto vale che lo ammetta fin da subito: il codice JS che vi presento è un tantino complicato. Ormai abbiamo rotto il ghiaccio con l’idea di scrivere codice, per cui è inutile che continuiamo a fare i timidi. Vedrete che riusciremo a domare anche questo programma e ci insegnerà un sacco di cose.
+
#inizioGioco()
 
+
#mossaCane()
 
+
#mossaAnatra()
Lo scopo di questo programma è parlare prima di tutto di ''scope resolution'' perché è un argomento un po’ astratto, ma ne verranno fuori tanti altri via via che scorreremo le righe. Intanto diamo un’occhiata generale al programma, che ha ben 5 funzioni:
+
#cambiaVisibilita
 
+
#trovaEleInvi()
# inizioGioco()
+
# mossaCane()
+
# mossaAnatra()
+
# cambiaVisibilita
+
# trovaEleInvi()
+
  
 
Beh? Di cosa vi meravigliate? Il codice va spezzato in funzioni oppure non riusciremo mai a riutilizzarlo.
 
Beh? Di cosa vi meravigliate? Il codice va spezzato in funzioni oppure non riusciremo mai a riutilizzarlo.
Riga 1 510: Riga 1 311:
 
Tra queste funzioni ce ne sono alcune che ci risulteranno ben chiare, ad esempio ''mossaCane()'' e ''mossaAnatra()'', che gestiscono il cambiamento del numero di fiammiferi in base alle scelte dei due giocatori. Altre invece ci risulteranno alquanto misteriose. Direi che la strategia più semplice per affrontarle è seguire il programma passo passo.
 
Tra queste funzioni ce ne sono alcune che ci risulteranno ben chiare, ad esempio ''mossaCane()'' e ''mossaAnatra()'', che gestiscono il cambiamento del numero di fiammiferi in base alle scelte dei due giocatori. Altre invece ci risulteranno alquanto misteriose. Direi che la strategia più semplice per affrontarle è seguire il programma passo passo.
  
 
+
<br/>Quando l’utente inizia, per prima cosa è invitato a leggere le spiegazioni e poi a premere il pulsante “Inizia a giocare”. Questo pulsante fa comparire la casella di testo dove il giocatore1 può inserire la sua scelta.
Quando l’utente inizia, per prima cosa è invitato a leggere le spiegazioni e poi a premere il pulsante “Inizia a giocare”. Questo pulsante fa comparire la casella di testo dove il giocatore1 può inserire la sua scelta.
+
  
 
Come fa a farlo?
 
Come fa a farlo?
Riga 1 517: Riga 1 317:
 
Guardiamo il codice HTML. Ci sono ben tre elementi che ‘nascono’ con associata la classe CSS ‘invisibile’:
 
Guardiamo il codice HTML. Ci sono ben tre elementi che ‘nascono’ con associata la classe CSS ‘invisibile’:
  
* la scritta “Quanti fiammiferi prendo?”
+
*la scritta “Quanti fiammiferi prendo?”
* la casella di testo in cui scrivere il numero
+
*la casella di testo in cui scrivere il numero
* il pulsante “Tocca a te”
+
*il pulsante “Tocca a te”
  
 
La classe ‘invisibile’ consiste nell’istruzione
 
La classe ‘invisibile’ consiste nell’istruzione
 
+
<pre>visibility&nbsp;: hidden;</pre>
<pre>visibility : hidden;</pre>
+
 
+
 
Hidden in inglese vuol dire nascosto, e infatti quello che fa questa istruzione è di nascondere gli elementi a video. Ossia, essi ‘esistono’ nel codice HTML, ma non sono rappresentati a video.
 
Hidden in inglese vuol dire nascosto, e infatti quello che fa questa istruzione è di nascondere gli elementi a video. Ossia, essi ‘esistono’ nel codice HTML, ma non sono rappresentati a video.
  
 
Quando la partita inizia, bisogna che questi elementi saltino fuori, e questo si può ottenere sostituendo la classe ‘invisibile’ con quella ‘visibile’.
 
Quando la partita inizia, bisogna che questi elementi saltino fuori, e questo si può ottenere sostituendo la classe ‘invisibile’ con quella ‘visibile’.
  
 +
<br/>La pressione sul pulsante “Inizia a giocare” compie proprio questo passaggio tramite la funzione ''inizioGioco()''. Questo passaggio è reso necessario dal fatto che, quando il gioco finisce, sopra le due immagini compaiono scritte che non devono più apparire; non solo, ma il numero dei fiammiferi sarà 1 invece che 21; oltre a ciò, per comunicare all’utente che il gioco è finito, i tre elementi elencati sopra saranno resi invisibili di nuovo. Pertanto ci serve una funzione che rimetta a posto le cose prima dell’inizio di una partita.
  
La pressione sul pulsante “Inizia a giocare” compie proprio questo passaggio tramite la funzione ''inizioGioco()''. Questo passaggio è reso necessario dal fatto che, quando il gioco finisce, sopra le due immagini compaiono scritte che non devono più apparire; non solo, ma il numero dei fiammiferi sarà 1 invece che 21; oltre a ciò, per comunicare all’utente che il gioco è finito, i tre elementi elencati sopra saranno resi invisibili di nuovo. Pertanto ci serve una funzione che rimetta a posto le cose prima dell’inizio di una partita.
+
Però diamo anche un’occhiata anche a ciò che è scritto prima di ''InizioGioco()'':
 
+
Però diamo anche un’occhiata anche a ciò che è scritto prima di ''InizioGioco()'':  
+
 
+
 
<pre>var fiammiferi;
 
<pre>var fiammiferi;
 
var elementi_invisibili = [];
 
var elementi_invisibili = [];
 
</pre>
 
</pre>
 
 
Queste due istruzioni si limitano a definire una variabile e un array; la prima conterrà il numero di fiammiferi; la seconda invece i tre elementi che dovranno ‘apparire’ o ‘sparire’, ossia quei tre elencai poco sopra. Queste due istruzioni non sembrano aver nessuna particolarità, se non una che forse non salta all’occhio subito: si trovano entrambe fuori da ogni funzione.
 
Queste due istruzioni si limitano a definire una variabile e un array; la prima conterrà il numero di fiammiferi; la seconda invece i tre elementi che dovranno ‘apparire’ o ‘sparire’, ossia quei tre elencai poco sopra. Queste due istruzioni non sembrano aver nessuna particolarità, se non una che forse non salta all’occhio subito: si trovano entrambe fuori da ogni funzione.
  
 
Torneremo tra pochissimo su questa osservazione, che è molto importante.
 
Torneremo tra pochissimo su questa osservazione, che è molto importante.
  
 +
<br/>Diamo un’occhiata a quali sono le operazioni preliminare a ogni partita, cioè a perché chiamiamo la funzione ''inizioGioco()'':
  
Diamo un’occhiata a quali sono le operazioni preliminare a ogni partita, cioè a perché chiamiamo la funzione ''inizioGioco()'':
+
<br/>'''fiammiferi = 21;'''
 
+
 
+
'''fiammiferi = 21;'''
+
  
 
Come si è detto, alla fine di una partita il numero di fiammiferi sarà uno, quindi all’inizio della partita successiva va riportato a 21. ‘fiammiferi’ è la variabile dichiarata fuori da ogni funzione. Come vedete, possiamo usarla senza problemi anche se non l’abbiamo definita qui.
 
Come si è detto, alla fine di una partita il numero di fiammiferi sarà uno, quindi all’inizio della partita successiva va riportato a 21. ‘fiammiferi’ è la variabile dichiarata fuori da ogni funzione. Come vedete, possiamo usarla senza problemi anche se non l’abbiamo definita qui.
  
 
+
<br/>'''numero_fiammiferi = document.getElementById('numfiammi');'''
'''numero_fiammiferi = document.getElementById('numfiammi');'''
+
  
 
'''numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;'''
 
'''numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;'''
  
 
+
<br/>A questo punto aggiorniamo la scritta “Fiammiferi rimasti: 21” sullo schermo. Quindi, ‘numero_fiammiferi’ è una variabile che ci consente di accedere al del codice HTML. Lì dentro, tramite il metodo ''innerHTML'', andiamo a inserire la frase: “Fiammiferi rimasti: 21”. Facciamo caso a una cosa: ''numero_fiammiferi'' è stata definita senza la parolina ''var'' davanti.<br/>'''document.getElementById("messaggio_cane").innerHTML = "&nbsp;";''' '''document.getElementById("messaggio_anatra").innerHTML = "&nbsp;";''' Queste due righe dovrebbero essere chiare, eccetto che forse non tutti sanno cosa vuol dire ''&nbsp;'' nello HTML. A dir la verità nel Coder Dojo abbiamo già avuto modo di scoprire che ''è'' serve per inserire la lettera ‘è’ e ''ò'' per inserire la lettera ‘ò’, perciò dovrebbe essere piuttosto naturale dedurre che anche ''&nbsp;'' serva per inserire una lettera. Beh, quasi, ma non proprio: è solo un modo complicato di inserire uno spazio. Avremmo anche potuto scrivere document.getElementById("messaggio_cane").innerHTML = " "; document.getElementById("messaggio_anatra").innerHTML = " "; con uno spazio dentro le virgolette e avrebbe funzionato lo stesso (provare per credere). Il fatto è che non tutti usano un semplice editor di testo per scrivere codice HTML; esistono anche dei programmi appositi, molto più evoluti. Una delle caratteristiche di questi programmi è che rimettono a posto il codice via via che lo si scrive; ad esempio se scriviamo &lt;p&gt;, questi programmi aggiungono automaticamente un subito dopo; e come questa, fanno anche tante altre cose per semplificarci la vita. Una di queste cose, però, è eliminare gli elementi vuoti. Ossia, se a un certo punto scrivete
A questo punto aggiorniamo la scritta “Fiammiferi rimasti: 21” sullo schermo.
+
 
+
Quindi, ‘numero_fiammiferi’ è una variabile che ci consente di accedere al <p id="numfiammi"> del codice HTML. Lì dentro, tramite il metodo ''innerHTML'', andiamo a inserire la frase: “Fiammiferi rimasti: 21”.
+
 
+
Facciamo caso a una cosa: ''numero_fiammiferi'' è stata definita senza la parolina ''var'' davanti.
+
 
+
 
+
<br/>'''document.getElementById("messaggio_cane").innerHTML = "&amp;nbsp;";'''
+
 
+
'''document.getElementById("messaggio_anatra").innerHTML = "&amp;nbsp;";'''
+
 
+
Queste due righe dovrebbero essere chiare, eccetto che forse non tutti sanno cosa vuol dire ''&amp;nbsp;'' nello HTML.
+
 
+
A dir la verità nel Coder Dojo abbiamo già avuto modo di scoprire che ''&amp;egrave;'' serve per inserire la lettera ‘è’ e ''&amp;ograve;'' per inserire la lettera ‘ò’, perciò dovrebbe essere piuttosto naturale dedurre che anche ''&amp;nbsp;'' serva per inserire una lettera. Beh, quasi, ma non proprio: è solo un modo complicato di inserire uno spazio. Avremmo anche potuto scrivere
+
 
+
document.getElementById("messaggio_cane").innerHTML = " ";
+
 
+
document.getElementById("messaggio_anatra").innerHTML = " ";
+
 
+
con uno spazio dentro le virgolette e avrebbe funzionato lo stesso (provare per credere).
+
 
+
 
+
Il fatto è che non tutti usano un semplice editor di testo per scrivere codice HTML; esistono anche dei programmi appositi, molto più evoluti. Una delle caratteristiche di questi programmi è che rimettono a posto il codice via via che lo si scrive; ad esempio se scriviamo <p>, questi programmi aggiungono automaticamente un </p> subito dopo; e come questa, fanno anche tante altre cose per semplificarci la vita. Una di queste cose, però, è eliminare gli elementi vuoti.
+
 
+
Ossia, se a un certo punto scrivete
+
 
+
 
<pre><p></p></pre>
 
<pre><p></p></pre>
 
 
oppure
 
oppure
 
 
<pre><p> </p></pre>
 
<pre><p> </p></pre>
 
 
con solo uno spazio dentro, il programma, quando lo vede, pensa: «Che cosa ci sta a fare qui un paragrafo senza niente dentro? Si è dimenticato di levarlo, quel pasticcione… Eh, meno male che ci sono io qui a rimettere a posto le cose, sennò chissà dove andremmo a finire!», e, detto fatto, lo cancella.
 
con solo uno spazio dentro, il programma, quando lo vede, pensa: «Che cosa ci sta a fare qui un paragrafo senza niente dentro? Si è dimenticato di levarlo, quel pasticcione… Eh, meno male che ci sono io qui a rimettere a posto le cose, sennò chissà dove andremmo a finire!», e, detto fatto, lo cancella.
  
 
Se invece scrivete
 
Se invece scrivete
 
+
<pre><p>&nbsp;</p></pre>
<pre><p>&amp;nbsp;</p></pre>
+
 
+
 
ottenete lo stesso risultato, ma il programma per scrivere codice HTML, se ne state usando uno, ve lo lascia stare.
 
ottenete lo stesso risultato, ma il programma per scrivere codice HTML, se ne state usando uno, ve lo lascia stare.
  
 
+
<br/>'''trovaEleInvi();'''
'''trovaEleInvi();'''
+
  
 
Questa istruzione fa saltare il programma nella funzione ''trovaEleInvi()''. Seguiamolo.
 
Questa istruzione fa saltare il programma nella funzione ''trovaEleInvi()''. Seguiamolo.
  
 
+
<br/>'''elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1label");'''
'''elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1label");'''
+
  
 
'''elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1");'''
 
'''elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1");'''
Riga 1 619: Riga 1 378:
  
 
Quindi, se noi vogliamo inserire il primo elemento nella prima posizione di una array, ossia in posizione 0, vuol dire che dobbiamo scrivere:
 
Quindi, se noi vogliamo inserire il primo elemento nella prima posizione di una array, ossia in posizione 0, vuol dire che dobbiamo scrivere:
 
 
<pre>elementi_invisibili[0] = …</pre>
 
<pre>elementi_invisibili[0] = …</pre>
 
 
Però anche ''elementi_invisibili.length'' è 0, pertanto le due istruzioni ''elementi_invisibili[0]'' e ''elementi_invisibili[elementi_invisibili.length]'' sono perfettamente identiche.
 
Però anche ''elementi_invisibili.length'' è 0, pertanto le due istruzioni ''elementi_invisibili[0]'' e ''elementi_invisibili[elementi_invisibili.length]'' sono perfettamente identiche.
  
 +
<br/>Quindi la prima delle tre righe inserisce l’elemento HTML &lt;label id="g1label"&gt; nella posizione 0 di ''elementi_invisibili''.
  
Quindi la prima delle tre righe inserisce l’elemento HTML <label id="g1label"> nella posizione 0 di ''elementi_invisibili''.
+
<br/>A questo punto, però, la dimensione del nostro array è cambiata perché dentro c’è un elemento. Quindi ''elementi_invisibili.length'' non restituirà più 0, bensì 1.
 
+
 
+
A questo punto, però, la dimensione del nostro array è cambiata perché dentro c’è un elemento. Quindi ''elementi_invisibili.length'' non restituirà più 0, bensì 1.
+
  
 
Quindi la seconda riga
 
Quindi la seconda riga
 
 
<pre>elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1");</pre>
 
<pre>elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1");</pre>
 
+
inserirà l’elemento HTML &lt;input id="g1"&gt; nella seconda posizione dello array, ossia in posizione 1.
inserirà l’elemento HTML <input id="g1"> nella seconda posizione dello array, ossia in posizione 1.
+
  
 
Ciò significa che scrivere
 
Ciò significa che scrivere
 
 
<pre>elementi_invisibili[elementi_invisibili.length] = qualcosa;</pre>
 
<pre>elementi_invisibili[elementi_invisibili.length] = qualcosa;</pre>
 
 
istruisce il computer a inserire ‘qualcosa’ nella prima posizione libera dell’array, ossia in coda agli altri dati contenuti.
 
istruisce il computer a inserire ‘qualcosa’ nella prima posizione libera dell’array, ossia in coda agli altri dati contenuti.
  
 +
<br/>Attenzione! Di nuovo dobbiamo far attenzione al fatto che l’array ''elementi_invisibili'' è stato definito da un’altra parte, ossia all’inizio del nostro programma. Anche in questa occasione, ci limitiamo ad usarlo, proprio come se fosse stato definito in questa funzione.
  
Attenzione! Di nuovo dobbiamo far attenzione al fatto che l’array ''elementi_invisibili'' è stato definito da un’altra parte, ossia all’inizio del nostro programma. Anche in questa occasione, ci limitiamo ad usarlo, proprio come se fosse stato definito in questa funzione.
+
<br/>A questo punto la funzione ''trovaEleInvi()'' è finita è il computer torna in ''inizioGioco()''. E noi con lui.
  
 
+
<br/>'''cambiaVisibilita(1);'''
A questo punto la funzione ''trovaEleInvi()'' è finita è il computer torna in ''inizioGioco()''. E noi con lui.
+
 
+
 
+
'''cambiaVisibilita(1);'''
+
  
 
Questa istruzione ci fa saltare nella funzione ''cambiaVisibilita()''.
 
Questa istruzione ci fa saltare nella funzione ''cambiaVisibilita()''.
Riga 1 655: Riga 1 403:
 
Mettiamoci d’accordo su un altro parolone: in informatica chiamare una funzione si dice ‘'''invocare'''’ una funzione.
 
Mettiamoci d’accordo su un altro parolone: in informatica chiamare una funzione si dice ‘'''invocare'''’ una funzione.
  
 
+
<br/>'''cambiaVisibilita(visibilita)'''
'''cambiaVisibilita(visibilita)'''
+
  
 
Questa funzione fa una cosa semplice, anche se a vederla sembra piena di righe complicate.
 
Questa funzione fa una cosa semplice, anche se a vederla sembra piena di righe complicate.
Riga 1 666: Riga 1 413:
 
Se quel valore è 0, li nasconde.
 
Se quel valore è 0, li nasconde.
  
 +
<br/>Fateci caso anche qui: stiamo usando l’array ''elementi_invisibili'' né più né meno come se l’avessimo definito in questa funzione.
  
Fateci caso anche qui: stiamo usando l’array ''elementi_invisibili'' né più né meno come se l’avessimo definito in questa funzione.
+
<br/>Tutto è gestito dal ciclo ''for'', che incrementa di uno il valore della variabile ‘indice’ da 0 fino a che non è '''inferiore''' al numero di dati contenuti nello array, ossia al massimo a 2 (perché 3 non sarebbe più inferiore alla dimensione dell’array, bensì uguale).
 
+
 
+
Tutto è gestito dal ciclo ''for'', che incrementa di uno il valore della variabile ‘indice’ da 0 fino a che non è '''inferiore''' al numero di dati contenuti nello array, ossia al massimo a 2 (perché 3 non sarebbe più inferiore alla dimensione dell’array, bensì uguale).
+
  
 
Il valore di questa variabile è poi usato come indice dell’array (e proprio perché fosse chiara questa sua funzione l’abbiamo chiamata ‘indice’, ma avrebbe potuto benissimo chiamarsi ‘Genoveffa’ e non sarebbe cambiato nulla).
 
Il valore di questa variabile è poi usato come indice dell’array (e proprio perché fosse chiara questa sua funzione l’abbiamo chiamata ‘indice’, ma avrebbe potuto benissimo chiamarsi ‘Genoveffa’ e non sarebbe cambiato nulla).
Riga 1 676: Riga 1 421:
 
Il metodo setAttribute si occupa di far cambiare agli Elementi HTML la classe CSS associata, ''visibile'' o ''invisibile''.
 
Il metodo setAttribute si occupa di far cambiare agli Elementi HTML la classe CSS associata, ''visibile'' o ''invisibile''.
  
 +
<br/>In questo caso è stato passato il valore 1 ed ecco spiegato come fanno i 3 famigerati elementi ad apparire.
  
In questo caso è stato passato il valore 1 ed ecco spiegato come fanno i 3 famigerati elementi ad apparire.
+
<br/>A questo punto il primo ‘passaggio’ è finito. Siamo in attesa che l’utente scriva un numero nella casella di testo &lt;input id="g1"&gt; e prema il pulsante “Tocca a te”.
 
+
 
+
A questo punto il primo ‘passaggio’ è finito. Siamo in attesa che l’utente scriva un numero nella casella di testo <input id="g1"> e prema il pulsante “Tocca a te”.
+
  
 
La pressione di quel pulsante invoca la funzione ''mossaCane()'', alla tentazione di esaminare la quale non possiamo resistere:
 
La pressione di quel pulsante invoca la funzione ''mossaCane()'', alla tentazione di esaminare la quale non possiamo resistere:
  
 +
<br/>'''var presa = document.getElementById("g1").value;'''
  
'''var presa = document.getElementById("g1").value;'''
+
Qui dichiariamo una variabile all’interno di una funzione tramite la parola ''var''. Ne sentivate la mancanza, di un’istruzione così?&nbsp;:)
  
Qui dichiariamo una variabile all’interno di una funzione tramite la parola ''var''. Ne sentivate la mancanza, di un’istruzione così? :)
+
Direi che non c’è molto da aggiungere: la variabile conterrà ciò che ha immesso l’utente della casella di testo &lt;input id="g1"&gt;
  
Direi che non c’è molto da aggiungere: la variabile conterrà ciò che ha immesso l’utente della casella di testo <input id="g1">
+
<br/>'''var messaggio = document.getElementById("messaggio_cane");'''
  
 
+
'''messaggio.innerHTML = "&nbsp;";'''
'''var messaggio = document.getElementById("messaggio_cane");'''
+
 
+
'''messaggio.innerHTML = "&amp;nbsp;";'''
+
  
 
Anche se l’avevamo già fatto prima, qui sostituiamo il testo che compare sopra l’immagine del canino con uno spazio, ossia con qualcosa di apparentemente vuoto.
 
Anche se l’avevamo già fatto prima, qui sostituiamo il testo che compare sopra l’immagine del canino con uno spazio, ossia con qualcosa di apparentemente vuoto.
Riga 1 700: Riga 1 441:
 
Il fatto è che il pulsante “Inizia a giocare” non sarà più premuto fino alla fine della partita, ma la presa dei fiammiferi si effettuerà più volte prima di allora, e ogni volta qui dovrà comparire un testo diverso.
 
Il fatto è che il pulsante “Inizia a giocare” non sarà più premuto fino alla fine della partita, ma la presa dei fiammiferi si effettuerà più volte prima di allora, e ogni volta qui dovrà comparire un testo diverso.
  
 
+
<br/>'''// Controllo di non essere gia' rimasto con l'ultimo fiammifero'''
'''// Controllo di non essere gia' rimasto con l'ultimo fiammifero'''
+
  
 
Questo è un commento per ricordarsi cosa si sta facendo. Il nostro codice dovrebbe esserne pieno, ma col fatto che poi commento tutto dopo, per ora non sto a scriverli. Però tenete presente che scrivere i commenti è una delle attività più importanti del programmare.
 
Questo è un commento per ricordarsi cosa si sta facendo. Il nostro codice dovrebbe esserne pieno, ma col fatto che poi commento tutto dopo, per ora non sto a scriverli. Però tenete presente che scrivere i commenti è una delle attività più importanti del programmare.
 +
  
  
 
{| class="wikitable"
 
{| class="wikitable"
 +
|-
 
! <center>Codice</center>
 
! <center>Codice</center>
 
! <center>Spiegazioni</center>
 
! <center>Spiegazioni</center>
 
 
|-
 
|-
| if ( 1 == fiammiferi ){
+
| if ( 1 == fiammiferi ){
|Il blocco successivo si attiverà solo quando il giocatore1 sarà rimasto con l’ultimo fiammifero
+
| Il blocco successivo si attiverà solo quando il giocatore1 sarà rimasto con l’ultimo fiammifero
 
+
 
|-
 
|-
| messaggio.innerHTML = "Mi sa che ha vinto lui...";
+
| messaggio.innerHTML = "Mi sa che ha vinto lui...";
|Vi ricordate cosa conteneva ‘messaggio’? L’elemento HTML <p id="messaggio_cane">
+
| Vi ricordate cosa conteneva ‘messaggio’? L’elemento HTML
  
|-
 
|  cambiaVisibilita(0);
 
|Si invoca la funzione ''cambiaVisibilita()'' passandogli il valore 0, ossia dicendole di far ‘sparire’ i 3 ormai arcinoti elementi
 
  
 
|-
 
|-
| return 0;
+
| cambiaVisibilita(0);
 +
| Si invoca la funzione ''cambiaVisibilita()'' passandogli il valore 0, ossia dicendole di far ‘sparire’ i 3 ormai arcinoti elementi
 +
|-
 +
| return 0;
 
| Questa riga forza l’uscita dalla funzione ''mossaCane()'' senza che venga eseguito il resto del codice – Se il giocatore1 ha perso, non c’è più motivo di fargli prendere altri fiammiferi – Attenzione! Non è rilevante che non ci sia nessuno a ‘raccogliere’ il valore restituito da ''mossaCane()'', l’importante è che ''return'' blocchi il codice.
 
| Questa riga forza l’uscita dalla funzione ''mossaCane()'' senza che venga eseguito il resto del codice – Se il giocatore1 ha perso, non c’è più motivo di fargli prendere altri fiammiferi – Attenzione! Non è rilevante che non ci sia nessuno a ‘raccogliere’ il valore restituito da ''mossaCane()'', l’importante è che ''return'' blocchi il codice.
 
 
|-
 
|-
| <nowiki> } </nowiki>
+
| <nowiki>} </nowiki>
|fine del blocco di codice ''if''
+
| fine del blocco di codice ''if''
 
+
 
|}
 
|}
  
 
+
<br/>'''if( presa > 0 && presa < 5 ) {'''
'''if( presa > 0 && presa < 5 ) {'''
+
  
 
Anche questa istruzione può lasciare interdetti, ma è molto più semplice di quel che appaia.
 
Anche questa istruzione può lasciare interdetti, ma è molto più semplice di quel che appaia.
Riga 1 749: Riga 1 486:
 
Detto alla rovescia, l’espressione dentro la parentesi è considerata vera SOLO SE '''TUTTE''' le condizioni sono vere.
 
Detto alla rovescia, l’espressione dentro la parentesi è considerata vera SOLO SE '''TUTTE''' le condizioni sono vere.
  
 +
<br/>Quindi, se l’utente inserisce un numero tra 1 e 4, si entra nel blocco, altrimenti si prosegue con il blocco ''else''.
  
Quindi, se l’utente inserisce un numero tra 1 e 4, si entra nel blocco, altrimenti si prosegue con il blocco ''else''.
+
<br/>'''messaggio.innerHTML = "Ho preso " + presa + " fiammiferi";'''
 
+
 
+
'''messaggio.innerHTML = "Ho preso " + presa + " fiammiferi";'''
+
  
 
Si aggiorna la scritta sopra l’immagine del canino.
 
Si aggiorna la scritta sopra l’immagine del canino.
  
 
+
<br/>'''fiammiferi -= presa;'''
'''fiammiferi -= presa;'''
+
  
 
Un’altra cosa che non abbiamo ancora visto, ma anche qui non c’è da farsi prendere dal panico.
 
Un’altra cosa che non abbiamo ancora visto, ma anche qui non c’è da farsi prendere dal panico.
  
 
Mettiamo che io abbia una variabile, ‘gigetto’, e che sia uguale a 5.
 
Mettiamo che io abbia una variabile, ‘gigetto’, e che sia uguale a 5.
 
 
<pre>var gigetto = 5;</pre>
 
<pre>var gigetto = 5;</pre>
 
 
Se scrivo
 
Se scrivo
 
 
<pre>gigetto = gigetto + 1;</pre>
 
<pre>gigetto = gigetto + 1;</pre>
 
 
‘gigetto’ diventa uguale a 6. Solo che l’istruzione è considerata molto lunga da qui pigroni degli informatici, perciò si sono messi d’accordo a trovare un modo di non ripetere la parola ‘gigetto’ e alla fine hanno trovato questa diavoleria:
 
‘gigetto’ diventa uguale a 6. Solo che l’istruzione è considerata molto lunga da qui pigroni degli informatici, perciò si sono messi d’accordo a trovare un modo di non ripetere la parola ‘gigetto’ e alla fine hanno trovato questa diavoleria:
 
 
<pre>gigetto += 1;</pre>
 
<pre>gigetto += 1;</pre>
 
 
Carino, eh? Badate bene, non vuol dire nulla di particolare: se ‘gigetto’ era uguale a 6, adesso diventa uguale a 7.
 
Carino, eh? Badate bene, non vuol dire nulla di particolare: se ‘gigetto’ era uguale a 6, adesso diventa uguale a 7.
  
 
Però non è finita qui. Visto che la maggior parte delle volte il valore di una variabile cambia solo di 1, si sono inventati un metodo ancora più breve, cioè questo:
 
Però non è finita qui. Visto che la maggior parte delle volte il valore di una variabile cambia solo di 1, si sono inventati un metodo ancora più breve, cioè questo:
 
 
<pre>gigetto++;</pre>
 
<pre>gigetto++;</pre>
 
 
Anche se può sembrare illeggibile, il significato delle 3 istruzioni è esattamente il medesimo; quindi, partendo dal 7 di prima, adesso ‘gigetto’ è diventata 8.
 
Anche se può sembrare illeggibile, il significato delle 3 istruzioni è esattamente il medesimo; quindi, partendo dal 7 di prima, adesso ‘gigetto’ è diventata 8.
  
 
Tutto qui.
 
Tutto qui.
  
 
+
<br/>E lo stesso vale per il segno meno:
E lo stesso vale per il segno meno:
+
 
+
 
<pre>gigetto -= 3;</pre>
 
<pre>gigetto -= 3;</pre>
 
 
fa tornare ‘gigetto’, da 8 che era, di nuovo a 5; e
 
fa tornare ‘gigetto’, da 8 che era, di nuovo a 5; e
 
 
<pre>gigetto--;</pre>
 
<pre>gigetto--;</pre>
 
 
addirittura a 4.
 
addirittura a 4.
  
 
+
<br/>Invece le altre operazioni si devono ‘accontentare’ della sintassi con il segno di uguale, ossia *= e /=.
Invece le altre operazioni si devono ‘accontentare’ della sintassi con il segno di uguale, ossia *= e /=.
+
  
 
Per rendere le cose semplici, riporto qui un po’ di esempi che dovrebbero essere più chiari di mille parole:
 
Per rendere le cose semplici, riporto qui un po’ di esempi che dovrebbero essere più chiari di mille parole:
  
  
{| class="wikitable"
 
|  var unvalore = 10;
 
|  unvalore == 10
 
  
 +
{| class="wikitable"
 
|-
 
|-
| unvalore++;
+
| var unvalore = 10;
| unvalore == 11
+
| unvalore == 10
 
+
 
|-
 
|-
| unvalore -= 9;
+
| unvalore++;
| unvalore == 2
+
| unvalore == 11
 
+
 
|-
 
|-
| unvalore *= 7;
+
| unvalore -= 9;
| unvalore == 14
+
| unvalore == 2
 
+
 
|-
 
|-
| unvalore--;
+
| unvalore *= 7;
| unvalore == 13
+
| unvalore == 14
 
+
 
|-
 
|-
| unvalore += 5;
+
| unvalore--;
| unvalore == 18
+
| unvalore == 13
 
+
 
|-
 
|-
| unvalore /= 3;
+
| unvalore += 5;
| un valore == 6
+
| unvalore == 18
 
+
|-
 +
| unvalore /= 3;
 +
| un valore == 6
 
|}
 
|}
  
 
Pertanto l’istruzione
 
Pertanto l’istruzione
 
 
<pre>fiammiferi -= presa;</pre>
 
<pre>fiammiferi -= presa;</pre>
 
 
è del tutto identica a
 
è del tutto identica a
 
 
<pre>fiammiferi = fiammiferi - presa;</pre>
 
<pre>fiammiferi = fiammiferi - presa;</pre>
 
 
e si limita a far calare il numero dei fiammiferi del valore di ‘presa’.
 
e si limita a far calare il numero dei fiammiferi del valore di ‘presa’.
  
 +
<br/>ANCORA UNA VOLTA STIAMO USANDO UNA VARIABILE CHE NON È STATA DICHIARATA NELLA FUNZIONE IN CUI CI TROVIAMO COME SE LO FOSSE STATA.
  
ANCORA UNA VOLTA STIAMO USANDO UNA VARIABILE CHE NON È STATA DICHIARATA NELLA FUNZIONE IN CUI CI TROVIAMO COME SE LO FOSSE STATA.
+
<br/>'''numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;'''
 
+
 
+
'''numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;'''
+
  
 
Dovrebbe essere chiaro.
 
Dovrebbe essere chiaro.
  
 
+
<br/>'''mossaAnatra();'''
'''mossaAnatra();'''
+
  
 
Andiamo a vedere cosa combina questa funzione.
 
Andiamo a vedere cosa combina questa funzione.
Riga 1 856: Riga 1 564:
 
Però, attenzione!, dopo NON torneremo in ''mossaCane()'' perché il codice restante, ossia lo ALTRIMENTI del blocco ''if'' è talmente ovvio che siete del tutto in grado di decifrarlo da soli.
 
Però, attenzione!, dopo NON torneremo in ''mossaCane()'' perché il codice restante, ossia lo ALTRIMENTI del blocco ''if'' è talmente ovvio che siete del tutto in grado di decifrarlo da soli.
  
 +
<br/>'''var messaggio = document.getElementById("messaggio_anatra");'''
  
'''var messaggio = document.getElementById("messaggio_anatra");'''
+
'''messaggio.innerHTML = "&nbsp;";'''
 
+
'''messaggio.innerHTML = "&amp;nbsp;";'''
+
  
 
Queste due righe erano staccate fra di loro, ma se si guardano così di seguito direi che non hanno bisogno di chiarimenti.
 
Queste due righe erano staccate fra di loro, ma se si guardano così di seguito direi che non hanno bisogno di chiarimenti.
  
 
+
<br/>'''var presa = 0;'''
'''var presa = 0;'''
+
  
 
Neanche questa ha bisogno di chiarimenti.
 
Neanche questa ha bisogno di chiarimenti.
  
 +
<br/>'''if( 1 < fiammiferi){'''
 +
 +
:'''presa = fiammiferi - 1;'''
  
'''if( 1 < fiammiferi){'''
 
: '''presa = fiammiferi - 1;'''
 
 
'''}'''
 
'''}'''
  
 
'''if( 6 < fiammiferi){'''
 
'''if( 6 < fiammiferi){'''
: '''presa = fiammiferi - 6;'''
+
 
 +
:'''presa = fiammiferi - 6;'''
 +
 
 
'''}'''
 
'''}'''
  
 
'''if( 11 < fiammiferi){'''
 
'''if( 11 < fiammiferi){'''
: '''presa = fiammiferi - 11;'''
+
 
 +
:'''presa = fiammiferi - 11;'''
 +
 
 
'''}'''
 
'''}'''
  
 
'''if( 16 < fiammiferi){'''
 
'''if( 16 < fiammiferi){'''
: '''presa = fiammiferi - 16;'''
+
 
 +
:'''presa = fiammiferi - 16;'''
 +
 
 
'''}'''
 
'''}'''
  
Riga 1 889: Riga 1 602:
 
Comprenderne la logica è lasciato come esercizio. Si può partire dall’invertire le condizioni; ossia, invece di scrivere ''if( 1 < fiammiferi)'' si può scrivere ''if( fiammiferi > 1 )'', il ché dovrebbe rendere il meccanismo più chiaro.
 
Comprenderne la logica è lasciato come esercizio. Si può partire dall’invertire le condizioni; ossia, invece di scrivere ''if( 1 < fiammiferi)'' si può scrivere ''if( fiammiferi > 1 )'', il ché dovrebbe rendere il meccanismo più chiaro.
  
 
+
<br/>'''fiammiferi -= presa;'''
'''fiammiferi -= presa;'''
+
  
 
Ne abbiamo già vista una identica poco sopra.
 
Ne abbiamo già vista una identica poco sopra.
  
 
+
<br/>'''messaggio.innerHTML = "Io prendo " + presa + " fiammiferi";'''
'''messaggio.innerHTML = "Io prendo " + presa + " fiammiferi";'''
+
  
 
'''numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;'''
 
'''numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;'''
Riga 1 901: Riga 1 612:
 
Non ci vedo difficoltà.
 
Non ci vedo difficoltà.
  
 +
<br/>'''if ( 1 == fiammiferi ) {'''
  
'''if ( 1 == fiammiferi ) {'''
+
:'''mossaCane();'''
 
+
: '''mossaCane();'''
+
  
 
Questa posso capire che lasci perplessi.
 
Questa posso capire che lasci perplessi.
Riga 1 910: Riga 1 620:
 
In pratica si dice: se rimane un solo fiammifero, non stare a chiedere all’utente quanti fiammiferi vuole prendere, ma salta subito nella funzione ''mossaCane()'' dove c’è un blocco ''if'' che gestisce questa situazione.
 
In pratica si dice: se rimane un solo fiammifero, non stare a chiedere all’utente quanti fiammiferi vuole prendere, ma salta subito nella funzione ''mossaCane()'' dove c’è un blocco ''if'' che gestisce questa situazione.
  
 +
<br/>Scommetto che morite dalla voglia di sapere perché ho continuato a ripetere quella frase “stiamo usando una variabile definita da un’altra parte come se l’avessimo definita qui!”. È giunto il momento che vi risponda.
  
Scommetto che morite dalla voglia di sapere perché ho continuato a ripetere quella frase “stiamo usando una variabile definita da un’altra parte come se l’avessimo definita qui!”. È giunto il momento che vi risponda.
+
<br/>Prendiamo in esame la variabile ‘presa’. Anzi: prendiamo in esame le due variabili ‘presa’. Dico due variabili perché si tratta di due variabili completamente diverse fra di loro, i cui valori non si intersecano mai.
 
+
 
+
Prendiamo in esame la variabile ‘presa’. Anzi: prendiamo in esame le due variabili ‘presa’. Dico due variabili perché si tratta di due variabili completamente diverse fra di loro, i cui valori non si intersecano mai.
+
  
 
Una delle due è dichiarata in ''mossaCane()'' e l’altra in ''mossaAnatra()''. Orbene, anche se hanno lo stesso nome, per il computer sono due variabili diverse e tutto ciò che faremo a una non avrà alcuna influenza su ciò che faremo all’altra. Se cambiamo, incrementiamo, azzeriamo o diminuiamo il valore di una, l’altra rimarrà inalterata.
 
Una delle due è dichiarata in ''mossaCane()'' e l’altra in ''mossaAnatra()''. Orbene, anche se hanno lo stesso nome, per il computer sono due variabili diverse e tutto ciò che faremo a una non avrà alcuna influenza su ciò che faremo all’altra. Se cambiamo, incrementiamo, azzeriamo o diminuiamo il valore di una, l’altra rimarrà inalterata.
  
 
+
<br/>Questo è ciò che si intende con ''spazio di visibilità'' di una variabile ed è un concetto importantissimo.
Questo è ciò che si intende con ''spazio di visibilità'' di una variabile ed è un concetto importantissimo.
+
  
 
Una variabile che è dichiarata all’interno di una funzione può essere vista '''SOLO''' dal codice di quella funzione. Fuori da quella funzione è assolutamente invisibile. Se dichiarate una variabile con lo stesso nome, beh, si tratta semplicemente di un’altra variabile.
 
Una variabile che è dichiarata all’interno di una funzione può essere vista '''SOLO''' dal codice di quella funzione. Fuori da quella funzione è assolutamente invisibile. Se dichiarate una variabile con lo stesso nome, beh, si tratta semplicemente di un’altra variabile.
Riga 1 927: Riga 1 634:
 
Nel C++ (ora vedremo anche il codice per quel linguaggio) le cose stanno all’incirca nella stessa maniera, solo che, essendo lui così (uffa! Mamma mia!) pedante, ci aggiunge un’altra complicazione, che è il ''mascheramento'' (che noi non useremo).
 
Nel C++ (ora vedremo anche il codice per quel linguaggio) le cose stanno all’incirca nella stessa maniera, solo che, essendo lui così (uffa! Mamma mia!) pedante, ci aggiunge un’altra complicazione, che è il ''mascheramento'' (che noi non useremo).
  
 
+
<br/>Del tutto diverse sono invece la variabile e l’array che abbiamo dichiarato '''fuori da ogni funzione'''.
Del tutto diverse sono invece la variabile e l’array che abbiamo dichiarato '''fuori da ogni funzione'''.
+
  
 
Riguardate il codice e i commenti: usiamo quella variabile e quell’array un po’ ovunque, ma il loro contenuto non va mai perso.
 
Riguardate il codice e i commenti: usiamo quella variabile e quell’array un po’ ovunque, ma il loro contenuto non va mai perso.
Riga 1 938: Riga 1 644:
 
Si dice che queste variabili, ossia quelle dichiarate fuori di ogni funzione, hanno ''visibilità globale''. Oppure semplicemente che sono ''variabili globali''.
 
Si dice che queste variabili, ossia quelle dichiarate fuori di ogni funzione, hanno ''visibilità globale''. Oppure semplicemente che sono ''variabili globali''.
  
 
+
<br/>Anche in questo caso, consoliamoci, il C++ vede le cose dallo stesso punto di vista.
Anche in questo caso, consoliamoci, il C++ vede le cose dallo stesso punto di vista.
+
  
 
Anche se, lo ammetto, se stessimo facendo un corso serissimo dovrei considerare il caso di una variabile ‘così tanto’ globale da dover essere vista addirittura da un altro file… No, no, è troppo complicato! Lasciamo stare, non posso stare qui a dirvi che basta scrivere ''extern'' all’inizio della dichiarazione di variabile…
 
Anche se, lo ammetto, se stessimo facendo un corso serissimo dovrei considerare il caso di una variabile ‘così tanto’ globale da dover essere vista addirittura da un altro file… No, no, è troppo complicato! Lasciamo stare, non posso stare qui a dirvi che basta scrivere ''extern'' all’inizio della dichiarazione di variabile…
  
 
+
<br/>Orbene, adesso mi metto qui in attesa di qualcuno che, avendo spulciato il codice per bene, mi fa notare che ''numero_fiammiferi'' è dichiarata all’interno della funzione ''inizioGioco()'', e quindi dovrebbe avere visibilità locale, ma è usata anche in altre funzioni proprio come se avesse visibilità globale…
Orbene, adesso mi metto qui in attesa di qualcuno che, avendo spulciato il codice per bene, mi fa notare che ''numero_fiammiferi'' è dichiarata all’interno della funzione ''inizioGioco()'', e quindi dovrebbe avere visibilità locale, ma è usata anche in altre funzioni proprio come se avesse visibilità globale…
+
  
 
C’è qualcuno che se n’è accorto? Bravi!
 
C’è qualcuno che se n’è accorto? Bravi!
  
 
+
<br/>Ecco, questo è un punto su cui il JavaScript e il C++ non andrebbero mai d’accordo.
Ecco, questo è un punto su cui il JavaScript e il C++ non andrebbero mai d’accordo.
+
  
 
Nel JavaScript basta non mettere la parola ''var'' prima di una variabile e quella sarà automaticamente considerata una variabile globale ANCHE SE è dichiarata all’interno di una funzione.
 
Nel JavaScript basta non mettere la parola ''var'' prima di una variabile e quella sarà automaticamente considerata una variabile globale ANCHE SE è dichiarata all’interno di una funzione.
Riga 1 957: Riga 1 660:
 
Quindi ‘numero_fiammiferi’ è una variabile globale a tutti gli effetti, e questo solo perché non c’è scritto ''var'' davanti.
 
Quindi ‘numero_fiammiferi’ è una variabile globale a tutti gli effetti, e questo solo perché non c’è scritto ''var'' davanti.
  
 
+
<br/>Ora mettiamoci nell’ordine d’idee di un programmatore in C++.
Ora mettiamoci nell’ordine d’idee di un programmatore in C++.
+
  
 
Si è detto che il C++ ci costringe a spezzare il nostro codice in blocchi. Più avanti vederemo che ci spinge anche a mettere questi blocchi su file diversi, proprio perché sia diviso in modo coerente e ordinato. Il motivo per cui è così minuzioso è perché è un linguaggio che è stato concepito per consentire a molte persone di lavorare sullo stesso progetto senza intralciarsi fra di loro. In altre parole, essendo il codice diviso in blocchi e i blocchi in file, in una squadra anche numerosa possiamo dirci: «Io lavoro su questo blocco e tu su quello» e andiamo avanti ognuno con ciò che deve fare senza curarci degli altri.
 
Si è detto che il C++ ci costringe a spezzare il nostro codice in blocchi. Più avanti vederemo che ci spinge anche a mettere questi blocchi su file diversi, proprio perché sia diviso in modo coerente e ordinato. Il motivo per cui è così minuzioso è perché è un linguaggio che è stato concepito per consentire a molte persone di lavorare sullo stesso progetto senza intralciarsi fra di loro. In altre parole, essendo il codice diviso in blocchi e i blocchi in file, in una squadra anche numerosa possiamo dirci: «Io lavoro su questo blocco e tu su quello» e andiamo avanti ognuno con ciò che deve fare senza curarci degli altri.
Riga 1 966: Riga 1 668:
 
Anzi, meglio: immaginate di essere voi ad aver dimenticato di scrivere ''var'', ma di non avere la più pallida idea di quale funzione possa essere e di aver già scritto decine e decine di file di codice… E i vostri colleghi sono tutti fermi in attesa che voi risolviate il problema perché sennò non si può compilare il programma!
 
Anzi, meglio: immaginate di essere voi ad aver dimenticato di scrivere ''var'', ma di non avere la più pallida idea di quale funzione possa essere e di aver già scritto decine e decine di file di codice… E i vostri colleghi sono tutti fermi in attesa che voi risolviate il problema perché sennò non si può compilare il programma!
  
Simpatico, nevvero? :)  
+
Simpatico, nevvero?&nbsp;:)
  
 
+
<br/>Si capisce allora perché nei forum ci siano tante polemiche: per un programmatore in JavaScript la possibilità di creare variabili globali in qualsiasi momento è una gran comodità; per un programmatore in C++ è una trappola da evitare come la peste. Entrambi hanno le loro buone ragioni.
Si capisce allora perché nei forum ci siano tante polemiche: per un programmatore in JavaScript la possibilità di creare variabili globali in qualsiasi momento è una gran comodità; per un programmatore in C++ è una trappola da evitare come la peste. Entrambi hanno le loro buone ragioni.
+
  
 
Nel C++, sia ben chiaro, al di là del fatto che non esiste la parola ''var'', è previsto un solo modo di dichiarare una variabile globale: crearla fuori da ogni funzione.
 
Nel C++, sia ben chiaro, al di là del fatto che non esiste la parola ''var'', è previsto un solo modo di dichiarare una variabile globale: crearla fuori da ogni funzione.
  
 
+
<br/>Non è questa l’unica discrepanza fra il modo di vedere le cose le programmatore C++ e quello del programmatore JavaScript. Vi ricordate che tempo fa ci siamo chieste perché nel JavaScript la parola ''length'' si scrivesse senza parentesi tonde? Allora non avevamo dato una risposta, lasciando che si potesse ipotizzare si trattava solo di una diversa sintassi. Beh, le cose sono un po’ più complicate di così.
Non è questa l’unica discrepanza fra il modo di vedere le cose le programmatore C++ e quello del programmatore JavaScript. Vi ricordate che tempo fa ci siamo chieste perché nel JavaScript la parola ''length'' si scrivesse senza parentesi tonde? Allora non avevamo dato una risposta, lasciando che si potesse ipotizzare si trattava solo di una diversa sintassi. Beh, le cose sono un po’ più complicate di così.
+
  
 
Ne JavaScript ''length'' non è un metodo (ossia una particolare funzione), bensì è una ''proprietà'', ossia un particolar tipo di variabile.
 
Ne JavaScript ''length'' non è un metodo (ossia una particolare funzione), bensì è una ''proprietà'', ossia un particolar tipo di variabile.
  
 
+
<br/>Quando ci si riferisce a un oggetto, la parola ''proprietà'' indica una variabile; questa variabile però non può essere usata come ci pare, bensì come è stato previsto dal creatore dell’oggetto. Chi ha creato gli array ha previsto che ''length'' contenesse il numero di dati inseriti; non si può usarla a caso, ma solo per gestire questo dato.
Quando ci si riferisce a un oggetto, la parola ''proprietà'' indica una variabile; questa variabile però non può essere usata come ci pare, bensì come è stato previsto dal creatore dell’oggetto. Chi ha creato gli array ha previsto che ''length'' contenesse il numero di dati inseriti; non si può usarla a caso, ma solo per gestire questo dato.
+
  
 
Fatto sta che il valore di ''length'', essendo una variabile, può essere modificato a piacere.
 
Fatto sta che il valore di ''length'', essendo una variabile, può essere modificato a piacere.
  
 
Guardate un po’ cosa succede qui:
 
Guardate un po’ cosa succede qui:
 
 
<pre><!DOCTYPE html>
 
<pre><!DOCTYPE html>
  
Riga 2 002: Riga 1 700:
 
</html>
 
</html>
 
</pre>
 
</pre>
 
 
Quello sopra è il codice HTML, questo il JavaScript (il file deve chiamarsi “provaLength.js”):
 
Quello sopra è il codice HTML, questo il JavaScript (il file deve chiamarsi “provaLength.js”):
 
 
<pre>function provaLength() {
 
<pre>function provaLength() {
 
     var output1 = document.getElementById("output1");
 
     var output1 = document.getElementById("output1");
Riga 2 023: Riga 1 719:
 
}
 
}
 
</pre>
 
</pre>
 
 
Anche in questo caso la grande flessibilità e semplicità di utilizzo del JavaScript può dare risultati inattesi, se non si sa cosa si sta facendo.
 
Anche in questo caso la grande flessibilità e semplicità di utilizzo del JavaScript può dare risultati inattesi, se non si sa cosa si sta facendo.
  
Riga 2 029: Riga 1 724:
  
 
State quindi molto attenti, nel JavaScript, quando elaborate qualcosa come
 
State quindi molto attenti, nel JavaScript, quando elaborate qualcosa come
 
 
<pre>if ( mioarray.length == miavariabile) {…</pre>
 
<pre>if ( mioarray.length == miavariabile) {…</pre>
 
 
a scrivere correttamente il simbolo ‘==’ e non ‘=’, perché potreste modificare il valore di length.
 
a scrivere correttamente il simbolo ‘==’ e non ‘=’, perché potreste modificare il valore di length.
  
 
+
<br/>Ancora una nota: se vi ricordate avevamo detto che era necessario, all’inizio del file C++, riportare un elenco delle funzioni che si erano scritte. In quel caso avevamo detto che così il compilatore poteva garantirci che non ci fossero duplicati.
Ancora una nota: se vi ricordate avevamo detto che era necessario, all’inizio del file C++, riportare un elenco delle funzioni che si erano scritte. In quel caso avevamo detto che così il compilatore poteva garantirci che non ci fossero duplicati.
+
  
 
Quello che abbiamo trattato qui è diverso, ma simile: anche in questo caso ci dobbiamo garantire che, all’interno dello stesso ''spazio di visibilità'' non ci siano nomi duplicati.
 
Quello che abbiamo trattato qui è diverso, ma simile: anche in questo caso ci dobbiamo garantire che, all’interno dello stesso ''spazio di visibilità'' non ci siano nomi duplicati.
  
 +
<br/>Bene, coraggio, il C++ ci aspetta.
  
Bene, coraggio, il C++ ci aspetta.
 
  
  
 
=== Il gioco dei fiammiferi in C++ ===
 
=== Il gioco dei fiammiferi in C++ ===
 +
 
Non possiamo però creare un programma che riguarda il gioco dei fiammiferi in un progetto che si chiama “Saluto”!
 
Non possiamo però creare un programma che riguarda il gioco dei fiammiferi in un progetto che si chiama “Saluto”!
  
Riga 2 050: Riga 1 743:
 
Come nome (“Name”) mettiamo “Gioco21” e come cartella (“create in”) la stessa, “…ProgrammiCpp/CppQt” o come si chiama il percorso che avete creato.
 
Come nome (“Name”) mettiamo “Gioco21” e come cartella (“create in”) la stessa, “…ProgrammiCpp/CppQt” o come si chiama il percorso che avete creato.
  
 +
<br/>[[File:Qt Gioco21 01.png|C++ con Qt, parte II, Qt Gioco21 01]]
  
[[File:Qt_Gioco21_01.png|C++ con Qt, parte II, Qt Gioco21 01]]
+
<br/>Vi dovreste ritrovare in una situazione simile a quella in cui ci siamo trovati nella prima versione del programma “Saluto”. Infatti Qt crea sempre un file main.cpp in cui inserisce il codice “Hello world!”.
 
+
 
+
Vi dovreste ritrovare in una situazione simile a quella in cui ci siamo trovati nella prima versione del programma “Saluto”. Infatti Qt crea sempre un file main.cpp in cui inserisce il codice “Hello world!”.
+
 
+
 
+
[[File:Qt_Gioco21_02.png|C++ con Qt, parte II, Gioco21 02]]
+
  
 +
<br/>[[File:Qt Gioco21 02.png|C++ con Qt, parte II, Gioco21 02]]
  
Avete la sicurezza di trovarvi in un nuovo progetto leggendo ciò che compare sulla barra del titolo (“Gioco21”).
+
<br/>Avete la sicurezza di trovarvi in un nuovo progetto leggendo ciò che compare sulla barra del titolo (“Gioco21”).
  
 
Anche in questo caso del codice “Hello world!” non ce ne facciamo di niente e lo sovrascriveremo.
 
Anche in questo caso del codice “Hello world!” non ce ne facciamo di niente e lo sovrascriveremo.
  
 
+
<br/>Ecco il nostro codice:
Ecco il nostro codice:
+
 
+
 
<pre>#include <iostream>
 
<pre>#include <iostream>
  
Riga 2 133: Riga 1 820:
 
   // Il ciclo while si ripete finché è necessario, ossia anche
 
   // Il ciclo while si ripete finché è necessario, ossia anche
 
   // all'infinito, in attesa che la condizione diventi falsa.
 
   // all'infinito, in attesa che la condizione diventi falsa.
   while ( presa < 1 || presa > 5 ){
+
   while ( presa < 1 || presa > 4 ){
  
 
       cout << "Quanti fiammiferi prendi (da 1 a 4)? " << endl;
 
       cout << "Quanti fiammiferi prendi (da 1 a 4)? " << endl;
 
       cin >> presa;
 
       cin >> presa;
  
       if( presa < 1 || presa > 5) {
+
       if( presa < 1 || presa > 4) {
 
         cout << "Spiacente. Devi prendere almeno un fiammifero, "
 
         cout << "Spiacente. Devi prendere almeno un fiammifero, "
 
                 "ma non più di quattro..." << endl << endl;
 
                 "ma non più di quattro..." << endl << endl;
Riga 2 176: Riga 1 863:
 
}
 
}
 
</pre>
 
</pre>
 
 
Come vedete, per quanto mi sia sforzato di rimanere il più attaccato possibile alla versione JavaScript, via via che entriamo nel mondo dal C++ siamo costretti ad allontanarci dagli altri.
 
Come vedete, per quanto mi sia sforzato di rimanere il più attaccato possibile alla versione JavaScript, via via che entriamo nel mondo dal C++ siamo costretti ad allontanarci dagli altri.
  
Riga 2 183: Riga 1 869:
 
Per poter presentare una finestra carina come quella che riusciamo a fare sommando le potenzialità di HTML5 e JavaScript, ossia con le immagini dei due giocatori e il testo disposto per bene in uno spazio organizzato, dobbiamo aspettare di usare le librerie Qt.
 
Per poter presentare una finestra carina come quella che riusciamo a fare sommando le potenzialità di HTML5 e JavaScript, ossia con le immagini dei due giocatori e il testo disposto per bene in uno spazio organizzato, dobbiamo aspettare di usare le librerie Qt.
  
 +
<br/>Però possiamo intanto introdurre dei nuovi costrutti, ossia nuovi modi di ‘costruire’ blocchi, come i due cicli ''do-while'' e ''while'' che compaiono in questo programma. Riguardo a essi non saprei bene cosa aggiungere rispetto a ciò che ho scritto sotto forma di commento nel codice.
  
Però possiamo intanto introdurre dei nuovi costrutti, ossia nuovi modi di ‘costruire’ blocchi, come i due cicli ''do-while'' e ''while'' che compaiono in questo programma. Riguardo a essi non saprei bene cosa aggiungere rispetto a ciò che ho scritto sotto forma di commento nel codice.
+
<br/>Entrambi questi tipi di blocchi servono a ripetere un certo numero di istruzioni per un numero illimitato di volte, ossia finché una determinata condizione da vera diventa falsa. Sono quindi del tutto diversi da ''for'' perché quel blocco nasce per essere ripetuto un numero predeterminato di volte.
 
+
 
+
Entrambi questi tipi di blocchi servono a ripetere un certo numero di istruzioni per un numero illimitato di volte, ossia finché una determinata condizione da vera diventa falsa. Sono quindi del tutto diversi da ''for'' perché quel blocco nasce per essere ripetuto un numero predeterminato di volte.
+
  
 
Questo tipo di blocchi, ossia quelli che si devono ripetere più di una volta, vengono di solito chiamati cicli o, in inglese, ''loop''; in questo caso la traduzione non è, diciamo, andata male, ma il significato prevalente di ''loop'' è quello di “anello”, “circuito”, “asola”, “cappio”… In un fiume, ad esempio, “ansa”.
 
Questo tipo di blocchi, ossia quelli che si devono ripetere più di una volta, vengono di solito chiamati cicli o, in inglese, ''loop''; in questo caso la traduzione non è, diciamo, andata male, ma il significato prevalente di ''loop'' è quello di “anello”, “circuito”, “asola”, “cappio”… In un fiume, ad esempio, “ansa”.
Riga 2 193: Riga 1 877:
 
Per indicare una ripetizione del blocco si usa il parolone ''iterazione''.
 
Per indicare una ripetizione del blocco si usa il parolone ''iterazione''.
  
 
+
<br/>Anche se è comodo avere due tipi di blocchi, un tipo che si ripete un numero non preordinato di volte e un altro di cui posso con facilità controllare quante volte si ripete (detto con il parolone: quante ''iterazioni'' compie), la verità è che posso sempre forzare la natura di questi due blocchi per far loro fare ciò che più mi piace.
Anche se è comodo avere due tipi di blocchi, un tipo che si ripete un numero non preordinato di volte e un altro di cui posso con facilità controllare quante volte si ripete (detto con il parolone: quante ''iterazioni'' compie), la verità è che posso sempre forzare la natura di questi due blocchi per far loro fare ciò che più mi piace.
+
 
+
 
<pre>int iterazioni = 0;
 
<pre>int iterazioni = 0;
 
while ( iterazioni < 10 ) {
 
while ( iterazioni < 10 ) {
Riga 2 201: Riga 1 883:
 
}
 
}
 
</pre>
 
</pre>
 
 
è un blocco che di per sé nasce per essere ripetuto un numero imprecisato di volte, ma possiamo prevedere con grande facilità che compirà esattamente 10 iterazioni.
 
è un blocco che di per sé nasce per essere ripetuto un numero imprecisato di volte, ma possiamo prevedere con grande facilità che compirà esattamente 10 iterazioni.
 
 
<pre>for ( int iterazioni = 0; iterazioni < 10; iterazioni++ ) {
 
<pre>for ( int iterazioni = 0; iterazioni < 10; iterazioni++ ) {
 
   iterazioni--;
 
   iterazioni--;
 
}
 
}
 
</pre>
 
</pre>
 
 
nascerebbe per ripetersi solo 10 volte, ma temo che proseguirà per sempre…
 
nascerebbe per ripetersi solo 10 volte, ma temo che proseguirà per sempre…
  
 +
<br/>La differenza tra il ciclo ''do-while'' e il ciclo ''while ''è che in quest’ultimo la condizione viene letta subito, perciò, se questa è falsa, il ciclo non viene proprio eseguito; invece nel primo la condizione viene letta alla fine, perciò almeno una volta le istruzioni contenute vengono eseguite.
  
La differenza tra il ciclo ''do-while'' e il ciclo ''while ''è che in quest’ultimo la condizione viene letta subito, perciò, se questa è falsa, il ciclo non viene proprio eseguito; invece nel primo la condizione viene letta alla fine, perciò almeno una volta le istruzioni contenute vengono eseguite.
+
<br/>L’unica variabile globale che rimane nel nostro codice C++ è ‘fiammiferi’, ma, essendo i programmatori C++ così riottosi nel dichiarare variabili globali, non possiamo evitare di esercitarci nella domanda se davvero sia indispensabile avere una variabile globale. E la risposta è ovviamente no, non è indispensabile.
 
+
 
+
L’unica variabile globale che rimane nel nostro codice C++ è ‘fiammiferi’, ma, essendo i programmatori C++ così riottosi nel dichiarare variabili globali, non possiamo evitare di esercitarci nella domanda se davvero sia indispensabile avere una variabile globale. E la risposta è ovviamente no, non è indispensabile.
+
  
 
Infatti ‘fiammiferi’ potrebbe essere dichiarata all’interno di ''main()'' e passata alle varie funzioni durante l’invocazione – ad esempio, ''mossaCane(fiammiferi)''.
 
Infatti ‘fiammiferi’ potrebbe essere dichiarata all’interno di ''main()'' e passata alle varie funzioni durante l’invocazione – ad esempio, ''mossaCane(fiammiferi)''.
  
 
Le medesime funzioni potrebbero restituire un intero, che sarebbe il nuovo numero di fiammiferi rimasti, ossia il valore da inserire nella variabile ‘fiammiferi’.
 
Le medesime funzioni potrebbero restituire un intero, che sarebbe il nuovo numero di fiammiferi rimasti, ossia il valore da inserire nella variabile ‘fiammiferi’.
 
 
<pre>int mossaCane(int nuovavariabile);
 
<pre>int mossaCane(int nuovavariabile);
 
int mossaAnatra(int nuovavariabile);
 
int mossaAnatra(int nuovavariabile);
 
</pre>
 
</pre>
 
 
Il valore restituito andrebbe, in main(), inserito nella variabile ‘fiammiferi’, che a questo punto diverrebbe una pura variabile locale.
 
Il valore restituito andrebbe, in main(), inserito nella variabile ‘fiammiferi’, che a questo punto diverrebbe una pura variabile locale.
  
 +
<br/>Tutto questo è lasciato come esercizio perché non è al di sopra delle vostre capacità, anche se ci sono diverse modifiche da apportare al programma.
  
Tutto questo è lasciato come esercizio perché non è al di sopra delle vostre capacità, anche se ci sono diverse modifiche da apportare al programma.
+
<br/>Scrivere questo codice vi potrebbe far apparire molto desiderabile l’uso delle variabili globali, e non sarebbe una percezione del tutto sbagliata. Per fortuna il C++ ha inventato un altro modo per gestire questo problema, ossia le variabili che devono essere modificate da più funzioni.
 
+
  
Scrivere questo codice vi potrebbe far apparire molto desiderabile l’uso delle variabili globali, e non sarebbe una percezione del tutto sbagliata. Per fortuna il C++ ha inventato un altro modo per gestire questo problema, ossia le variabili che devono essere modificate da più funzioni.
 
  
  
 
Allora reggetevi perché stanno per arrivare ''references'' e puntatori.
 
Allora reggetevi perché stanno per arrivare ''references'' e puntatori.
 +
[[Category:C++|Category:C++]]

Versione attuale delle 14:49, 19 nov 2014

Tutorial C++ con le librerie Qt – Parte II

Come superare gli schieramenti

Se uno ha troppi amici…

Ripartiamo da dov’eravamo rimasti.

Vorrei che provaste a confrontare queste due righe di codice:

Nella funzione salutaUtente:

segnale_di_ritorno = -1;

Nella funzione interrogaUtente:

if ( verifica == -1 ) {

A parte le varie parentesi, tonda e graffa, ci vedete qualche differenza?

Vi salta all’occhio lo strano simbolo ‘==’?

Visto che esiste l’equivalente in JavaScript (e anche in C, tanto per cambiare), adesso vedremo cosa significa in quel linguaggio. Però diamo prima un’occhiata a questo codice Scratch, che ci aprirà un po’ la strada:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Okay, apparentemente non c’entra nulla, ma ci serve un po’ di pazienza.

Questo esempio è piuttosto semplice, ma introduce un po’ una complicazione: un’istruzione SE contenuta dentro un’altra.

Proviamo a esprimere a parole le istruzioni di questo programma, proprio come se stessimo parlando a un robottino e gli dovessimo spiegare passo passo cosa fare:

Quando faccio click, tu (robottino) memorizza questi due dati: Mario e Maria in due celle di memoria, amico1 e amico2; poi chiedi a chi si avvicina: “Come ti chiami?”. Dopo procedi così:

  • se la risposta che ti hanno dato è uguale a quello che hai scritto nella variabile amico1, allora saluta;
  • altrimenti (quindi, se la risposta non è uguale a quello che è scritto in amico1), confronta la risposta con quello che è scritto in amico2; se stavolta è uguale, saluta;
  • altrimenti, digli che non lo conosci.


Wow! Faticoso, non è vero? Mi accorgo ora che ho messo un’istruzione di troppo: l’istruzione porta nome a risposta si può tranquillamente ignorare. Ma, a parte quella, direi che la vita del robottino è un po’ complicata.

Pensate un po’ se voleste istruirlo a riconoscere 4 amici, anziché 2. Guardate un po’ come verrebbe:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Anche qui c’è un’istruzione di troppo, la stessa di prima, ma non è quella che ci sta complicando la vita. La domanda è: come verrebbe il programma se il robottino dovesse imparare a salutare tutti i vostri compagni di classe o tutte le persone che conoscete?

Chi ci capirebbe più niente, in tutti quei SE… ALLORA… ALTRIMENTI?


Per fortuna il robottino è furbo e ci suggerisce un’alternativa:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Questo esempio fa la stessa cosa del precedente, ma introduce una cosa nuova, che fin qui non avevamo trattato: le liste.

Cos’è una lista?

Pensiamo ai compiti da fare a casa: il maestro/a o professore/essa ci danno una serie di cose da studiare o di esercizi da fare. Certo, possono essere tutti diversi fra di loro, tipo leggere e ripetere pagine di storia; oppure condurre l’analisi logica di alcune frasi; oppure risolvere problemi di matematica; o molte altre cose. Però, anche se sono tutte diverse, per noi rientrano in un’unica categoria: sono i compiti per casa.


Tant’è che sul diario li scriviamo tutti insieme: a quella determinata data scriviamo tutte le materie che dobbiamo avere studiato, siano esse storia o italiano o matematica.

Altri esempi simili possono essere la lista della spesa o la rubrica del telefono: in una sono segnati oggetti che sono diversissimi fra di loro, come la verdura e i detersivi, mentre nella seconda ci possono essere nomi anche di persone che non si conoscono l’un con l’altra.


Ma tutte queste cose hanno qualcosa in comune, che è il motivo per cui le scriviamo tutte di seguito, una dietro l’altra:

  • i compiti hanno in comune la data in cui devono essere svolti;
  • i nomi nella rubrica hanno in comune di essere nostri amici o parenti;
  • gli oggetti nella lista della spesa hanno in comune di dover essere tutti acquistati oggi.

Quindi: quando una serie di cose, simili o dissimili fra di loro, hanno un punto in comune, di solito preferiamo non considerarle come tante cose singole, ma come un’unica lista di tante cose.


Anche quando creiamo una variabile possiamo pensare di doverci mettere un dato singolo, che non ha nessun rapporto con il contenuto delle altre variabili, oppure di doverci mettere una serie di dati che hanno qualcosa in comune.


Nell’esempio Scratch precedente abbiamo deciso che non aveva senso creare una serie di variabili “amico1”, “amico2”, “amico3”… Abbiamo invece preferito creare un’unica lista “Amici” in cui ci fosse posto per tutti.


Sono contento che abbiamo avuto modo di parlare di questo perché anche nel JavaScript e nel C++ abbiamo delle cose simile alle liste, ma si chiamano array, che è una parola inglese che significa schieramento, oppure varietà, gamma di oggetti. Come sapete, le parole ogni tanto hanno più significati e delle volte anche distanti fra di loro.


Però dobbiamo rimandare di un pochino il momento in cui affronteremo gli array in JavaScript perché ci eravamo ripromessi di guardare il significato del doppio simbolo di uguale, quella strana scritta ‘==’ che abbiamo trovato nel nostro programma.


Partiamo dal JavaScript:

<!DOCTYPE html>

<html lang="it-IT">
<head>
  <meta charset="utf-8">

  <title>JavaScript e HTML5 - un pulsante che saluta... a volte!</title>

  <script type="text/javascript">
    function cambioTesto() {
      var utente = document.getElementById("risposta").value;

      if ( 1 == controllaNome(utente) ) {
        document.getElementById("testoDaCambiare").innerHTML = "Ciao, " + utente + "!";
      }
      else {
        document.getElementById("testoDaCambiare").innerHTML = "Non ti conosco, " + utente + "!";
      }

    }

    function controllaNome(persona) {

      var risultato;

      if (persona == "Mario" || persona == "Maria" 
          || persona == "Gianni" || persona == "Gianna") {
        risultato = 1;
      }
      else {
        risultato = 0;
      }

      return risultato;
     }
  </script>

  <style>
    .fraseCattiva {
      color : red;
      text-decoration : underline;
      text-transform : uppercase;
    }
    </style>
</head>

<body>

  <div>
    <p>Sappi che oggi sono d'umore un po’ scontroso. Può darsi che ti saluti e può darsi di <span class="fraseCattiva">no</span>.</p>
    <p>Tu comunque provaci lo stesso…</p>
  </div>

  <div>
    <label for="risposta">Qual è il tuo nome?</label>
    <input type="text" id="risposta" />
  </div>

  <div>
    <label for="cambiaTesto">Pulsante che modificherà il testo sottostante --></label>
    <input type="button" id="cambiaTesto" value="Premimi per cambiare il testo"
         onclick="cambioTesto();" />
  </div>

  <div>
    <p id="testoDaCambiare">Il testo contenuto in questo paragrafo cambierà quando sarà premuto il pulsante soprastante.</p>
  </div>

  </body>
</html>

Come primo commento lasciatemi dire: che brutto!

Lo so che ora stavamo parlando d’altro, e fra un attimo riprendo il filo, però prima o poi a questa osservazione bisognava arrivarci: adesso abbiamo un codice dove si trovano mischiati HTML5, JavaScript e CSS. Non ci si capisce più niente. Se vogliamo avventurarci nel mondo del C++ dobbiamo essere molto più precisi, perché nel C++ il codice deve stare diviso in blocchi coerenti.


Cominciamo da questo: entriamo in una cartella dove possiamo salvare i nostri file che non sono C++ – oppure creiamone una.

Poi facciamo il copia-incolla del codice di cui sopra e chiamiamolo BruttaRisposta.html

Fin qui non ci dovrebbero essere novità. Ora però creiamo altri due file, vuoti:

  • BruttaRisposta.js
  • BruttaRisposta.CSS

Tagliamo dal file BruttaRisposta.html le righe

  function cambioTesto(){
     var utente = document.getElementById("risposta").value;

     if ( 1 == controllaNome(utente) ) {
       document.getElementById("testoDaCambiare").innerHTML = "Ciao, " + utente + "!";
     }
     else {
       document.getElementById("testoDaCambiare").innerHTML = "Non ti conosco, " + utente + "!";
     }

   }

     function controllaNome(persona) {

       var risultato;

       if (persona == "Mario" || persona == "Maria" 
            || persona == "Gianni" || persona == "Gianna") {
         risultato = 1;
       }
       else{
         risultato = 0;
       }

       return risultato;
     }

e incolliamole nel file BruttaRisposta.js.


Nel file BruttaRisposta.html modifichiamo le righe:

<script type="text/javascript">
</script>

in questo modo:

<script type="text/javascript" src="BruttaRisposta.js"></script>

Dallo stesso file facciamo il taglia delle seguenti righe:

  .fraseCattiva {
     color           : red;
     text-decoration : underline;
     text-transform  : uppercase;
   }

e incolliamole nel file BruttaRisposta.CSS

Sempre nel file BruttaRisposta.html, modifichiamo le seguenti righe:

 <style>
</style>

in modo che diventino così:

 <link rel="stylesheet" href="BruttaRisposta.CSS" type="text/css" />

(di due righe ne rimane una)


A questo punto dovremmo trovarci in questa situazione:


Un file BruttaRisposta.html con questo codice dentro:

<!DOCTYPE html>

<html lang="it-IT">
<head>
  <meta charset="utf-8">

  <title>JavaScript e HTML5 - un pulsante che saluta... a volte!</title>

  <script type="text/javascript" src="BruttaRisposta.js"></script>

  <link rel="stylesheet" href="BruttaRisposta.CSS" type="text/css" />
</head>

<body>

  <div>
    <p>Sappi che oggi sono d'umore un po’ scontroso. Può darsi che ti saluti e può darsi di <span class="fraseCattiva">no</span>.</p>
    <p>Tu comunque provaci lo stesso…</p>
  </div>

  <div>
    <label for="risposta">Qual è il tuo nome?</label>
    <input type="text" id="risposta" />
  </div>

  <div>
    <label for="cambiaTesto">Pulsante che modificherà il testo sottostante --></label>
    <input type="button" id="cambiaTesto" value="Premimi per cambiare il testo"
         onclick="cambioTesto();" />
  </div>

  <div>
    <p id="testoDaCambiare">Il testo contenuto in questo paragrafo cambierà quando sarà premuto il pulsante soprastante.</p>
  </div>

  </body>
</html>

Un file BruttaRisposta.js con questo codice dentro:

function cambioTesto() {
    var utente = document.getElementById("risposta").value;

    if ( 1 == controllaNome(utente) ) {
        document.getElementById("testoDaCambiare").innerHTML = "Ciao, " + utente + "!";
    }
    else {
        document.getElementById("testoDaCambiare").innerHTML = "Non ti conosco, " + utente + "!";
    }

}

function controllaNome(persona) {
    var risultato;

    if (persona == "Mario" || persona == "Maria" 
           || persona == "Gianni" || persona == "Gianna") {
        risultato = 1;
    }
    else {
        risultato = 0;
    }

    return risultato;
 }

Un file BruttaRisposta.CSS con questo codice dentro:

.fraseCattiva {
   color : red;
   text-decoration : underline;
   text-transform : uppercase;
 }

I tre file sembrano separati fra di loro, ma non lo sono: finché li avremo tutti e tre nella stessa cartella, le nuove istruzioni nel file HTML porteranno il browser a caricare tutti e tre i file e ad usarli come se fossero tutti scritti nello stesso file.


Ossia, quando il browser leggerà:

<script type="text/javascript" src="BruttaRisposta.js"></script>

andrà a cercare il file BruttaRisposta.js e lo caricherà in memoria per intero, e solo dopo che avrà finito questa operazione proseguirà a leggere il resto del documento HTML.

Lo stesso accadrà con il file BruttaRisposta.CSS all’istruzione:

<link rel="stylesheet" href="BruttaRisposta.CSS" type="text/css" />

Mentre osservate con gioia la chiarezza e pulizia del codice che siamo riusciti a ottenere, una vocina potrebbe suggerirvi nella testa: «Ehi! Ma è la stessa cosa che succedeva nel C++ con l’istruzione #include <iostream>!»


Esatto!

A dire il vero da un punto di vista tecnico non sono la stessa cosa, ma il concetto di base è lo stesso.


Ottimo! Ora abbiamo imparato a dividere il nostro codice su più file, che è una delle cose che rende il C++ così utile e apprezzato; sarà bene che sappiate, infatti, che noi ci sforzeremo di disubbidire perché siamo appena all’inizio, ma gli ambienti di programmazione in C++ fanno di tutto per convincere i programmatori a spezzare il codice su più file.

Dividere il codice in più file è indispensabile in una forma di programmazione, che si chiama programmazione a oggetti, che ha molti estimatori.


Adesso diamo un’occhiata al nostro file JavaScript, così bello pulito, e paragoniamo queste due righe:

if ( 1 == controllaNome(utente) ) {
    risultato = 1;

che dovrebbero essere rispettivamente la 4 e la 19 – o giù di lì, se nell’incollare abbiamo lasciato qualche riga bianca.


Notiamo subito che nella prima compare di nuovo il simbolo ‘==’, e immagino che per voi ormai sia chiaro cosa significa. Ma possiamo cercare ispirazione anche in ciò che abbiamo visto in Scratch:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

La prima istruzione dice: prendi la risposta che ottieni e copiala in una cella di memoria a cui ho messo l’etichetta Nome (o, per brevità: nella variabile Nome).

La seconda invece dice: CONFRONTA se quello che è contenuto nella variabile amico1 è uguale a quello che è contenuto nella variabile risposta.


Ecco dunque che Scratch ci offre due possibili modi di lavorare con le variabili: copiare i valori da una all’altra oppure confrontare il valore di una con il valore dell’altra.


Anche il JavaScript ci consente di compiere queste due operazioni, con l’unico difetto che la sintassi da usare è così simile, nei due casi, che può capitare di confondersi.


Mettiamo che io abbia creato una variabile qualsiasi, chiamiamola “mia_variabile”. In JavaScript:

var mia_variabile;

A questo punto ci posso inserire dentro dei valori:

mia_variabile = 4;

Dopo questa istruzione, dentro la cella di memoria etichettata mia_variabile si troverà il dato ‘4’.

Dopo qualche migliaio di righe di programma, non siamo sicuri se questo dato sia stato modificato o no, per cui chiediamo di verificare, ossia diciamo al computer: «SE il dato contenuto in mia_variabile è uguale a 4, allora…»

Ecco qui come viene:

if ( mia_variabile == 4) …

Eccolo lì! Il mistero è svelato: il simbolo ‘==’ significa confronta; non serve a inserire dati dentro la variabile, bensì a leggerli e a porli in paragone con altri dati. Quindi i due simboli (‘=’ e ‘==’) somigliano, ma sono completamente diversi.

Se per errore scriviamo:

if ( mia_variabile = 4) …

ci facciamo del male da soli. Infatti quello che succederà dentro la parentesi sarà che il computer, ubbidendo alle nostre istruzioni, inserirà il dato ‘4’ nella variabile mia_variabile. Non solo, ma quando avrà finito, si confermerà da solo: «Tutto ok, operazione andata a buon fine», che è un segnale di ritorno positivo, ossia uguale a “vero”, e quindi potrebbe arrivare a questa brillante conclusione: il contenuto della parentesi è vero!

Di conseguenza potrebbe eseguire sempre il codice SE… ALLORA, e mai quello ALTRIMENTI.


Questo errore è veramente comune, tanto che c’è chi consiglia di abituarsi a scrivere alla rovescia:

if ( 4 == mia_variabile ) …

che apparentemente può sembrare assurdo, ma invece funziona!

Pensiamoci un po’. Il significato dell’istruzione è: «confronta il valore 4 con il dato contenuto nella variabile mia_variabile

Il che è assolutamente identico a dire: «confronta il dato contenuto contenuto in mia_variabile con il numero 4»!

Il vantaggio è che, se per errore scrivessimo:

if ( 4 = mia_variabile ) …

in linguaggi come il C++ il compilatore si fermerebbe e ci chiederebbe cosa cappero stiamo scrivendo. 4 è un numero, e non si può dire: scrivi il contenuto di mia_variabile in 4, non ha senso!

Nel caso del JavaScript, invece, probabilmente l’esecuzione del codice si interromperebbe, facendoci capire che da qualche parte abbiamo sbagliato qualcosa.


Possiamo ora leggere il nostro codice JavaScript per essere sicuri di averlo capito bene:

Cominciamo dalla funzione cambioTesto:


var utente = document.getElementById("risposta").value;

Dovrebbe essere chiara. Vuol dire:

  • trova l’elemento HTML con id="risposta"
  • leggi il suo contenuto
  • crea la variabile utente e inserisci questo contenuto lì dentro

if ( 1 == controllaNome(utente) ) {

Questa può richiedere un po’ più di ragionamento.

L’istruzione dice: CONFRONTA (‘==’) se ‘1’ e il valore di ritorno di controllaNome sono uguali…

A questo punto, l’esecuzione salta da qui fin dentro la funzione controllaNome per cercare di avere il suo segnale di ritorno. Nel salto, si porta con sé il valore contenuto nella neonata variabile ‘utente’, perché dovrà inserirlo nella variabile che è lì in attesa, cioè quella che è scritta dentro la parentesi dopo il nome di funzione controllaNome.


Saltiamo anche noi dentro controllaNome, ma ricordiamoci che poi dovremo tornare qui.


function controllaNome(persona) {

A queste punto, nella variabile ‘persona’ è stato copiato il contenuto della variabile ‘utente’.


var risultato;

Crea un’altra variabile.


if (persona == "Mario" || persona == "Maria" || persona == "Gianni" || persona == "Gianna") {

Ahia!

Questa può far male, lo ammetto :)

Leggiamola con calma. Il simbolo ‘||’ sembra una cosa molto misteriosa, ma vuol dire solo ‘oppure’.

Lasciate che provi a tradurre questa istruzione in linguaggio corrente:

«SE la variabile persona contiene Mario OPPURE la variabile persona contiene Maria OPPURE la variabile persona contiene Gianni OPPURE la variabile persona contiene Gianna, ALLORA…»


Non è così difficile da interpretare: il simbolo || dice al computer: me ne basta una.

Ossia: io ti do due possibilità, una è quella a sinistra del simbolo e una è quella a destra; se anche solo una delle due è vera, allora mi devi rispondere ‘vero!’.

Da un altro punto di vista: la condizione è falsa se TUTTE le condizioni sono false.


risultato = 1;

Si arriva a questo punto qui solo se la variabile ‘persona’ contiene uno dei 4 nomi sopra elencati.


else{

risultato = 0;

(ALTRIMENTI) Si arriva qui se l’utente non ha digitato nessuno dei 4 nomi previsti.


return risultato;

Se l’utente ha digitato uno dei 4 nomi, il segnale di ritorno sarà 1, altrimenti sarà 0.


if ( 1 == controllaNome(utente) ) {

Questo rigo l’avevamo già visto, ma ho preferito ritornare qui perché il processo fosse più chiaro.

Adesso il computer ha il valore di ritorno di controllaNome, che può essere solo 0 oppure 1 (abbiamo visto perché). Quindi può stabilire se il confronto con 1 dà vero o falso.

Le ultime due righe non sto nemmeno a spiegarle perché spero siano chiarissime.


Confessioni e paroloni

Va bene, lo ammetto: lo sto facendo apposta.

In effetti il codice JavaScript avrebbe potuto essere scritto così:

function cambioTesto() {
    var utente = document.getElementById("risposta").value;

    if (utente == "Mario" || utente == "Maria" 
          || utente == "Gianni" || utente == "Gianna") {
        document.getElementById("testoDaCambiare").innerHTML = "Ciao, " + utente + "!";
    }
    else {
        document.getElementById("testoDaCambiare").innerHTML = "Non ti conosco, " + utente + "!";
    }
 }

e avrebbe funzionato lo stesso.


Il fatto è che dobbiamo abituarci a scrivere funzioni, per cui anche in questo caso in cui si sarebbe potuta saltare, non è stata una cattiva idea scriverla: adesso abbiamo una funzione che svolge un compito preciso ed è possibile che un domani ci torni comodo un’altra volta. Nel qual caso, sappiamo dove trovarla. È un pezzo di codice riutilizzabile.


E poi avete ragione: tutte queste righe di codice solo per spiegare che ‘==’ vuol dire ‘confronta’…

Va bene, vorrà dire che scriveremo anche il codice con gli array, ossia l’equivalente delle liste di Scratch.


Ma prima del divertimento dobbiamo levarci un sassolino dalla scarpa. Finora ho usato espressioni del tipo: “il dato contenuto nella cella di memoria etichettata…”; oppure: “creare una variabile”; o anche: “la funzione che abbiamo chiamato nomeFunzione”; ecc. ecc.

Adesso è venuto il momento di essere un gocciolino più precisi, nel senso di imparare un po’ di termini appropriati.


Per ora preoccupiamoci solo delle variabili.

È chiaro a tutti che una variabile è una cella di memoria a cui abbiamo dato un’etichetta e che quella cella di memoria il computer non la gestisce come vuole lui, bensì ci inserisce solo i dati che decidiamo noi? Okay, allora non userò più l’espressione ‘cella di memoria’, ma parlerò solo di variabili.

Allora, il dato contenuto in una variabile è detto valore della variabile. Questo non è vero solo per le variabili numeriche, bensì anche per le variabili che contengono testo. Ossia, se in C++ scrivo:

string amico1 = "Mario"

per riferirmi al dato contenuto nella variabile ‘amico1’ uno dovrò dire: «il valore della variabile ‘amico1’ di tipo string è “Mario”».

A proposito, visto che abbiamo evitato l’argomento nella prima parte, sarà bene sapere fin d’ora che la parola inglese string NON significa stringa, come viene normalmente tradotta. Infatti le stringhe delle scarpe si chiamo laces. String significa corda, filo, cordone, ma in senso figurato anche serie, sequenza, e in quest’ultimo significato è stata adottata dalla matematica prima, e dall’informatica poi. Le variabili che dovevano contenere testo furono chiamate string a significare una sequenza di caratteri.

Adesso, se volessimo fare una lezione barbosissima, dovremmo affrontare un argomento davvero complicato, perché in C++ non potete creare una variabile, però potete dichiararla, definirla o inizializzarla, che sono tre cose diverse fra di loro. Però per ora tralasceremo questo argomento e troveremo un compromesso fra di noi, a livello amichevole: useremo le parole dichiarare e definire come se fossero sinonimi, tenendo però presente che verrà il momento di distinguere questi due passaggi.


Ancora un punto e potremo tornare al nostro codice.

Vi ricordate come siete stati bravi a scoprire che length() era una funzione perché il nome era seguito da parentesi tonde? Vi andrebbe bene se d’ora innanzi procedessimo sullo stesso sentiero, ossia se scrivessi i nomi di funzione sempre seguiti da parentesi tonde? Perché questa sarebbe la convenzione.

Ad es., poco sopra avrei dovuto scrivere: “il valore di ritorno di controllaNome(), che può essere…”. Sarebbe molto comodo perché non correremmo più il rischio di confondere una variabile con una funzione.


Chiusa la piccola parentesi sui termini, devo confessare un altro piccolo dispetto, nel caso qualcuno non se ne fosse accorto.

Vi avevo detto che molto spesso si usa 0 come valore di ritorno dandogli senso positivo, ossia di “zero errori”. Questa però non è assolutamente una regola, anzi! Può darsi benissimo che una funzione restituisca 0 proprio per indicare una situazione di errore o comunque problematica. In tal caso, diciamo che andrebbe interpretata come “risultati 0”.

Questo significa che:

  • quando usate una funzione preparata da qualcun altro (vedi length()), dovete andare a leggere quali segnali di ritorno ha previsto chi l’ha scritta;
  • quando scrivete una funzione, vi potete considerare liberi di scegliere i valori di ritorno che preferite!

Ad esempio, nella funzione controllaNome… OPS! Volevo dire controllaNome(), scusate!… Nella funzione controllaNome() abbiamo deciso di restituire 1 per significare “ho trovato una corrispondenza” e 0 per dire “nessuna corrispondenza trovata”.


Visto che questo è un tutorial sul C++, vediamo infine come verrebbe il nostro codice in C++. Visto che stiamo parlando delle basi del C++, quelle che sono cambiate poco rispetto al C, la somiglianza con il JavaScript è davvero tanta:

#include <iostream>

using namespace std;

int controllaNome(string persona);
void cambioTesto();

int main()
{
   cambioTesto();
   return 0;
}

void cambioTesto()
{
   string utente;
   cout << "Qual è il tuo nome? ";
   cin >> utente;

   if ( 1 == controllaNome(utente) ) {
      cout << "Ciao, " << utente << "!" << endl << endl;
   }
   else {
      cout << "Non ti conosco, " << utente << "!" << endl << endl;
   }
}

int controllaNome(string persona)
{
   int risultato;

   if ( persona == "Mario" || persona == "Maria"
        || persona == "Gianni" || persona == "Gianna" ) {
      risultato = 1;
   }
   else {
      risultato = 0;
   }

   return risultato;
}

Direi che, se si è capito come funziona la versione JavaScript, non dovrebbe essere un problema decifrare questo codice.

Anche in questo caso si può fare l’equivalente della versione breve:

#include <iostream>

using namespace std;

void cambioTesto();

int main()
{
    cambioTesto();
    return 0;
}

void cambioTesto()
{
    string utente;
    cout << "Qual è il tuo nome? ";
    cin >> utente;

    if ( utente == "Mario" || utente == "Maria"
          || utente == "Gianni" || utente == "Gianna" ) {
        cout << "Ciao, " << utente << "!" << endl << endl;
    }
    else {
        cout << "Non ti conosco, " << utente << "!" << endl << endl;
    }
}

Per poter scrivere il nostro programmino con gli array, però, dobbiamo introdurre prima un’altra novità.

Infatti Scratch ci offriva un’operazione interessante da compiere sulle liste, ossia questa qui:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Bisogna ammettere che è molto comoda: se ho una lista di 100 amici, con una sola istruzione posso sapere se un nome è in quella lista o no.

Purtroppo il JavaScript non ci fornisce niente di equivalente, come non ce la fornirebbe il C. Il C++ invece, vedremo, sa essere un pochino più amichevole in questo genere di operazioni, per per arrivare a quello dobbiamo perdere un po’ di tempo sulla programmazione ‘tradizionale’.


Vediamo di scoprire come si può risolvere il problema.

La soluzione parte dal presupposto che la lista debba per forza essere ordinata. È vero che nella vita abbiamo spesso a che fare con liste apparentemente disordinate, come ad esempio la lista della spesa, in cui scriviamo le cose via via che ci vengono in mente, ma per il computer le cose non stanno così.

Noi possiamo anche essere coscienti che quando abbiamo inserito i nomi dei nostri amici l’abbiamo fatto più o meno a caso, ma il computer non legge nei nostri pensieri: per quel che ne sa lui, quella sequenza può essere ordinata secondo un principio misterioso che nessuno gli ha spiegato. Questo significa che senza il nostro permesso non si azzarderà mai a cambiare l’ordine in cui abbiamo immesso i dati.

Pertanto, se abbiamo inserito il nome “Gianni” per terzo, per quel che riguarda il computer quel nome rimarrà sempre in terza posizione, o almeno finché noi non gli diremo in modo esplicito di spostarlo.


Attenzione! Questo non è vero per la rubrica del cellulare perché lì il programma è stato pensato apposta per tenere i nomi in ordine alfabetico. Anche questo si può fare, ovviamente, ossia si può creare una funzione che fa in modo che, via via che si inseriscono i nomi, vengano subito spostati nella posizione corretta secondo l’alfabeto.

Quel che è importante tenere presente, però, è che bisogna specificare al computer di compiere questa azione, altrimenti lui non la farà: terrà gli oggetti nella sequenza in cui li abbiamo inseriti anche se noi non abbiamo usato nessun criterio.


Perché specifico tutto questo? Perché, se ci riflettete un secondo, questo implica una cosa importante: il computer usa un ordine interno per tenere in memoria i dati che gli passiamo in una lista.

In altre parole, quando scriviamo i nomi dei nostri amici, lui non memorizza in maniera confusa: «Che ha detto? Mario? Mario, okay. E poi? Maria? Mario o Maria? Si sarà mica sbagliato? E Gianna? E poi Gianni? Ma si chiamano tutti nella stessa maniera?»

No, il nostro computer memorizzerà correttamente:

Mario → posizione numero 1

Maria → posizione numero 2

Gianni → posizione numero 3

Gianna → posizione numero 4


Secondo voi questo significa che c’è un numero associato a ogni nome?

Beh, per ora diciamo di sì, anche se più avanti incontreremo delle buffe creature come gli array associativi oppure le list del C++ in cui questo numero, se esiste, per noi è irraggiungibile e non ci si può riferire ad esso per recuperare i nostri dati. Ma per ora useremo delle liste un po’ meno eccentriche che hanno sempre questo numero associato a ogni dato.

Intanto diciamo come si chiama questo numero: si chiama indice. Non bisogna pensare all’indice dei libri, bensì alla parola indice che usano i matematici. E sì, perché di creature bizzarre non è pieno solo il C++, ma anche fra gli esseri umani ce ne sono un sacco un po’ strampalati: pensate che ce ne sono alcuni a cui la matematica piace davvero e passano la vita a studiarla!

Beh, c’è stato un momento nel passato in cui qualcuno di loro, osservando i numeri interi (vi ricordate cosa sono, vero?) si è chiesto: ma cosa hanno in comune fra di loro, tutti questi numeri? Beh, fra le varie risposte possibili ha osservato che ognuno di essi è separato dal successivo sempre della stessa quantità, che è 1. Ha anche realizzato che questo non è vero per tutti i numeri, ma lo è per gli interi.

A quel punto ha deciso che era venuto il momento di creare un nuovo concetto matematico: la progressione aritmetica.

La progressione aritmetica dice che si può scegliere una serie di numeri lunga quanto si vuole; se, osservandoli, ci si rende conto che sono tutti alla stessa ‘distanza’ fra di loro, allora sono in progressione. Ad esempio, se scegliamo -2, 0, 2, 4, 6, 8, questi sono sei numeri in progressione; la ‘distanza’ fra un numero e il successivo è sempre 2.

Metto ‘distanza’ fra virgolette perché in matematica si dovrebbe dire ragione (ma, voglio dire, vi sembra ragionevole?).

Beh, se dei numeri sono in progressione, allora possiamo riferirci a loro dicendo: il primo della progressione, il secondo della progressione, il terzo della progressione, e così via. Sapete come si chiama questo numerino “primo”, “secondo”, “terzo”…? Eccolo lì: si chiama indice.


Ora, quelli di voi che la pensano come me si confermeranno nell’idea che i matematici sono proprio strani, ma la realtà è che gli informatici sono molto più strani di loro! Infatti i matematici si erano messi d’accordo su un punto che mi sembrerebbe molto sensato: un indice deve comunque essere superiore a zero. Ossia, quando si chiamano i numeri della progressione non si può dire “lo zeeresimo della progressione”, ma bisogna cominciare con “primo”!

Quando sono arrivati gli informatici (ossia quelli che traducono string con stringa, tanto per intenderci) hanno deciso che questo limite era inutile. « Ma no!» si sono detti. «Le nostre liste inizieranno con 0!» Et voilà, a noi ci tocca prenderle così.


La conclusione è che prima non ho scritto una cosa corretta. Il computer memorizzerà i dati che gli passiamo in questa maniera:

Mario → posizione numero 0

Maria → posizione numero 1

Gianni → posizione numero 2

Gianna → posizione numero 3


A questo punto sappiamo che:

  • in ogni lista c’è un numero associato a ogni dato che inseriamo;
  • quel numero si chiama indice;
  • l’indice parte da 0, e non da 1 come molti potrebbero aspettarsi.

Bene, ma come ci aiuta tutto ciò a scoprire se un nome si trova nella lista o no?

In realtà è piuttosto semplice: basta scorrere la lista e paragonare ogni nome con quello che stiamo cercando.

Ora dovete sapere che esiste un’istruzione che dice al computer: compi questa operazione, sempre la stessa, un certo numero di volte. Quindi noi possiamo scorrere la lista tramite questa istruzione in questo modo:

  1. definisci una variabile che sia 0, chiamiamola indice per ricordarci a cosa serve;
  2. definisci una variabile che sia 0; chiamiamola risultato;#CONFRONTA il contenuto della lista alla posizione indice con la risposta dell’utente;
  3. SE il contenuto è uguale, allora cambia risultato in 1;
  4. aumenta il valore di indice di 1, in modo da passare alla posizione successiva;
  5. riparti dal punto 1.

Secondo voi siamo in grado di scrivere un programma del genere?

Proviamo in JavaScript:


1) definisci una variabile che sia 0, chiamiamola indice

var indice = 0;


2) definisci una variabile che sia 0; chiamiamola risultato;

var risultato = 0;


3) CONFRONTA il contenuto della lista alla posizione indice con la risposta dell’utente;

Qui bisogna conoscere la sintassi. Mettiamo che la lista si chiami “amici”; per riferirci all’indice della lista bisogna usare le parentesi quadre, in questo modo:

amici[]

Quindi la prima posizione di Amici (ricordiamoci che la prima posizione è 0!) sarà:

amici[0]

La seconda posizione sarà:

amici[1]

eccetera.

Quindi, per dire «la posizione indicata dal valore della variabile indice», bisognerà scrivere:

amici[indice]

Come vedete è piuttosto semplice. A questo punto possiamo occuparci dell’istruzione CONFRONTA. Se partiamo dall’ultimo programmino che abbiamo scritto, la risposta dell’utente era contenuta nella variabile persona, per cui:

amici[indice] == persona


4) SE il contenuto è uguale, allora cambia risultato in 1;

if ( amici[indice] == persona ) {
   risultato = 1;


5) aumenta il valore di indice di 1, in modo da passare alla posizione successiva;

Questo si scrive in maniera un po’ ridicola, ma va preso così com’è:

indice = indice + 1;


riparti dal punto 1.

Bene, questo ancora non lo sappiamo scrivere perché non abbiamo ancora parlato dell’istruzione che ci consente di ripetere lo stesso blocco di codice un certo numero di volte. Quest’istruzione si chiama for loop ed è arrivato il momento di andarla a conoscere.


A questo punto ci possiamo sbizzarrire con la versione con gli array. Ricordiamoci però di pronunciarli /əˈreɪ/ (ossia all’incirca come se in italiano fossero scritti eréi). Ecco il nostro codice:

function cambioTesto(){
    var utente = document.getElementById("risposta").value;

    if ( 1 == controllaNome(utente) ) {
        document.getElementById("testoDaCambiare").innerHTML = "Ciao, " + utente + "!";
    }
    else {
        document.getElementById("testoDaCambiare").innerHTML = "Non ti conosco, " + utente + "!";
    }

}

function controllaNome(persona) {

    var risultato = 0;
    var amici = ["Mario", "Maria", "Gianni", "Gianna"];

    for(var indice = 0; indice < amici.length; indice = indice + 1 ) {
        if ( persona ==  amici[indice] ) {
            risultato = 1;
       }
    }

    return risultato;
}

L’unica parte che potrebbe risultare misteriosa è come si scrive l’istruzione for. In effetti merita qualche chiarimento.

L’istruzione for si chiama così perché è introdotta dalla parola for seguita da parentesi tonde. for serve per ripetere un blocco di codice un certo numero di volte, pertanto la cosa più importante è trovare il modo di informare il computer su esattamente quante volte deve ripetere il codice. Ciò che sta dentro le parentesi tonde serve proprio a questo.

Di solito servono tre cose (a dire il vero non sono sempre tutte e tre obbligatorie):

  1. una condizione iniziale – nel nostro caso, si parte da 0;
  2. una condizione finale – nel nostro caso poniamo la condizione che il valore della variabile indice non abbia superato la dimensione (length) della lista, ossia indice deve essere minore (‘<’) della lunghezza della lista;
  3. un’istruzione per decidere qual è il passo successivo – nel nostro caso, il valore di indice deve crescere continuamente di 1 per passare alla posizione successiva della lista.

Il codice che deve essere ripetuto deve essere contenuto tra parentesi graffe.


for può non essere subito chiara, perciò cercheremo di trovare altri esempi in cui usarla.

Adesso però diamo un’occhiata a come si creano gli array nel JavaScript. Come vedete la sintassi è ispirata a quella della dichiarazione di variabile:

var amici = ["Mario", "Maria", "Gianni", "Gianna"];

Mi sembra piuttosto semplice: si scrivono i valori che si vogliono inserire usando una virgola per separarli. Il gruppo dei valori deve stare fra parentesi quadre.


Adesso finalmente prendiamo il volo verso il C++.


Il bello di stare fra amici

Il codice C++ si presenta subito con un’altra grana da risolvere, quindi tanto vale levarsi subito il dente:

#include <iostream>

using namespace std;

int controllaNome(string persona);
void cambioTesto();

int main()
{
   cambioTesto();
   return 0;
}

void cambioTesto()
{
   string utente;
   cout << "Qual è il tuo nome? ";
   cin >> utente;

   if ( 1 == controllaNome(utente) ) {
      cout << "Ciao, " << utente << "!" << endl << endl;
   }
   else {
      cout << "Non ti conosco, " << utente << "!" << endl << endl;
   }
}

int controllaNome(string persona)
{
   int risultato = 0;

   string amici[] = { "Mario", "Maria", "Gianni", "Gianna" };

   // Scopro quanto è grande il mio array
   int amici_length = sizeof(amici) / sizeof(amici[0]);

   for (int indice = 0; indice < amici_length; indice = indice + 1 )
   if ( persona == amici[indice] ) {
      risultato = 1;
   }

   return risultato;
}

Cominciamo dagli aspetti più… innocui.


string amici[] = { "Mario", "Maria", "Gianni", "Gianna" };

Come possiamo vedere. il C++ insiste con la sua ‘pignoleria’: giacché un array è qualcosa di molto diverso da una variabile, non ammette che lo si possa definire usando la stessa sintassi che si usa per le variabili; al contrario, pretende che si specifichi con chiarezza che noi vogliamo davvero un array usando, dopo il nome, il simbolo ‘[]’.

D’ora innanzi, quando useremo l’array dovremo sempre accompagnare il nome dal simbolo ‘[]’ anche se non abbiamo un indice da usare.

C’è da dire, d’altro canto, che il C++ ha una sua coerenza interna perché i blocchi di codice sono sempre identificati dalle parentesi graffe e anche in questo caso non si rinvengono eccezioni.


int amici_length = sizeof(amici) / sizeof(amici[0]);

Questa è la parte che mi aspetto risulti più oscura.

Intanto cerchiamo di capire a cosa serve, poi cercheremo di penetrare il meccanismo di come fa a fare ciò che ci serve.

Torniamo a Scratch. Abbiamo visto che Scratch ci offriva una comoda funzione (“contiene”) che ci informava se un valore era contenuto in una lista o no. Poi abbiamo scoperto che nel JavaScript e nel C++ non era disponibile e ci siamo dovuti inventare un altro sistema per ottenere lo stesso risultato.

Adesso soffermiamoci sul JavaScript. Questo, a sua volta, pur non offrendo l’istruzione “contiene”, ci veniva incontro con un’altra parolina magica, length, la quale ci informava almeno su quanto era grande l’array, ossia su quanti dati vi erano contenuti.

Arrivati al C++ ci imbattiamo in una sorpresa: nel C++ non c’è la parolina magica length.


«Ma come?» direte voi. «L’abbiamo usata poco tempo fa per string

Esatto, ma come vi dicevo il C++ è pignolo: chi ha scritto il codice per string ha previsto anche una funzione length() per string, e chi ha scritto il codice per gli array non ha previsto una funzione equivalente. E il C++ non consente di prendere la funzione scritta per string e attaccarla a array.

Spiacente. Non c’è e basta.


Un attimo, però, sennò tra un po’ non ci capiamo più. Vi ricordate come si usava length() per string? Si usava così:

string.length()

ossia, attaccandole tramite un punto.

Quel punto sta a significare qualcosa di particolare, ossia vuol dire che length() non è una funzione che si può usare ovunque, bensì è una funzione che si può applicare soltanto a string. È stata scritta, si può dire, su misura. Infatti abbiamo detto che è sì una funzione, ma di solito questo tipo di funzioni vengono chiamate metodi, così non facciamo confusione. In particolare, si dice che length() è un metodo di string, e in questa maniera si chiarisce che si può ‘attaccare’ solo a una variabile di tipo string.


Andando avanti troveremo un sacco di paroline magiche con i loro metodi e qualche volta li attaccheremo con un punto e altre volte con la buffa combinazione ‘->’ (es., string->length()), ma ora ne sappiamo ancora troppo poco per avventurarci in questo terreno.


Lasciatemi finire il discorso sul pezzo di codice che abbiamo fra le mani e dopo andremo a sviscerare un po’ di misteri su queste paroline magiche e sui loro metodi e ci faremo domande del tipo: «Ma perché, se sono sempre metodi, ossia un particolare tipo di funzioni, nel C++ si deve scrivere length() e in JavaScript si scrive length? Non bisogna mettere la parentesi tonda dopo il nome di funzione anche in JavaScript?»


Abbiamo detto che in C++ non c’è un metodo per sapere quanti dati sono contenuti in un array. In questo caso noi sappiamo che sono 4, ma se è per questo sappiamo già che cosa c’è contenuto dentro. Di solito chi scrive un programma non ha tutte queste informazioni disponibili. Ad esempio, la lista dei nomi potrebbe arrivare da un database o da un’altra funzione e noi non sapremmo né quanti sono né quali sono.

Il nostro obiettivo è quello di scrivere un codice che funzioni sempre, non solo quando abbiamo tutta la pappa scodellata.

Perciò ora ci dobbiamo inventare un sistema per scoprire quanto è grande questo array (ossia quanti dati contiene).


Facciamo un esempio un po’ assurdo. Mettiamo che un giorno, per scommessa, dobbiate scoprire quanti piani ci sono dentro un’antica torre medioevale. Vi recate a darle un’occhiata e vi scoraggiate subito: la torre è altissima e senza finestre e avete scommesso che riuscirete a scoprirlo senza entrarci dentro. E non vi potete mica arrampicare lungo il muro!

Come potete fare a scoprirlo?

Per fortuna in quel momento incrociate la vostra amica Leonilda, la quale vi saluta: « Ciao! Cosa ci fai qui?»

A quel punto le spiegate che dovete scoprire quanti piani ha la torre, ma non sapete come fare.

Al che lei ci pensa un po’ su e poi vi sorride: «So io come puoi fare. Devi sapere che la torre è stata edificata da un gruppo di nani che ha costruito tutti piani dal soffitto bassissimo: io, per esempio, ci riesco a entrare precisa precisa, e sono alta un metro e sessanta. L’altezza della torre è scritta in questo cartello informativo, vedi? Sono 54,4 metri. Con queste informazioni, è facilissimo sapere quanti piani ci sono nella torre!»

E in effetti subito intuite che la soluzione è

Numero di piani = Torre : Leonilda

e in pochi secondi riuscite a calcolare:

Numero di piani = 54,4 m : 1,60 m = 5540 cm : 160 cm = 34 piani


Beh, non è stato difficile, ma ora applichiamo lo stesso ragionamento qui.

Il C++ ci offre uno strumento comodo: sizeof.

sizeof è un’istruzione che ci informa di quanta memoria occupa un oggetto creato in un programma, per esempio una variabile o un array, il che è un altro modo di dire “quanto è grande”. Per la nostra torre abbiamo usato i metri, ma per parlare della memoria del computer dovremo usare un’unità di misura che non si vede: i byte.

Stare a definire cos’è un byte non credo ci servirebbe a molto ora, mentre invece ci è utile sapere che sizeof ci informa su quanti byte vengono occupati da cose come gli array.


A questo punto, se scriviamo sizeof(amici), possiamo scoprire quanti byte totali di memoria sono occupati dall’array amici. Questo è un po’ come sapere l’altezza della torre.


Se invece scriviamo sizeof(amici[0]) scopriamo quanti byte sono occupati da un singolo dato inserito nell’array; nel caso particolare, il primo, quello in posizione 0 – ma noi abbiamo imparato che si dice “con indice 0”. Ma che sia il primo o l’ultimo o uno a caso non ha rilevanza: in un array tutti i dati occupano lo stesso spazio di memoria; visto che la maggior parte delle volte non siamo sicuri di quanti dati abbiamo nell’array, conviene riferirsi a quello in posizione 0, partendo dal presupposto che, se uno ha dichiarato un array, almeno un dato ce l’avrà messo!

Comunque sia, quale che misuriamo, otterremo l’equivalente dell’altezza di un piano della torre.


Quindi non ci resta che compiere la stessa operazione di prima, dividere l’altezza della torre per l’altezza di un piano e troveremo il numero dei piani.

Parlando di array, dividendo la lunghezza complessiva in byte di un array per la lunghezza di un singolo dato otteniamo il numero dei dati contenuti.


E questo è il significato di questa riga. By the way, il simbolo ‘/’ in questo caso significa DIVIDI.


Il risultato della divisione viene immagazzinato nella variabile amici_length (l’ho chiamata così perché fosse chiaro a cosa doveva servire).


Beh, questo era lo soglio più grosso che dovevamo affrontare; superato questo, direi che il codice C++ è praticamente uguale a quello JavaScript.


Una lista un po’ più simpatica

A questo punto, se dovessi fare un tutorial molto serioso sul C++, dovrei soffermarmi un sacco su una novità come gli array e mostrare sia l’utilità che hanno, sia i limiti che delle volte presentano. Per non parlare poi dell’istruzione for, di cui bisogna portare almeno un altro paio di esempi se vogliamo essere sicuri di averla domata.


Ma il mio intento non è certo quello di dire tutto. Ci sono fior fiore di manuali, scritti da gente molto, ma molto più competente di me sul C++, e sopra tutto ci sono i mentor al vostro fianco, che sono lì per aiutarvi nei dettagli che non riusciamo a affrontare. Il mio scopo è più quello di essere chiaro che non di essere esaustivo.

Quindi voglio affrontare subito un dubbio amletico che sicuramente sta serpeggiando fra di voi, che è: «ma chi ce lo fa fare? Scratch è così chiaro e ha pure la funzione “contiene”. JavaScript come minimo non fa tanto il difficile su lentgh… Ma perché perdere tempo su questa cosa cervellotica del C++?»

Ebbene, sono qui a sollevare il vostro spirito: gioite perché ora andiamo a recuperare length per la coda.


Il motivo per cui nel JavaScript si può attaccare length a un array è che nel JavaScript un array è un oggetto. Lo so che la parola è così comune da far sospettare che la stia usando in modo improprio, ossia come dire un affare, una cosa, una di quegli aggeggi che…

Invece non è così: oggetto in informatica ha un significato molto preciso, ma finché non ne creeremo uno con le nostre mani qualunque cosa dica risulterà incomprensibile. Comunque per ora fidatevi: con il termine oggetto si intende un particolare blocco di codice che ha la sua brava etichetta, un po’ come le variabili o come string. Un oggetto può avere dei metodi (ricordate? Funzioni che si attaccano con un punto o con ‘->’)

Nel JavaScript un array è un oggetto; nel C++ non è un oggetto.

Quindi nel JavaScript possiamo usare length con un array, mentre nel C++ non possiamo farlo.


Che sfortuna, vero? È una cosa triste, lo so. Bisognerebbe che anche nel C++ ci fosse un oggetto che si potesse usare come un array… Ehi, un momento! Ma c’è! Ma certo, è un vector!

Un vector fa le stesse cose di un array, ma, signore e signori, è un oggetto.


Non ci resta che dare un’occhiata al nuovo codice C++ e rimandare le considerazioni a dopo.

#include <iostream>
#include <vector>

using namespace std;

int controllaNome(string persona);
void cambioTesto();

int main()
{
   cambioTesto();
   return 0;
}

void cambioTesto()
{
   string utente;
   cout << "Qual è il tuo nome? ";
   cin >> utente;

   if ( 1 == controllaNome(utente) ) {
      cout << "Ciao, " << utente << "!" << endl << endl;
   }
   else {
      cout << "Non ti conosco, " << utente << "!" << endl << endl;
   }
}

int controllaNome(string persona)
{
   int risultato = 0;

   vector<string> amici = { "Mario", "Maria", "Gianni", "Gianna" };

   for (int indice = 0; indice < amici.size(); indice = indice + 1 ) {
      if ( persona == amici.at(indice) ) {
         risultato = 1;
      }
   }

   return risultato;
}

Il problema di questo codice è che, se provate a compilarlo e a farlo partire, è possibile che Qt si blocchi. Ad alcuni si bloccherà e ad altri no. Coloro cui è andata bene devono portare un po’ di pazienza perché è bene risolvere questo problema fin da subito, invece che cercare di aggirarlo.

Quelli cui si è bloccato dovrebbero trovarsi davanti a una schermata come questa:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Un giorno impareremo a leggere queste schermate e scopriremo che dentro sono contenute un sacco di informazioni per migliorare il codice che stiamo scrivendo, ma non è un argomento per i primi passi nel C++.


Il ‘padre’ del C++ è il danese Bjarne Stroustrup, il quale fin dai primi anni ottanta stava cercando di aggiungere al linguaggio C il supporto per la programmazione a oggetti. Può quindi sembrare molto vecchio, almeno nei termini dell’informatica, ma nel corso degli anni è stato soggetto a molti miglioramenti. Anche nell’ultimo decennio ha subito molte revisioni, tra cui importantissima e molto sofferta è stata quella del 2011. Pensate un po’ che la discussione se introdurre o no le novità che molti proponevano fu iniziata nel 2008, ma erano così tanti a sollevare eccezioni e dubbi che i lavori si conclusero solo 3 anni dopo, nel 2011 appunto.

In seguito a quella revisione, il suo stesso ideatore arrivò a dire che la trasformazione era stata tale che aveva l'impressione di lavorare con un linguaggio del tutto nuovo.


Perché vi racconto questo? Per farvi inquadrare cos’è che ci blocca in questo momento. La complicazione la pone questa riga:

vector<string> amici = { "Mario", "Maria", "Gianni", "Gianna" };

Anche a voi quel vector<string> potrebbe parere un po’ strano, ma non è quello che dà fastidio a Qt. Anzi, a dire il vero non c’è niente che dia fastidio a Qt, il piccoso è il compilatore.

Non so se vi ricordate cosa si è detto quando si è presentato Qt: durante la fase di installazione, porta con sé un compilatore. Questo dovrebbe confermarvi che Qt è un ottimo ambiente di programmazione, ma non è di per sé un compilatore; però può ‘governare’ al posto nostro il compilatore che vogliamo usare.

Tanto per farvelo sapere, se avete installato la versione ‘standard’ di Qt, il compilatore che si è portato appresso è l’ottimo GCC, che nella versione per Windows si chiama MinGw.


«Tutto molto bello» starete pensando. «Ma perché è di cattivo umore, questo compilatore? Perché non fa quel che deve fare e basta?»

Aspettiamo a trattarlo male, perché lui sta cercando di non farci sbagliare. Il fatto è che prima della revisione del 2001 vector non ammetteva di caricare i dati da un blocco fra parentesi graffe come fa un array. Bisognava usare un’altra sintassi con molte più righe da digitare.

«Okay, ma ora siamo nel 2014, perciò… qual è il problema? Compili e basta.»

Beh, io potrei darvi anche ragione, ma non è così che funziona lo sviluppo del software. Ci sono programmi che esistono da anni e anni e rimangono in buona sostanza gli stessi, magari con qualche aggiornamento ogni tanto.

Quello che l’azienda di software vuole è che, quando scrive un piccolo aggiornamento per una nuova funzione o per risolvere un piccolo difetto, tutto il programma possa essere compilato di nuovo correttamente. Non vuole scoprire che intanto, da qualche parte del mondo, qualcuno ha deciso che, “Oh, guarda, questa versione del C++ non ci piace più, adesso la cambiamo in modo che il codice vada scritto così e cosà”, e d’un tratto il nuovo compilatore si rifiuta di accettare centinaia e centinaia di righe di codice che fino al giorno prima andavano benissimo!

Per questo i creatori di GCC hanno deciso di fare in modo che al compilatore possa essere detto: questo codice qui lo compili secondo le regole che erano in vigore prima del 2011, e quest’altro codice secondo quelle dal 2011 in poi.


Noi scriveremo tutto codice compatibile con le regole dal 2011 in poi, quindi ora ci basta informare il compilatore e la situazione si sbloccherà.


Orbene, informare il compilatore non è difficile, ma noi perché dovremmo stare a domandarci come si fa? Non si è detto che Qt lo può governare per noi? È ovvio che può!

È ora di scoprire cosa possono fare per noi quei file ‘in più’ che ci siamo ritrovati fra i piedi oltre al nostro main.cpp.

A noi interessa il file Saluto.pro, per cui coraggio: fateci doppio click sopra ed apritelo:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Come vedete il file si apre nella colonna di destra, andando per il momento a coprire il contenuto di main.cpp. Questa è una funzione molto comoda di Qt: i file si aprono uno sopra all’altro, di modo che possiamo recuperare il sottostante in ogni momento. Ancora non abbiamo cominciato a lavorare con più file contemporaneamente, però, per cui per recuperare main.cpp dovremo – DOPO, NON ORA! – fare doppio click sul suo nome.


Adesso, sotto la riga:

CONFIG -= qt

dobbiamo scrivere la seguente:

CONFIG += c++11

di modo che il file venga così:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Per far riapparire il contenuto di main.cpp, fate doppio click sul suo nome. Poi compilate ed eseguite: adesso dovrebbe andare tutto liscio.


RICORDATEVI QUESTI PASSAGGI PERCHÉ DOVREMO COMPIERLI PER OGNI PROGETTO DI QT! (almeno per ora)


Dicevamo che l’istruzione

vector<string> amici…

potrebbe causare un po’ di perplessità a qualcuno, e sarebbe comprensibile. In realtà non c’è niente di complicato. Confrontiamola con l’istruzione equivalente che fa uso degli array:

string amici[] …

A ben guardare le due scritte sono equivalenti, giacché contengono le stesse istruzioni, anche se scritte in ordine diverso:

  1. il nome della nostra variabile è sempre ‘amici’;
  2. si tratta sempre di una variabile di tipo string;#l’unica differenza è in come si dichiara un array (‘[]’) e in come si dichiara un vector (‘vector<>’).

I vector sono oggetti di un tipo particolare, detti template, i quali hanno la caratteristica di potersi adattare a diversi tipi di dati. Quindi noi avremmo potuto avere un vector di string come un vector di int e non sarebbe cambiato di una virgola il modo di usarli, solo che la dichiarazione iniziale sarebbe stata vector<int> amici. Nel caso fosse stato un array, invece, avremmo scritto int amici[].


Se la differenza fra i due fosse questa, non ci sarebbero motivi per andare a cercare i nostri amici vector. Il motivo per cui abbiamo voluto presentarli è che i vector, come le string, portano con loro un sacco di metodi già pronti e impacchettati che ci semplificano la vita, come ad esempio il metodo size() che ci ha risparmiato di scrivere un’intera riga di codice.

Rifletteteci un po’: se avessimo usato fin da subito vector, non ci sarebbe stato nemmen bisogno di cominciare a parlare di torri medievali e di altezze dei piani! Gli oggetti del C++ sono lì per semplificarci le cose e possiamo cominciare a usarli senza doverli conoscere in ogni minimo dettaglio.


Pensate che Qt ci offre un oggetto ancora più amichevole: QVector. Un QVector è un oggetto della libreria Qt che potremmo considerare un vector palestrato, giacché porta con sé un altra carrellata di metodi molto utili; uno di questi è contains, il quale, indovinate un po’, ci informa se il nostro QVector contiene, tra i suoi dati, quello che stiamo cercando.

Il che significa che non ci sarebbe più bisogno di un ciclo for per trovarlo.

Detto in altre parole, se avessimo utilizzato un QVector tramite questa istruzione:

QVector<string> amici…

dopo avremmo potuto procedere così:

if ( amici.contains("Mario") || amici.contains("Maria")…

senza preoccuparci né del ciclo for né del size di vector.

Questo è il motivo per cui vogliamo cominciare a conoscere fin da subito gli oggetti del C++ e anche passare appena possibile a quelli di Qt.


A proposito, l’avete notato vero il rigo:

#include <vector>

all’inizio del nostro codice? Senza quello, il codice non funziona, chissà perché… ;-)


Oltre l’orizzonte

Se questo fosse un tutorial serio e ben strutturato ora rimarrei qui a farvi fare un sacco di prove con gli array e i vector e proverei a dimostrarvi quanti errori di programmazione si possono prevenire usando i secondi. Un’altra cosa che mi piacerebbe sottolineare è quanto l’apparente rigidità della sintassi del C++ possa contribuire a evitare errori e di come la ‘amichevolezza’ del JavaScipt possa ogni tanto nascondere trappole insidiose, ma il problema di trattare un argomento del genere è che si corre il rischio di ferire la suscettibilità di chi ama programmare in JavaScript e questo non rientra affatto fra i miei progetti. Vorrei quindi cambiare prospettiva e proporre un’altra visione: che ogni linguaggio che si usa ha i suoi pro e i suoi contro.

Vediamolo con un esempio, sempre partendo da Scratch.

Il gioco dei fiammiferi con Scratch

Per questo gioco avremmo bisogno di 2 sprite, che io ho chiamato Giocatore1 e Giocatore2.


Il codice di Giocatore1

Le variabili:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Tenete presente che la variabile ‘presa’ dev’essere creata con una visibilità limitata al singolo sprite, come si può vedere qui sotto:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


La variabile ‘Fiammiferi rimasti’ potrà invece essere lasciata “per tutti gli sprites”.

Questo il resto del codice:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Il codice di Giocatore2

Le variabili sono esattamente le stesse di prima, punto per punto.

Il codice è composto dai seguenti spezzoni:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Il codice Scratch è, come al solito, autoesplicativo.

Metto soltanto in luce che il gioco non comincia quando si preme la bandierina verde, bensì quando si preme il tasto ‘p’. In alternativa si può premere ‘s’ per avere le spiegazioni sul gioco.


Un tutorial in C++ non si rivolge a bambini molto piccoli, ma alcuni potrebbero non aver fatto algebra, pertanto potrebbero non capire la seguente istruzione:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Basterà dir loro che serve a trasformare ‘presa’ in un numero negativo, ma chi vuole sperticarsi in una lezione sulla moltiplicazione fra numeri positivi e negativi faccia pure :)


Un altro punto su cui sarebbe utile soffermarsi sarebbe questo, perché ci introdurrà al meccanismo signals/slot delle librerie Qt:


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Cosa dire del codice?

Va bene, lo ammetto, sono stato cattivo. Non si può vincere mai, penso ve ne siate accorti :)

Il motivo per cui ho scelto questo gioco non è stato però per sadismo, bensì perché ci consente di introdurre un argomento che ci sta inseguendo fin dal primo tutorial: lo scope resolution, espressione che fa temere il peggio, ma gode per lo meno del raro privilegio di essere di solito tradotta in maniera intelligente con “spazio di visibilità”, immagino perché, quando gli informatici hanno cercato di forzare quello scope in un qualcosa di similare in italiano, non è venuto loro in mente niente di appropriato.


Per capire l’argomento torniamo alle due variabili ‘presa’ che esistono nel codice e osserviamo il loro comportamento. Ci si può rendere conto rapidamente che i loro valori si ‘muovono’ in maniera indipendente fra di loro e che ci sono istruzioni, come questa


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

che influiscono solo su una delle due, ma lasciano inalterata l’altra.


Il motivo è abbastanza evidente: quando le abbiamo create abbiamo specificato che ciascuna si riferisse a un solo sprite, e non a tutti gli sprite, pertanto il codice di uno sprite non è in grado di influenzare quella dell’altro sprite.

In informatica si usa il termine visibilità per descrivere questo fenomeno e si dice, appunto, che una variabile è visibile solo dal codice dello sprite cui si riferisce.


Per fare un paragone, è possibile che sia nella rubrica del vostro smartphone sia in quella del vostro compagno di tavolo sia presente il nome Ildebrando, però, stante il gran numero di Ildebrado che popolano questa nazione, potrebbero benissimo essere due persone diverse.

Quindi il nome di una variabile è unico solo nel suo spazio di visibilità.


«Ma perché mai tutto queste complicazioni?» a qualcuno verrà da chiedere. «Non potevamo semplicemente creare due variabili con due nomi distinti, tipo presa1 e presa2, e lasciare che fossero visibili a tutti gli sprite?»

Beh, certo, lo potevamo fare. Anche in JavaScript o in C++ potremmo, con molta sofferenza, raggiungere questo poco auspicabile traguardo.

Anzi! Se le prese dei due giocatori sono visibili da entrambi, il codice del Giocatore2 si semplifica non poco, ossia si tagliano via i 4 if. Credo che lascerò questa parte come esercizio; per chi ci vuole provare, il primo passo è cercare di capire come mai non si riesce a vincere – da qui si può partire per costruire un algoritmo di gran lunga più efficiente di quello utilizzato.


Adesso, però, per penetrare nel mistero dello spazio di visibilità, vediamo una delle possibili trasposizioni del gioco dei fiammiferi in JavaScript.


Il gioco dei fiammiferi in JavaScript

Cominciamo con il file in HTML5:

<!DOCTYPE html>

<html>
<head>
  <meta charset="utf-8">
  <link href="comuni.css" rel="stylesheet" type="text/css">
  <script src="gioco21.js" type="text/javascript"></script>

  <title>Gioco dei 21 fiammiferi</title>
</head>

<body>
  <h1>Non giocate con i fiammiferi!</h1>

  <div class="bordato">
    <p>Ci sono 21 fiammiferi. A ogni turno possiamo prenderne da 1 a 4. Chi rimane con l’ultimo ha perso.</p>
    <p>Hai la prima mossa.</p>
    <input type="button" value="Inizia a giocare" onclick="inizioGioco();" />
  </div>

  <div>
    <div class="sx">
      <p id="messaggio_cane"> </p>

      <p><img alt="Immagine di un cane" src="dog.jpg"></p>
      <div>
        <label for="g1" id="g1label" class="invisibile">Quanti fiammiferi prendo?</label>
        <input id="g1" type="text" class="invisibile" />
      </div>
    </div>

    <div class="sx">
      <p id="numfiammi" class="molto_grande">Fiammiferi rimasti: 21</p>
    </div>

    <div class="sx">
      <p id="messaggio_anatra" class="destra"> </p>

      <p><img alt="Immagine di una anatra" src="duck.jpeg"></p>
    </div>
  </div>

  <hr class="fine_float">
  <div>
    <input id="cambio" type="button" value="Tocca a te!"
          class="invisibile" onclick="mossaCane();" />
  </div>

</body>
</html>

Poi i CSS:

img {
   width          : 200px;
   height         : 220px;
}

input {
   display        : block;
}

label {
   display        : block;
}

div.sx {
   float          : left;
}

hr.fine_float {
   clear          : both;
   height         : 0;
   margin         : 0;
   border         : none;
}

.molto_grande {
   font-size      : larger;
   font-weight    : bold;
}

.bordato {
   border-color   : teal;
   border-style   : ridge;
   border-width   : 2;
   padding        : 0.6em;
   width          : 40em;
}

.invisibile {
   visibility     : hidden;
}

.visibile {
   visibility     : visible;
}

.destra {
   text-align     : right;
}

Infine il JavaScript (il file deve chiamarsi “gioco21.js”):

var fiammiferi;
var elementi_invisibili = [];

function inizioGioco() {
   fiammiferi = 21;
   numero_fiammiferi = document.getElementById('numfiammi');
   numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;
   document.getElementById("messaggio_cane").innerHTML = " ";
   document.getElementById("messaggio_anatra").innerHTML = " ";

   trovaEleInvi();
   cambiaVisibilita(1);
}

function mossaCane() {
   var presa = document.getElementById("g1").value;
   var messaggio = document.getElementById("messaggio_cane");

   messaggio.innerHTML = " ";

   // Controllo di non essere gia' rimasto con l'ultimo fiammifero
   if ( 1 == fiammiferi ){
      messaggio.innerHTML = "Mi sa che ha vinto lui...";
      cambiaVisibilita(0);
      return 0; // esco dalla funzione!
   }

   // Controllo che l'utente non abbia immesso un numero
   // minore di 1 o maggiore di 5
   if( presa > 0 && presa < 5 ) {
      messaggio.innerHTML = "Ho preso " + presa + " fiammiferi";
      fiammiferi -= presa;
      numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;
      mossaAnatra();
   } else {
      messaggio.innerHTML = "Mi sa sche non posso farlo...";
   }
}

function mossaAnatra() {
   var messaggio = document.getElementById("messaggio_anatra");
   var presa = 0;

   messaggio.innerHTML = " ";

   if( 1 < fiammiferi){
      presa = fiammiferi - 1;
   }
   if( 6 < fiammiferi){
      presa = fiammiferi - 6;
   }
   if( 11 < fiammiferi){
      presa = fiammiferi - 11;
   }
   if( 16 < fiammiferi){
      presa = fiammiferi - 16;
   }

   fiammiferi -= presa;
   messaggio.innerHTML = "Io prendo " + presa + " fiammiferi";
   numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;

   if ( 1 == fiammiferi ) {
      mossaCane();
   }
}

function cambiaVisibilita(visibilita) {
   for (var indice=0; indice < elementi_invisibili.length; indice++){
      if( 1 == visibilita ) {
         elementi_invisibili[indice].setAttribute("class", "visibile");
      } else if ( 0 == visibilita ) {
         elementi_invisibili[indice].setAttribute("class", "invisibile");
      } else {
         alert("C'è un errore nel programma!");
      }
   }
}

function trovaEleInvi() {
   elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1label");
   elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1");
   elementi_invisibili[elementi_invisibili.length] = document.getElementById("cambio");
}

Le immagini da utilizzare, mettendole nella stessa cartella del progetto, sono dog.jpg e duck.jpeg, che si trovano sullo wiki nelle rispettive pagine:


Un’altra cosa: scrivere tutte le volte il nome JavaScript per esteso mi fa un po’ fatica. Un sacco di gente lo chiama semplicemente JS, perché non lo facciamo anche noi?


Tanto vale che lo ammetta fin da subito: il codice JS che vi presento è un tantino complicato. Ormai abbiamo rotto il ghiaccio con l’idea di scrivere codice, per cui è inutile che continuiamo a fare i timidi. Vedrete che riusciremo a domare anche questo programma e ci insegnerà un sacco di cose.


Lo scopo di questo programma è parlare prima di tutto di scope resolution perché è un argomento un po’ astratto, ma ne verranno fuori tanti altri via via che scorreremo le righe. Intanto diamo un’occhiata generale al programma, che ha ben 5 funzioni:

  1. inizioGioco()
  2. mossaCane()
  3. mossaAnatra()
  4. cambiaVisibilita
  5. trovaEleInvi()

Beh? Di cosa vi meravigliate? Il codice va spezzato in funzioni oppure non riusciremo mai a riutilizzarlo.

Tra queste funzioni ce ne sono alcune che ci risulteranno ben chiare, ad esempio mossaCane() e mossaAnatra(), che gestiscono il cambiamento del numero di fiammiferi in base alle scelte dei due giocatori. Altre invece ci risulteranno alquanto misteriose. Direi che la strategia più semplice per affrontarle è seguire il programma passo passo.


Quando l’utente inizia, per prima cosa è invitato a leggere le spiegazioni e poi a premere il pulsante “Inizia a giocare”. Questo pulsante fa comparire la casella di testo dove il giocatore1 può inserire la sua scelta.

Come fa a farlo?

Guardiamo il codice HTML. Ci sono ben tre elementi che ‘nascono’ con associata la classe CSS ‘invisibile’:

  • la scritta “Quanti fiammiferi prendo?”
  • la casella di testo in cui scrivere il numero
  • il pulsante “Tocca a te”

La classe ‘invisibile’ consiste nell’istruzione

visibility : hidden;

Hidden in inglese vuol dire nascosto, e infatti quello che fa questa istruzione è di nascondere gli elementi a video. Ossia, essi ‘esistono’ nel codice HTML, ma non sono rappresentati a video.

Quando la partita inizia, bisogna che questi elementi saltino fuori, e questo si può ottenere sostituendo la classe ‘invisibile’ con quella ‘visibile’.


La pressione sul pulsante “Inizia a giocare” compie proprio questo passaggio tramite la funzione inizioGioco(). Questo passaggio è reso necessario dal fatto che, quando il gioco finisce, sopra le due immagini compaiono scritte che non devono più apparire; non solo, ma il numero dei fiammiferi sarà 1 invece che 21; oltre a ciò, per comunicare all’utente che il gioco è finito, i tre elementi elencati sopra saranno resi invisibili di nuovo. Pertanto ci serve una funzione che rimetta a posto le cose prima dell’inizio di una partita.

Però diamo anche un’occhiata anche a ciò che è scritto prima di InizioGioco():

var fiammiferi;
var elementi_invisibili = [];

Queste due istruzioni si limitano a definire una variabile e un array; la prima conterrà il numero di fiammiferi; la seconda invece i tre elementi che dovranno ‘apparire’ o ‘sparire’, ossia quei tre elencai poco sopra. Queste due istruzioni non sembrano aver nessuna particolarità, se non una che forse non salta all’occhio subito: si trovano entrambe fuori da ogni funzione.

Torneremo tra pochissimo su questa osservazione, che è molto importante.


Diamo un’occhiata a quali sono le operazioni preliminare a ogni partita, cioè a perché chiamiamo la funzione inizioGioco():


fiammiferi = 21;

Come si è detto, alla fine di una partita il numero di fiammiferi sarà uno, quindi all’inizio della partita successiva va riportato a 21. ‘fiammiferi’ è la variabile dichiarata fuori da ogni funzione. Come vedete, possiamo usarla senza problemi anche se non l’abbiamo definita qui.


numero_fiammiferi = document.getElementById('numfiammi');

numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;


A questo punto aggiorniamo la scritta “Fiammiferi rimasti: 21” sullo schermo. Quindi, ‘numero_fiammiferi’ è una variabile che ci consente di accedere al del codice HTML. Lì dentro, tramite il metodo innerHTML, andiamo a inserire la frase: “Fiammiferi rimasti: 21”. Facciamo caso a una cosa: numero_fiammiferi è stata definita senza la parolina var davanti.
document.getElementById("messaggio_cane").innerHTML = " "; document.getElementById("messaggio_anatra").innerHTML = " "; Queste due righe dovrebbero essere chiare, eccetto che forse non tutti sanno cosa vuol dire   nello HTML. A dir la verità nel Coder Dojo abbiamo già avuto modo di scoprire che è serve per inserire la lettera ‘è’ e ò per inserire la lettera ‘ò’, perciò dovrebbe essere piuttosto naturale dedurre che anche   serva per inserire una lettera. Beh, quasi, ma non proprio: è solo un modo complicato di inserire uno spazio. Avremmo anche potuto scrivere document.getElementById("messaggio_cane").innerHTML = " "; document.getElementById("messaggio_anatra").innerHTML = " "; con uno spazio dentro le virgolette e avrebbe funzionato lo stesso (provare per credere). Il fatto è che non tutti usano un semplice editor di testo per scrivere codice HTML; esistono anche dei programmi appositi, molto più evoluti. Una delle caratteristiche di questi programmi è che rimettono a posto il codice via via che lo si scrive; ad esempio se scriviamo <p>, questi programmi aggiungono automaticamente un subito dopo; e come questa, fanno anche tante altre cose per semplificarci la vita. Una di queste cose, però, è eliminare gli elementi vuoti. Ossia, se a un certo punto scrivete

<p></p>

oppure

<p> </p>

con solo uno spazio dentro, il programma, quando lo vede, pensa: «Che cosa ci sta a fare qui un paragrafo senza niente dentro? Si è dimenticato di levarlo, quel pasticcione… Eh, meno male che ci sono io qui a rimettere a posto le cose, sennò chissà dove andremmo a finire!», e, detto fatto, lo cancella.

Se invece scrivete

<p> </p>

ottenete lo stesso risultato, ma il programma per scrivere codice HTML, se ne state usando uno, ve lo lascia stare.


trovaEleInvi();

Questa istruzione fa saltare il programma nella funzione trovaEleInvi(). Seguiamolo.


elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1label");

elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1");

elementi_invisibili[elementi_invisibili.length] = document.getElementById("cambio");

Le tre istruzioni di per sé dovrebbero essere molto semplici.

In pratica, carichiamo dentro l’array elementi_invisibili gli elementi che, come abbiamo scoperto, dovremmo ogni tanto far apparire e ogni tanto far sparire.

Potrebbe essere un po’ difficile decifrare quel elementi_invisibili.length. Avevamo scoperto che length serviva per scoprire quanti elementi c’erano in un array, adesso in apparenza sembra che serva per un’altra cosa.

Beh, non proprio. Ragioniamoci un po’ su, partendo proprio dal nostro codice.

All’inizio l’array elementi_invisibili è vuoto; questo significa che elementi_invisibili.length è 0. Bene. Ma non abbiamo detto che il primo elemento di un array è quello in posizione 0?

Quindi, se noi vogliamo inserire il primo elemento nella prima posizione di una array, ossia in posizione 0, vuol dire che dobbiamo scrivere:

elementi_invisibili[0] = …

Però anche elementi_invisibili.length è 0, pertanto le due istruzioni elementi_invisibili[0] e elementi_invisibili[elementi_invisibili.length] sono perfettamente identiche.


Quindi la prima delle tre righe inserisce l’elemento HTML <label id="g1label"> nella posizione 0 di elementi_invisibili.


A questo punto, però, la dimensione del nostro array è cambiata perché dentro c’è un elemento. Quindi elementi_invisibili.length non restituirà più 0, bensì 1.

Quindi la seconda riga

elementi_invisibili[elementi_invisibili.length] = document.getElementById("g1");

inserirà l’elemento HTML <input id="g1"> nella seconda posizione dello array, ossia in posizione 1.

Ciò significa che scrivere

elementi_invisibili[elementi_invisibili.length] = qualcosa;

istruisce il computer a inserire ‘qualcosa’ nella prima posizione libera dell’array, ossia in coda agli altri dati contenuti.


Attenzione! Di nuovo dobbiamo far attenzione al fatto che l’array elementi_invisibili è stato definito da un’altra parte, ossia all’inizio del nostro programma. Anche in questa occasione, ci limitiamo ad usarlo, proprio come se fosse stato definito in questa funzione.


A questo punto la funzione trovaEleInvi() è finita è il computer torna in inizioGioco(). E noi con lui.


cambiaVisibilita(1);

Questa istruzione ci fa saltare nella funzione cambiaVisibilita().

Mettiamoci d’accordo su un altro parolone: in informatica chiamare una funzione si dice ‘invocare’ una funzione.


cambiaVisibilita(visibilita)

Questa funzione fa una cosa semplice, anche se a vederla sembra piena di righe complicate.

Come vedete accanto al nome della funzione c’è il nome di una variabile; dentro quella variabile, come sappiamo, finirà il valore che viene trasmesso alla funzione quando l’abbiamo chiamata – ossia, invocata.

Se quel valore è 1, la funzione mostra i tre elementi contenuti nell’array elementi_invisibili.

Se quel valore è 0, li nasconde.


Fateci caso anche qui: stiamo usando l’array elementi_invisibili né più né meno come se l’avessimo definito in questa funzione.


Tutto è gestito dal ciclo for, che incrementa di uno il valore della variabile ‘indice’ da 0 fino a che non è inferiore al numero di dati contenuti nello array, ossia al massimo a 2 (perché 3 non sarebbe più inferiore alla dimensione dell’array, bensì uguale).

Il valore di questa variabile è poi usato come indice dell’array (e proprio perché fosse chiara questa sua funzione l’abbiamo chiamata ‘indice’, ma avrebbe potuto benissimo chiamarsi ‘Genoveffa’ e non sarebbe cambiato nulla).

Il metodo setAttribute si occupa di far cambiare agli Elementi HTML la classe CSS associata, visibile o invisibile.


In questo caso è stato passato il valore 1 ed ecco spiegato come fanno i 3 famigerati elementi ad apparire.


A questo punto il primo ‘passaggio’ è finito. Siamo in attesa che l’utente scriva un numero nella casella di testo <input id="g1"> e prema il pulsante “Tocca a te”.

La pressione di quel pulsante invoca la funzione mossaCane(), alla tentazione di esaminare la quale non possiamo resistere:


var presa = document.getElementById("g1").value;

Qui dichiariamo una variabile all’interno di una funzione tramite la parola var. Ne sentivate la mancanza, di un’istruzione così? :)

Direi che non c’è molto da aggiungere: la variabile conterrà ciò che ha immesso l’utente della casella di testo <input id="g1">


var messaggio = document.getElementById("messaggio_cane");

messaggio.innerHTML = " ";

Anche se l’avevamo già fatto prima, qui sostituiamo il testo che compare sopra l’immagine del canino con uno spazio, ossia con qualcosa di apparentemente vuoto.

Il fatto è che il pulsante “Inizia a giocare” non sarà più premuto fino alla fine della partita, ma la presa dei fiammiferi si effettuerà più volte prima di allora, e ogni volta qui dovrà comparire un testo diverso.


// Controllo di non essere gia' rimasto con l'ultimo fiammifero

Questo è un commento per ricordarsi cosa si sta facendo. Il nostro codice dovrebbe esserne pieno, ma col fatto che poi commento tutto dopo, per ora non sto a scriverli. Però tenete presente che scrivere i commenti è una delle attività più importanti del programmare.


Codice
Spiegazioni
if ( 1 == fiammiferi ){ Il blocco successivo si attiverà solo quando il giocatore1 sarà rimasto con l’ultimo fiammifero
messaggio.innerHTML = "Mi sa che ha vinto lui..."; Vi ricordate cosa conteneva ‘messaggio’? L’elemento HTML


cambiaVisibilita(0); Si invoca la funzione cambiaVisibilita() passandogli il valore 0, ossia dicendole di far ‘sparire’ i 3 ormai arcinoti elementi
return 0; Questa riga forza l’uscita dalla funzione mossaCane() senza che venga eseguito il resto del codice – Se il giocatore1 ha perso, non c’è più motivo di fargli prendere altri fiammiferi – Attenzione! Non è rilevante che non ci sia nessuno a ‘raccogliere’ il valore restituito da mossaCane(), l’importante è che return blocchi il codice.
} fine del blocco di codice if


if( presa > 0 && presa < 5 ) {

Anche questa istruzione può lasciare interdetti, ma è molto più semplice di quel che appaia.

Abbiamo visto sopra il simbolo ‘||’ che vuol dire OPPURE.

Ebbene questo simbolo simbolo qui, ‘&&’, vuol dire E.

In altre parole, la frase si dovrebbe leggere: SE il valore di ‘presa’ è maggiore di 0 E il valore di ‘presa’ è inferiore a 5, ALLORA…

Tutto ciò è un modo un po’ complicato di dire che ‘presa’ deve stare fra 1 e 4.

Il simbolo ‘&&’ istruisce il computer a considerare falsa l’espressione dentro la parentesi se anche solo una delle condizioni è falsa.

Detto alla rovescia, l’espressione dentro la parentesi è considerata vera SOLO SE TUTTE le condizioni sono vere.


Quindi, se l’utente inserisce un numero tra 1 e 4, si entra nel blocco, altrimenti si prosegue con il blocco else.


messaggio.innerHTML = "Ho preso " + presa + " fiammiferi";

Si aggiorna la scritta sopra l’immagine del canino.


fiammiferi -= presa;

Un’altra cosa che non abbiamo ancora visto, ma anche qui non c’è da farsi prendere dal panico.

Mettiamo che io abbia una variabile, ‘gigetto’, e che sia uguale a 5.

var gigetto = 5;

Se scrivo

gigetto = gigetto + 1;

‘gigetto’ diventa uguale a 6. Solo che l’istruzione è considerata molto lunga da qui pigroni degli informatici, perciò si sono messi d’accordo a trovare un modo di non ripetere la parola ‘gigetto’ e alla fine hanno trovato questa diavoleria:

gigetto += 1;

Carino, eh? Badate bene, non vuol dire nulla di particolare: se ‘gigetto’ era uguale a 6, adesso diventa uguale a 7.

Però non è finita qui. Visto che la maggior parte delle volte il valore di una variabile cambia solo di 1, si sono inventati un metodo ancora più breve, cioè questo:

gigetto++;

Anche se può sembrare illeggibile, il significato delle 3 istruzioni è esattamente il medesimo; quindi, partendo dal 7 di prima, adesso ‘gigetto’ è diventata 8.

Tutto qui.


E lo stesso vale per il segno meno:

gigetto -= 3;

fa tornare ‘gigetto’, da 8 che era, di nuovo a 5; e

gigetto--;

addirittura a 4.


Invece le altre operazioni si devono ‘accontentare’ della sintassi con il segno di uguale, ossia *= e /=.

Per rendere le cose semplici, riporto qui un po’ di esempi che dovrebbero essere più chiari di mille parole:


var unvalore = 10; unvalore == 10
unvalore++; unvalore == 11
unvalore -= 9; unvalore == 2
unvalore *= 7; unvalore == 14
unvalore--; unvalore == 13
unvalore += 5; unvalore == 18
unvalore /= 3; un valore == 6

Pertanto l’istruzione

fiammiferi -= presa;

è del tutto identica a

fiammiferi = fiammiferi - presa;

e si limita a far calare il numero dei fiammiferi del valore di ‘presa’.


ANCORA UNA VOLTA STIAMO USANDO UNA VARIABILE CHE NON È STATA DICHIARATA NELLA FUNZIONE IN CUI CI TROVIAMO COME SE LO FOSSE STATA.


numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;

Dovrebbe essere chiaro.


mossaAnatra();

Andiamo a vedere cosa combina questa funzione.

Però, attenzione!, dopo NON torneremo in mossaCane() perché il codice restante, ossia lo ALTRIMENTI del blocco if è talmente ovvio che siete del tutto in grado di decifrarlo da soli.


var messaggio = document.getElementById("messaggio_anatra");

messaggio.innerHTML = " ";

Queste due righe erano staccate fra di loro, ma se si guardano così di seguito direi che non hanno bisogno di chiarimenti.


var presa = 0;

Neanche questa ha bisogno di chiarimenti.


if( 1 < fiammiferi){

presa = fiammiferi - 1;

}

if( 6 < fiammiferi){

presa = fiammiferi - 6;

}

if( 11 < fiammiferi){

presa = fiammiferi - 11;

}

if( 16 < fiammiferi){

presa = fiammiferi - 16;

}

Questo blocco può essere poco chiaro dal punto di vista della logica, ma direi che non presenta difficoltà sintattiche.

Comprenderne la logica è lasciato come esercizio. Si può partire dall’invertire le condizioni; ossia, invece di scrivere if( 1 < fiammiferi) si può scrivere if( fiammiferi > 1 ), il ché dovrebbe rendere il meccanismo più chiaro.


fiammiferi -= presa;

Ne abbiamo già vista una identica poco sopra.


messaggio.innerHTML = "Io prendo " + presa + " fiammiferi";

numero_fiammiferi.innerHTML = "Fiammiferi rimasti: " + fiammiferi;

Non ci vedo difficoltà.


if ( 1 == fiammiferi ) {

mossaCane();

Questa posso capire che lasci perplessi.

In pratica si dice: se rimane un solo fiammifero, non stare a chiedere all’utente quanti fiammiferi vuole prendere, ma salta subito nella funzione mossaCane() dove c’è un blocco if che gestisce questa situazione.


Scommetto che morite dalla voglia di sapere perché ho continuato a ripetere quella frase “stiamo usando una variabile definita da un’altra parte come se l’avessimo definita qui!”. È giunto il momento che vi risponda.


Prendiamo in esame la variabile ‘presa’. Anzi: prendiamo in esame le due variabili ‘presa’. Dico due variabili perché si tratta di due variabili completamente diverse fra di loro, i cui valori non si intersecano mai.

Una delle due è dichiarata in mossaCane() e l’altra in mossaAnatra(). Orbene, anche se hanno lo stesso nome, per il computer sono due variabili diverse e tutto ciò che faremo a una non avrà alcuna influenza su ciò che faremo all’altra. Se cambiamo, incrementiamo, azzeriamo o diminuiamo il valore di una, l’altra rimarrà inalterata.


Questo è ciò che si intende con spazio di visibilità di una variabile ed è un concetto importantissimo.

Una variabile che è dichiarata all’interno di una funzione può essere vista SOLO dal codice di quella funzione. Fuori da quella funzione è assolutamente invisibile. Se dichiarate una variabile con lo stesso nome, beh, si tratta semplicemente di un’altra variabile.

Le funzioni che possono essere viste solo all’interno della loro funzione si dice che hanno visibilità locale oppure che sono variabili locali.

Nel C++ (ora vedremo anche il codice per quel linguaggio) le cose stanno all’incirca nella stessa maniera, solo che, essendo lui così (uffa! Mamma mia!) pedante, ci aggiunge un’altra complicazione, che è il mascheramento (che noi non useremo).


Del tutto diverse sono invece la variabile e l’array che abbiamo dichiarato fuori da ogni funzione.

Riguardate il codice e i commenti: usiamo quella variabile e quell’array un po’ ovunque, ma il loro contenuto non va mai perso.

Ossia, anche se carichiamo i valori nell’array elementi_invisibili dentro la funzione trovaEleInvi(), tutte le volte che invochiamo la funzione cambiaVisibilita() li ritroviamo lì ad aspettarci.

E lo stesso vale per fiammiferi: quando ne abbiamo bisogno la usiamo e dentro ci troviamo sempre proprio il numero che ci aspettiamo di trovarci, anche se la modifichiamo una volta in mossaCane() e una volta in mossaAnatra().

Si dice che queste variabili, ossia quelle dichiarate fuori di ogni funzione, hanno visibilità globale. Oppure semplicemente che sono variabili globali.


Anche in questo caso, consoliamoci, il C++ vede le cose dallo stesso punto di vista.

Anche se, lo ammetto, se stessimo facendo un corso serissimo dovrei considerare il caso di una variabile ‘così tanto’ globale da dover essere vista addirittura da un altro file… No, no, è troppo complicato! Lasciamo stare, non posso stare qui a dirvi che basta scrivere extern all’inizio della dichiarazione di variabile…


Orbene, adesso mi metto qui in attesa di qualcuno che, avendo spulciato il codice per bene, mi fa notare che numero_fiammiferi è dichiarata all’interno della funzione inizioGioco(), e quindi dovrebbe avere visibilità locale, ma è usata anche in altre funzioni proprio come se avesse visibilità globale…

C’è qualcuno che se n’è accorto? Bravi!


Ecco, questo è un punto su cui il JavaScript e il C++ non andrebbero mai d’accordo.

Nel JavaScript basta non mettere la parola var prima di una variabile e quella sarà automaticamente considerata una variabile globale ANCHE SE è dichiarata all’interno di una funzione.

Sorpresa!

Quindi ‘numero_fiammiferi’ è una variabile globale a tutti gli effetti, e questo solo perché non c’è scritto var davanti.


Ora mettiamoci nell’ordine d’idee di un programmatore in C++.

Si è detto che il C++ ci costringe a spezzare il nostro codice in blocchi. Più avanti vederemo che ci spinge anche a mettere questi blocchi su file diversi, proprio perché sia diviso in modo coerente e ordinato. Il motivo per cui è così minuzioso è perché è un linguaggio che è stato concepito per consentire a molte persone di lavorare sullo stesso progetto senza intralciarsi fra di loro. In altre parole, essendo il codice diviso in blocchi e i blocchi in file, in una squadra anche numerosa possiamo dirci: «Io lavoro su questo blocco e tu su quello» e andiamo avanti ognuno con ciò che deve fare senza curarci degli altri.

Ora fate conto di stare lavorando in rete con altre duecento persone di tutti i paesi del mondo e di scoprire che il vostro codice non funziona più perché qualcuno degli altri duecento, in qualcuna delle innumerevoli funzioni che ha scritto, ha usato un nome di variabile che avete usato anche voi, ma si è dimenticato di scriverci davanti var

Anzi, meglio: immaginate di essere voi ad aver dimenticato di scrivere var, ma di non avere la più pallida idea di quale funzione possa essere e di aver già scritto decine e decine di file di codice… E i vostri colleghi sono tutti fermi in attesa che voi risolviate il problema perché sennò non si può compilare il programma!

Simpatico, nevvero? :)


Si capisce allora perché nei forum ci siano tante polemiche: per un programmatore in JavaScript la possibilità di creare variabili globali in qualsiasi momento è una gran comodità; per un programmatore in C++ è una trappola da evitare come la peste. Entrambi hanno le loro buone ragioni.

Nel C++, sia ben chiaro, al di là del fatto che non esiste la parola var, è previsto un solo modo di dichiarare una variabile globale: crearla fuori da ogni funzione.


Non è questa l’unica discrepanza fra il modo di vedere le cose le programmatore C++ e quello del programmatore JavaScript. Vi ricordate che tempo fa ci siamo chieste perché nel JavaScript la parola length si scrivesse senza parentesi tonde? Allora non avevamo dato una risposta, lasciando che si potesse ipotizzare si trattava solo di una diversa sintassi. Beh, le cose sono un po’ più complicate di così.

Ne JavaScript length non è un metodo (ossia una particolare funzione), bensì è una proprietà, ossia un particolar tipo di variabile.


Quando ci si riferisce a un oggetto, la parola proprietà indica una variabile; questa variabile però non può essere usata come ci pare, bensì come è stato previsto dal creatore dell’oggetto. Chi ha creato gli array ha previsto che length contenesse il numero di dati inseriti; non si può usarla a caso, ma solo per gestire questo dato.

Fatto sta che il valore di length, essendo una variabile, può essere modificato a piacere.

Guardate un po’ cosa succede qui:

<!DOCTYPE html>

<html>
<head>
  <meta charset="utf-8">
  <script type="text/javascript" src="provaLength.js"></script>
  <title>Prova della proprietà length</title>
</head>

<body>
  <input type="button" value="Premi per provare" onclick="provaLength()">
  <p id="output1"> </p>
  <p id="output2"> </p>
  <p id="output3"> </p>
</body>
</html>

Quello sopra è il codice HTML, questo il JavaScript (il file deve chiamarsi “provaLength.js”):

function provaLength() {
    var output1 = document.getElementById("output1");
    var output2 = document.getElementById("output2");
    var output3 = document.getElementById("output3");

    var mioarray = [];
    var dimensione = mioarray.length;
    output1.innerHTML = "Dimensione array: " + dimensione;

    mioarray.length = 3;
    dimensione = mioarray.length;
    output2.innerHTML = "Dimensione array: " + dimensione;

    mioarray[0] = "Una frase a caso";
    dimensione = mioarray.length;
    output3.innerHTML = "Dimensione array: " + dimensione;
}

Anche in questo caso la grande flessibilità e semplicità di utilizzo del JavaScript può dare risultati inattesi, se non si sa cosa si sta facendo.

Anche nel C++ si potrebbero creare oggetti con delle proprietà, ossia delle variabili ad essi connesse, che si possono modificare a piacere, ma, all’interno del pignolo C++, è considerato un pessimo modo di scrivere codice e nessuno degli oggetti che fanno parte dello standard presenta una proprietà del genere.

State quindi molto attenti, nel JavaScript, quando elaborate qualcosa come

if ( mioarray.length == miavariabile) {…

a scrivere correttamente il simbolo ‘==’ e non ‘=’, perché potreste modificare il valore di length.


Ancora una nota: se vi ricordate avevamo detto che era necessario, all’inizio del file C++, riportare un elenco delle funzioni che si erano scritte. In quel caso avevamo detto che così il compilatore poteva garantirci che non ci fossero duplicati.

Quello che abbiamo trattato qui è diverso, ma simile: anche in questo caso ci dobbiamo garantire che, all’interno dello stesso spazio di visibilità non ci siano nomi duplicati.


Bene, coraggio, il C++ ci aspetta.


Il gioco dei fiammiferi in C++

Non possiamo però creare un programma che riguarda il gioco dei fiammiferi in un progetto che si chiama “Saluto”!

È ora di creare un nuovo progetto. Non sto qui a ripetervi i passi: tornate a consultare il primo tutorial.

Come nome (“Name”) mettiamo “Gioco21” e come cartella (“create in”) la stessa, “…ProgrammiCpp/CppQt” o come si chiama il percorso che avete creato.


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Vi dovreste ritrovare in una situazione simile a quella in cui ci siamo trovati nella prima versione del programma “Saluto”. Infatti Qt crea sempre un file main.cpp in cui inserisce il codice “Hello world!”.


Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione


Avete la sicurezza di trovarvi in un nuovo progetto leggendo ciò che compare sulla barra del titolo (“Gioco21”).

Anche in questo caso del codice “Hello world!” non ce ne facciamo di niente e lo sovrascriveremo.


Ecco il nostro codice:

#include <iostream>

using namespace std;

int fiammiferi;

void spiegazioni();
void mossaCane();
void mossaAnatra();

int main()
{
   spiegazioni();
   fiammiferi = 21;

   // Questo tipo di blocco si chiama ciclo do-while.
   // Funziona così:
   // la riga "do {" identifica solo l'inizio del blocco.
   // Il programma la legge e viene informato solo che
   // prima o poi incontrerà la scritta "}while(...".
   // Il computer continua a eseguire le istruzioni fino alla
   // fine del blocco, poi legge dentro la perentesi tonda
   // dopo la parola while.
   // "while" funziona come "if", ossia propone una condizione
   // di cui il computer deve decidere se sia vera o falsa.
   // Se la condizione è vera, allora il computer torna alla
   // parola "do" e ricomincia il ciclo.
   do {
      mossaCane();
      mossaAnatra();
   } while ( 1 < fiammiferi );

   // Se siamo arrivati qui, vuol dire che il numero dei fiammiferi
   // è diventato uguale a 1.
   cout << endl << "* * * * * * * * * * * * * * * * * * * * * * * * * * *"
        << endl;
   cout << "Mi spiace, sei rimasto con l'ultimo"
           " fiammifero..." << endl;
   cout << "Ho vinto io." << endl;
   cout << "* * * * * * * * * * * * * * * * * * * * * * * * * * *"
        << endl << endl;

   return 0;
}

void spiegazioni()
{
   cout << "Ci sono 21 fiammiferi." << endl;
   cout << "Ne possiamo prendere da 1 a 4 per volta." << endl;
   cout << "Chi rimane con l'ultimo ha perso." << endl;
   cout << endl << "Hai la prima mossa." << endl << endl;
}

void mossaCane()
{
   int presa = 0;

   // In questo momento presa == 0,
   // pertanto la condizione successiva sarà ritenuta *vera*.
   // Infatti l'istruzione dice:
   // FINCHE' presa sarà minore di 1 OPPURE presa sarà
   //    maggiore di 5...
   // presa è al momento minore di 1, pertanto si entra
   // nel ciclo while.
   // Il ciclo while si ripete finché è necessario, ossia anche
   // all'infinito, in attesa che la condizione diventi falsa.
   while ( presa < 1 || presa > 4 ){

      cout << "Quanti fiammiferi prendi (da 1 a 4)? " << endl;
      cin >> presa;

      if( presa < 1 || presa > 4) {
         cout << "Spiacente. Devi prendere almeno un fiammifero, "
                 "ma non più di quattro..." << endl << endl;
      }

   }

   // Se siamo usciti dal blocco 'while' vuol dire che
   // abbiamo ottenuto un numero da 1 a 4
   fiammiferi -= presa;
   cout << "Hai preso " << presa << " fiammiferi." << endl;
   cout << "Ne rimangono " << fiammiferi << "." << endl;
}

void mossaAnatra()
{
   int presa;

   if( 1 < fiammiferi ) {
      presa = fiammiferi - 1;
   }
   if( 6 < fiammiferi ) {
      presa = fiammiferi - 6;
   }
   if( 11 < fiammiferi ) {
      presa = fiammiferi - 11;
   }
   if( 16 < fiammiferi ) {
      presa = fiammiferi - 16;
   }

   fiammiferi -= presa;

   cout << "Io prendo " << presa << " fiammiferi." << endl;
   cout << "Adesso ne rimangono " << fiammiferi << "." << endl
            << endl;
}

Come vedete, per quanto mi sia sforzato di rimanere il più attaccato possibile alla versione JavaScript, via via che entriamo nel mondo dal C++ siamo costretti ad allontanarci dagli altri.

Il C++ non nasce per interagire strettamente con un file HTML, ma volendo potrebbe anche farlo, solo che sarebbe così dispendioso in termini di quantità di codice da scrivere da non avere alcun senso (ammesso e non concesso che a me riuscisse scriverlo, quel codice!).

Per poter presentare una finestra carina come quella che riusciamo a fare sommando le potenzialità di HTML5 e JavaScript, ossia con le immagini dei due giocatori e il testo disposto per bene in uno spazio organizzato, dobbiamo aspettare di usare le librerie Qt.


Però possiamo intanto introdurre dei nuovi costrutti, ossia nuovi modi di ‘costruire’ blocchi, come i due cicli do-while e while che compaiono in questo programma. Riguardo a essi non saprei bene cosa aggiungere rispetto a ciò che ho scritto sotto forma di commento nel codice.


Entrambi questi tipi di blocchi servono a ripetere un certo numero di istruzioni per un numero illimitato di volte, ossia finché una determinata condizione da vera diventa falsa. Sono quindi del tutto diversi da for perché quel blocco nasce per essere ripetuto un numero predeterminato di volte.

Questo tipo di blocchi, ossia quelli che si devono ripetere più di una volta, vengono di solito chiamati cicli o, in inglese, loop; in questo caso la traduzione non è, diciamo, andata male, ma il significato prevalente di loop è quello di “anello”, “circuito”, “asola”, “cappio”… In un fiume, ad esempio, “ansa”.

Per indicare una ripetizione del blocco si usa il parolone iterazione.


Anche se è comodo avere due tipi di blocchi, un tipo che si ripete un numero non preordinato di volte e un altro di cui posso con facilità controllare quante volte si ripete (detto con il parolone: quante iterazioni compie), la verità è che posso sempre forzare la natura di questi due blocchi per far loro fare ciò che più mi piace.

int iterazioni = 0;
while ( iterazioni < 10 ) {
   iterazioni++;
}

è un blocco che di per sé nasce per essere ripetuto un numero imprecisato di volte, ma possiamo prevedere con grande facilità che compirà esattamente 10 iterazioni.

for ( int iterazioni = 0; iterazioni < 10; iterazioni++ ) {
   iterazioni--;
}

nascerebbe per ripetersi solo 10 volte, ma temo che proseguirà per sempre…


La differenza tra il ciclo do-while e il ciclo while è che in quest’ultimo la condizione viene letta subito, perciò, se questa è falsa, il ciclo non viene proprio eseguito; invece nel primo la condizione viene letta alla fine, perciò almeno una volta le istruzioni contenute vengono eseguite.


L’unica variabile globale che rimane nel nostro codice C++ è ‘fiammiferi’, ma, essendo i programmatori C++ così riottosi nel dichiarare variabili globali, non possiamo evitare di esercitarci nella domanda se davvero sia indispensabile avere una variabile globale. E la risposta è ovviamente no, non è indispensabile.

Infatti ‘fiammiferi’ potrebbe essere dichiarata all’interno di main() e passata alle varie funzioni durante l’invocazione – ad esempio, mossaCane(fiammiferi).

Le medesime funzioni potrebbero restituire un intero, che sarebbe il nuovo numero di fiammiferi rimasti, ossia il valore da inserire nella variabile ‘fiammiferi’.

int mossaCane(int nuovavariabile);
int mossaAnatra(int nuovavariabile);

Il valore restituito andrebbe, in main(), inserito nella variabile ‘fiammiferi’, che a questo punto diverrebbe una pura variabile locale.


Tutto questo è lasciato come esercizio perché non è al di sopra delle vostre capacità, anche se ci sono diverse modifiche da apportare al programma.


Scrivere questo codice vi potrebbe far apparire molto desiderabile l’uso delle variabili globali, e non sarebbe una percezione del tutto sbagliata. Per fortuna il C++ ha inventato un altro modo per gestire questo problema, ossia le variabili che devono essere modificate da più funzioni.


Allora reggetevi perché stanno per arrivare references e puntatori.