[C] Esercizio lancio cannone

Messaggioda framelone96 » 10/07/2020, 23:13

Buonasera a tutti! Ho svolto il seguente esercizio di informatica in C (il testo è abbastanza lungo ma non mi è sembrato difficile) e vorrei delle opinioni sulla risoluzione. Se magari ci sono errori che non ho visto oppure qualcosa che possa essere migliorato. Il testo:

Si consideri un cannone posto nell’origine di un sistema cartesiano a tre assi, dove il piano xy corrisponde al piano orizzontale e l’asse z alla verticale. La direzione verso cui spara il cannone è individuata da due angoli: l’azimut, cioè l’angolo compreso tra l’asse x e la proiezione sul piano orizzontale della direzione del cannone, e l’altezza, cioè il complementare dell’angolo tra la direzione del cannone e l’asse z. Il cannone spara ad azimut pari a 0, verso le x positive, ma con altezza θ variabile. Il proiettile esce dalla bocca del cannone con modulo della velocità v pari sempre a 300 km/h. Il moto del proiettile si svolge sotto l’azione della forza di gravità (si consideri g = 9.80665 m⁄s^2 ) e la sua traiettoria è sempre contenuta nel piano xz. Il moto si considera concluso non appena il proiettile incontra nuovamente l’asse x dopo essere stato sparato. Indichiamo con x la distanza tra il punto in cui il proiettile arriva al suolo e il cannone posto nell’origine. Tale distanza varia a seconda dell’angolo di altezza θ con la formula:

$ x= v^2sin(2vartheta )/g $

Il bersaglio che il cannone intende colpire e una circonferenza di raggio 10 m, contenuta nel piano xy e il cui centro e contenuto sull’asse x a distanza D dall’origine. Si scriva un programma che simula dei tentativi di colpire il bersaglio con il cannone descritto, date le seguenti indicazioni.
Il programma deve leggere da riga di comando il valore, espresso in metri, della distanza D a cui si pone il bersaglio dall’origine. I valori accettabili di D variano tra 600 m e 720 m. Il cannone ha a disposizione N munizioni. Il programma simuli il lancio di tutti i proiettili, scegliendo per ciascuno dei lanci un diverso angolo di altezza θ, usando un algoritmo pseudocasuale per selezionarne i valori tra 30◦ e 60◦ . Il programma deve stabilire, per ciascuno dei lanci, se sia stato colpito il bersaglio. A ogni tentativo si stampi l’angolo espresso in gradi, la distanza espressa in metri, e infine la parola COLPITO o MANCATO, a seconda dei casi. Si separino le tre colonne con un punto e virgola (;) seguito da uno spazio. Si usino al massimo due cifre decimali. Al termine degli N colpi, si stampi sul monitor la percentuale di volte che il bersaglio è stato colpito, con al più due cifre decimali. Nella versione finale, si definisca N pari a 120. Non è consentito dichiarare vettori la cui dimensione sia specificata dal nome di una variabile (è invece possibile allocare dinamicamente lo spazio per un vettore o per una matrice la cui dimensione non sia nota a priori).


Questo è il mio svolgimento:
Codice:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define Vo 83.333
#define g 9.80665
#define N 120


double Direzione_Cannone()
{
   double Direzione;
   Direzione = 3000+ rand()%3100;
   return Direzione/100;
}

double Calcolo_Gittata()
{
   double Direzione;
   Direzione= Direzione_Cannone();
   printf("%2.2f° ",Angolo);
   return (pow((Vo),2)*sin(2*(Direzione*3.14)/180))/g;
   
}


int main(int argc, char * argv[])
{
   int Bersaglio_Centrato=0,Prove;
   double Gittata, D;
   srand(time(NULL));
   
   for (Prove=0; Prove <N ; Prove++)
      {
      
      D=atof(argv[1]);
      Gittata = Calcolo_Gittata();
      printf("  %3.2f Metri",Gittata);
   
   
         if(Gittata>=D-10 && Gittata<=D+10)
            {   
            Bersaglio_Centrato++;
            printf("    Bersaglio Colpito!\n");
            }
         else
            

            printf("    Bersaglio Mancato!\n");
            
      }
   
   printf("\nIl cannone ha colpito il bersaglio con una percentuale del %3.2f%%",((double)Bersaglio_Centrato/N)*100);

   
}


Grazie in anticipo!
framelone96
Starting Member
Starting Member
 
Messaggio: 4 di 12
Iscritto il: 29/05/2020, 01:07

Re: [C] Esercizio lancio cannone

Messaggioda Lucacs » 11/07/2020, 11:44

A me sembra perfetto.
Anche se sarebbe stato meglio farlo in c++
Lucacs
Average Member
Average Member
 
Messaggio: 423 di 980
Iscritto il: 06/01/2020, 10:07

Re: [C] Esercizio lancio cannone

Messaggioda framelone96 » 11/07/2020, 14:33

Grazie mille! Sì purtroppo era obbligatorio farlo in C
framelone96
Starting Member
Starting Member
 
Messaggio: 5 di 12
Iscritto il: 29/05/2020, 01:07

Re: [C] Esercizio lancio cannone

Messaggioda apatriarca » 11/07/2020, 22:24

Prima di tutto il programma non segue le richieste dell'esercizio:
1. L'output del programma è nel formato sbagliato. Veniva richiesto l'angolo, la gittata e una tra le parole COLPITO e MANCATO separati dal punto e virgola. Il tuo output contiene le stesse informazioni, ma il formato non è quello corretto.
2. L'angolo deve essere compreso tra \(30^\circ\) e \(60^\circ\) gradi secondo il testo dell'esercizio. Nel tuo caso stai invece generando valori tra \(30.00^\circ\) e \(60.99^\circ\).

Contiene poi un errore in fase di compilazione. Nel seguente codice la variabile Angolo non è infatti dichiarata.
Codice:
double Calcolo_Gittata()
{
   double Direzione;
   Direzione = Direzione_Cannone();
   printf("%2.2f° ", Angolo);
   return (pow((Vo),2)*sin(2*(Direzione*3.14)/180))/g;
}

Avresti dovuto scrivere Direzione.

Ci sono poi altri commenti più stilistici:
1. La conversione da gradi a radianti nel tuo codice è un po' approssimativa.
2. Non è necessario separare dichiarazione e inizializzazione di una variabile. È anzi spesso consigliabile fare le due cose insieme.
3. Non è più necessario dichiarare le variabili all'inizio della funzione (in effetti non lo è mai stato*) da circa due decenni. Personalmente preferisco dichiarare le variabili subito prima di usarle.
4. Quando si scrivono delle funzioni è utile cercare di renderle il più riutilizzabili possibili. Le tue funzioni non sono riutilizzabili perché contengono troppa logica specifica del tuo esercizio. Sarebbe stato meglio avere le due funzioni seguenti: una che generasse un numero compreso tra valori passati come argomento e un'altra che calcolasse la gittata da un angolo passato come argomento.
5. time(NULL) non è necessariamente il miglior modo per inizializzare il generatore di numeri pseudocasuali perché cambia solo ogni secondo.
6. Personalmente preferisco Vo * Vo piuttosto che pow((Vo),2) perché lo trovo più leggibile e il prodotto è più veloce di una potenza da calcolare (in effetti il compilatore converte la potenza in prodotto automaticamente probabilmente).
7. Non vedo in che modo l'uso del C++ in questo caso sarebbe automaticamente migliore.

* La richiesta in C89 era di dichiarare le variabili all'inizio del blocco di codice in cui venivano usate che poteva quindi anche essere il blocco di un if o di un ciclo per esempio.
apatriarca
Moderatore
Moderatore
 
Messaggio: 5456 di 10435
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Esercizio lancio cannone

Messaggioda Lucacs » 12/07/2020, 01:24

Alcune considerazioni sono soggettive
Comunque concordo.
Il c++ ha un maggiore controllo dei tipi e migliori librerie con molte soluzioni.
La random del c++ qui, per esempio, andava benone.
Lucacs
Average Member
Average Member
 
Messaggio: 427 di 980
Iscritto il: 06/01/2020, 10:07

Re: [C] Esercizio lancio cannone

Messaggioda framelone96 » 12/07/2020, 10:39

Grazie per avermi fatto notare gli errori, ora li sistemo. Avendo seguito solo un piccolo corso di informatica in università, molte cose su come ottimizzare e migliorare i programmi non le so, quindi grazie mille per i consigli!
framelone96
Starting Member
Starting Member
 
Messaggio: 6 di 12
Iscritto il: 29/05/2020, 01:07

Re: [C] Esercizio lancio cannone

Messaggioda apatriarca » 12/07/2020, 18:55

@Lucas: Tutti i punti che ho indicato come "stilistici" sono certamente per la maggior parte soggettivi. Il punto sul C++ riguarda principalmente questo esercizio, in cui la differenza tra i due linguaggi non sarebbe particolarmente grossa. Devo poi dire di non amare le funzioni random del C++ per quanto siano certamente un miglioramento rispetto alle funzioni dello standard C. Sono infatti incredibilmente poco leggibili e user-friendly.
apatriarca
Moderatore
Moderatore
 
Messaggio: 5457 di 10435
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Esercizio lancio cannone

Messaggioda Lucacs » 13/07/2020, 08:01

Era per dire, poi puoi usare un sacco di algoritmi pronti, dalle distribuzioni gaussiane, al metodo monte Carlo e altri ancora
Comunque bravo e grazie ti leggo con piacere
Lucacs
Average Member
Average Member
 
Messaggio: 433 di 980
Iscritto il: 06/01/2020, 10:07


Torna a Informatica

Chi c’è in linea

Visitano il forum: Google [Bot] e 1 ospite