Indovinelli con Scratch

In questa lezione realizzemo un gioco con gli indovinelli con Scratch.
Proporremo 4 semplici indovinelli:
1) Giro curioso nel bosco fitto e frondoso. Mi arrotolo in palla, sono piccolo e gioioso.
2) Mi nutro di insetti nell’oscurità, Un piccolo mammifero nella mia verità.
3) Nella notte mi senti cantare, Con occhi grandi posso guardare.
4) Faccio il sonnellino durante la lunga stagione. Amo miele e pesce, sono un buon pescatore!

Per individuare la risposta corretta, occorre trascinare ciascun animale sulla macchina. Se la macchina parte con l’animale vuol dire che la risposta è corretta, altrimenti la macchina cambia colore e l’animale ritorna in posizione.

Ecco una possibile implementazione del gioco indovinelli con Scratch:

Equazione di secondo grado in C

Equazione di secondo grado in C

Realizziamo un programma che risolva un’equazione di secondo grado in C.


Equazioni di secondo grado

Innanzitutto partiamo dalla definizione. Un’equazione di secondo grado è un’equazione di grado 2 con, eventualmente, esponenti di grado inferiore.

Un’equazione di secondo grado scritta nella forma canonica è del tipo:

ax2+bx+c=0

Dove

a è il coefficiente del termine di grado 2

b è il coefficiente del termine di grado 1

c è il coefficiente del termine di grado 0, detto anche termine noto


Per risolvere l’equazione occorre conoscere i tre coefficienti. Una volta acquisiti i tre valori occorre calcolare il determinante o delta utilizzando la formula:

b*b-4*a*c;

In base al determinante si verificano queste situazioni:

se il determinante è minore di zero, non esistono soluzioni reali;

se il determinante è uguale a zero, l’equazione ammette due soluzioni reali coincidenti;

se il determinante è maggiore di zero, l’equazione ammette due soluzioni reali distinte;

Inoltre, se il coefficiente a è uguale a zero, chiaramente non ci troveremo più di fronte ad un’equazione di secondo grado ma di primo grado. Dunque ovviamente non si potrà applicare la formula.

Nei casi in cui le soluzioni esistono si ottengono con questa formula:

x1=(-b+sqrt(determinante))/2*a

x2=(-b-sqrt(determinante))/2*a

dove sqrt è la funzione per il calcolo della radice quadrata.

Procedimento dell’algoritmo per la risoluzione delle equazioni di secondo grado

Per risolvere le equazioni di secondo grado in C, si possono creare tante soluzioni.

Ve ne propongo due, una con l’uso delle funzioni o procedure e l’altra senza.

Esempio 1: equazione di secondo grado senza funzioni create in C

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main() {
   float a,b,c;
   double x1,x2,d;

   printf("coefficiente a:\t");
   scanf("%f", &a);
   printf("\ncoefficiente b:\t");
   scanf("%f", &b);
   printf("\ncoefficiente c:\t");
   scanf("%f", &c);

   if (a==0) {
	if((b==0)&&(c==0))
	    printf("\nequazione indeterminata");
	else if(b==0)
	    printf("\nequazione impossibile");
	else {
	   printf("l'equazione e' di primo grado\n");
	   x1=-c/b;
	   printf("\n x= %lf", x1);
	}
  }
  else {
	d=b*b-4*a*c; 
	printf("\nil determinante e' %5.3lf ",d);
	if(d>0) {
	    x1=(-b-sqrt(d))/(2*a);
	    x2=(-b+sqrt(d))/(2*a);
	    printf("\nDue soluzioni reali distinte x1= %5.3lf e x2= %5.3lf ",x1,x2);
	  }
	  else if(d==0) {
	    x1=(-b)/(2*a); 
	    printf("\nDue soluzioni reali coincidenti x1 e x2 uguali a %5.3lf ",x1);
	 }
	 else printf("\nNon esistono soluzioni reali\n");
  }
system("pause");
return 0;
}

Chiaramente si potrebbero aggiungere degli accorgimenti al programma ad esempio considerando le equazioni di secondo grado monomie, ecc..

Esempio 1: equazione di secondo grado con l’uso di funzioni o procedure in C

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

float a, b, c;
double x1,x2,d;

void coefficienti() 
{
   printf("coefficiente a:\t");
   scanf("%f", &a);
   printf("\ncoefficiente b:\t");
   scanf("%f", &b);
   printf("\ncoefficiente c:\t");
   scanf("%f", &c);
}

void determinante()
{
   d=b*b-4*a*c;
}

void soluzioni()
{ 
   if(d<0)
      printf("\nnon possono esserci soluzioni reali");
   else if(d==0) {
      x1=(-b)/(2*a);
      printf("Due soluzioni reali coincidenti x1 e x2 uguali a %5.3lf ",x1);
  }
   else
   {
      x1=(-b-sqrt(d))/(2*a);
      x2=(-b+sqrt(d))/(2*a);
      printf("Due soluzioni reali distinte x1= %5.3lf e x2= %5.3lf ",x1,x2);
   }

}

void equazione_primo()
{
    if((b==0)&&(c==0))
	printf("\nequazione indeterminata");
    else if(b==0)
	printf("\nequazione impossibile");
    else {
	x1=-c/b;
	printf("\n x= %5.3f", x1);
	 }
}

main()
{
   coefficienti();
   if(a==0) 
       equazione_primo();
   else {
        determinante();
        soluzioni();
    }
system("pause");	
}

Alcuni link utili:

Funzioni in C

Funzione strlen() in C

Funzione gets() e puts() in C

Funzioni getchar() e putchar in C

Uso della libreria string.h

Concatenare due stringhe in C

Array di caratteri in C

Ricerca di un elemento in una matrice

Prodotto tra matrici in C

Somma tra due matrici in C

Array multidimensionali

Tavola pitagorica in C

Array o vettori in linguaggio C

Media dei numeri in un array in linguaggio C


Funzioni in C

Funzioni in C

Oggi parleremo delle funzioni in C, uno strumento molto utile e potente che consente il riutilizzo di blocchi di istruzione.

Una funzione può essere vista come un sottoprogramma dove vengono aggregati gruppi di istruzioni.

Le funzioni in C sono utilizzate proprio per evitare di replicare porzioni di codice; infatti invocare un sottoprogramma vuol dire mandare in esecuzione la porzione di codice ad esso relativa.

Una funzione può essere invocata anche più volte e chiaramente in tal caso la porzione di codice verrà ripetuta tante volte quante sono le invocazioni.

In definitiva ogni funzione prende in ingresso un insieme di argomenti detti parametri e restituisce un valore.

Fino ad ora abbiamo utilizzato la funzione main(), che come abbiamo già detto, è la funzione che rappresenta il corpo del programma in C.


Differenza tra procedure e funzioni in C

Innanzitutto occorre fare una distinzione tra procedure e funzioni.
Le funzioni in C ritornano un valore, se il valore di ritorno non è specificato, si assume per default int; se la funzione non ritorna alcun valore, allora si usa un ‘tipo speciale’ detto void, in questo caso parliamo di procedure.

La differenza sostanziale tra funzioni e procedure è dunque che le funzioni restituiscono un qualcosa mentre le procedure no.


Dichiarazioni di funzioni e procedure in C

Prima di utilizzare una funzione occorre dichiararla come si fa per le variabili. Ma, a differenza di quanto abbiamo visto per le variabili, non è sempre necessario dichiarare una funzione prima di poterla invocare.

La dichiarazione ci permette di capire unicamente come invocarla, ma non è obbligatoria. Essa infatti specifica quali e quanti argomenti prende in input, oltre al tipo del valore di ritorno.

La dichiarazione, detta anche prototipo della funzione, và fatta prima del main().

La sintassi è dunque questa:

<tipo_ritorno> nome_funzione ([<elenco_parametri>])

Dove:

<tipo_ritorno> è il valore di ritorno specificato, ricordiamo che se non viene specificato si assume per default int e se il tipo di ritorno è void si tratta di una procedura.

nome_funzione o nome_procedura è il nome che viene dato alla funzione o alla procedura. Si raccomanda di dare nomi sensati e di seguire le stesse regole sintattiche che si utilizzano per le variabili.

elenco_parametri rappresentano i valori in ingresso su cui agire, detti anche parametri formali.

Ecco quindi alcuni esempi di dichiarazione:

double cubo(float c);

int max(int x, int y);

int minimo(double x, y);

che equivale a: int minimo(double a, int b);
e non a: int minimo(double a, double b);

int fattoriale(int);

void stampa();  indica la dichiarazione della procedura stampa();

Una dichiarazione inoltre deve essere coerente con la definizione che la segue.


Definizione di funzioni e procedure in C

Prima di essere utilizzata una funzione deve essere o dichiarata o definita.

Una funzione viene definita o prima del main() se non è presente la dichiarazione, altrimenti può essere definita anche dopo il main().

Se il compilatore ad esempio trova una chiamata alla funzione prima della sua definizione, non sa quanti e di che tipo siano i parametri, quindi fa delle assunzioni e magari effettua dei casting, ma non sempre in maniera corretta.

Le funzioni in C ritornano un valore specificato e si definiscono in questo modo:

<tipo_ritorno> nome_funzione ([<elenco_parametri>])

{

<istruzioni>

return valore_restituito;

}

Dove:

per <tipo_ritorno>, nome_funzione o nome_procedura ed elenco_parametri valgono le stesse regole di prima.

Quindi tra le parentesi graffe si inseriscono le istruzioni e tra queste istruzioni assume particolare importanza return, che viene utilizzata per restituire un valore al chiamante. Il valore restituito però deve essere compatibile con il tipo restituito dalla funzione.

Facciamo dunque alcuni esempi.

Funzione che prende due interi e restituisce l’intero più grande:

int max(int x, int y)

{

if (x >= y)

return x;

else return y;

}

Esempio dove si verifica una conversione implicita. Si verifica quando il valore restituito non è coerente con il tipo_ritorno. In questo caso, infatti, la funzione PiGreco ritornerà il valore troncato a 3.

int PiGreco()

{

return 3.14;

}

Dunque, se non c’è coerenza tra il tipo di ritorno e il tipo dell’espressione passata a return, si applicano le regole di conversione implicita.

Quindi in definitiva o la dichiarazione (prototipo) o la definizione devono sempre precedere ogni utilizzo della funzione stessa.

N.B. Una funzione si può dichiarare all’interno di un’altra funzione, ma non si può definire. Dunque in C non si possono definire funzioni dentro funzioni.


Invocazione di una funzione o procedura in C

L’invocazione, ovvero la chiamata di funzione, è un’istruzione che permette l’esecuzione della funzione.

Esempi:

c=cubo(lato); viene invocata la funzione cubo su lato;

b=quadrato(x); viene invocata la funzione quadrato su x;

max=massimo(x,y); viene invocata la funzione massimo sui numeri x e y.


Facciamo adesso degli esempi molto semplici per capire meglio l’uso delle funzioni.


Esempio 1 di funzioni in C – funzione che calcola il volume di un cubo

Per quanto detto prima, per poter utilizzare un identificatore occorre dichiararlo, quindi inserisco:

double cubo(float); //dichiarazione o prototipo di funzione

In questo modo dichiaro la funzione cubo, prima del main(), che restituisce al programma un valore di tipo double e si dichiara che accetta in ingresso un solo argomento il cui tipo è float.
Quindi in questo caso la definizione della funzione può avvenire anche dopo l’invocazione.

double cubo(float c) //definizione di funzione
{
return c*c*c;
}

In alternativa, se ometto la dichiarazione, allora devo inserire la definizione della funzione prima del main().


Allego i due esempi. Il primo con la dichiarazione della funzione o prototipo:

#include <stdio.h>

double cubo(float);//prototipo o dichiarazione della funzione
main () {
  float lato;
  double c;
	
  printf("Inserisci il lato del cubo, calcolero' il volume:\n");
  scanf("%f", &lato);
	
  c=cubo(lato);	//invocazione della funzione
  printf("%.2f", c);
}

double cubo(float c) //definizione della funzione
{
   return c*c*c;
}

Seconda soluzione senza dichiarazione ma con la definizione

#include <stdio.h>

double cubo(float c) //definizione funzione cubo
{
   return c*c*c;
}

main ()
{
    float lato;
    double c;
	
    printf("Inserisci il lato del cubo, calcolero' il volume:\n");
    scanf("%f", &lato);
	
    c=cubo(lato);	//invocazione funzione cubo
    printf("%.2f", c);
}

Esempio 2 di procedura in C – visualizzare un messaggio

Un tipico esempio di procedure, ovvero di funzioni che non ritornano nessun valore, è quando dobbiamo visualizzare semplicemente un messaggio. Quindi un esempio banale è questo:

#include <stdio.h>

double cubo(float c) //definizione di funzione
{
    return c*c*c;
}

void stampa() //definizione di procedura
{    
    printf("Il volume e':\t");
}

main ()
{
	float lato;
	double c;
	
	printf("Inserisci il lato del cubo, calcolero' il volume:\n");
	scanf("%f", &lato);
	
	c=cubo(lato);  //invocazione di funzione
	stampa();	//invocazione di procedura
	printf("%.2f", c);
}

Esempio 3 – conto alla rovescia con le procedure

Facciamo un altro semplicissimo esempio sull’uso delle procedure. Realizzeremo quindi un programma che fa il conto alla rovescia utilizzando una procedura.

#include <stdio.h>

void contare(int j)  //definizione di procedura
{ 
	printf("%d\t", j);
}

int main() {
	int i;
	for (i=10; i>0; i--)
	    contare(i);  //invocazione procedura
	return 0;
}

Esempio 4 – uso delle funzioni per il calcolo del massimo fra 3 numeri

Facciamo adesso un altro semplice esempio che calcola il massimo tra 3 numeri, stavolta utilizzando le funzioni.

#include <stdio.h>

int  massimo(int x, int y, int z)
{
int max=x;
  if (y>max) max=y;
  if (z>max) max=z;
return max;
}

int main() {
  int a, b, c;
  printf("dammi 3 numeri:\n");
  scanf("%d %d %d",&a,&b,&c);
  printf("il massimo e': %d", massimo(a,b,c));
  return 0;
}


Esempio 5 – media di 10 numeri usando una funzione

Supponiamo di voler fare la media dei voti di 10 materie e utilizziamo una funzione somma che poi invocheremo per fare la media.

#include <stdio.h>
#define MATERIE 10

float somma() 
{
	int i;
	float s=0;

	float voto;
	for(i=0;i<MATERIE;i++){
		printf("inserisci il voto:\t");
		scanf("%f", &voto);
		s+=voto;
	}
	return s;
}

void stampa()
{
    printf("la media e':\t");
}

main ()
{
	float media;
        media=somma()/MATERIE;	
	stampa();
	printf("%.2f", media);
	
}

Chiaramente questi sono solo dei semplici esempi, più avanti approfondiremo ancora le funzioni in C.

N.B. Alcuni sinonimi del termine funzione sono procedura, sottoprogramma, routine e subroutine.

Alcuni link utili:

Funzione strlen() in C

Funzione gets() e puts() in C

Funzioni getchar() e putchar in C

Uso della libreria string.h

Concatenare due stringhe in C

Array di caratteri in C

Ricerca di un elemento in una matrice

Prodotto tra matrici in C

Somma tra due matrici in C

Array multidimensionali

Tavola pitagorica in C

Array o vettori in linguaggio C

Media dei numeri in un array in linguaggio C