Advertisement
Guest User

Untitled

a guest
Jun 24th, 2017
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 35.01 KB | None | 0 0
  1. /*
  2. \file drop.c
  3.   \authors Framba Luca & Amato Lorenzo Gaetano informatica (CDS Fisica) 2016/17
  4.   \brief assegnamento 2: intestazione delle funzioni da implementare
  5.  */
  6.  
  7. /* protezione inclusioni multiple */
  8. #ifndef __DROP__H
  9. #define __DROP__H
  10.  
  11. #include <math.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <errno.h>
  15. #include "drop.h"
  16. #include <stdbool.h>
  17.  
  18. /* ATTENZIONE: l'area di caduta e' rappresentata con una matrice di puntatori
  19.    a righe e NON e' globale come era nel primo assegnamento */
  20.  
  21. /** tipo delle 4 adiacenze
  22.     con cui stiamo lavorando (nessuna, croce, diagonale, entrambe) */
  23. typedef enum {NONE, CROSS, DIAGONAL, BOTH} adj_t;
  24.  
  25. /** valori possibili per la matrice che rappresenta l'area di caduta, EMPTY contraddistingue un'area vuota, FULL un'area un cui si e' gia' sedimentata una
  26. particella e OSTACLE rappresenta un'area occupata da un ostacolo. FULL ed OBSTACLE non sono attraversabili*/
  27. #define EMPTY '.'
  28. #define FULL '*'
  29. #define OBSTACLE '@'
  30.  
  31. /** ogni ostacolo e' quadrato o rettangolare e definito dalle coordinate dell'estremo in alto a sinistra e in basso a destra all'interno della matrice che rappresenta l'area di caduta. s_i deve sempre essere minore o uguale di d_i e s_j mionre uguale di d_j */
  32. typedef struct {
  33.   unsigned s_i, s_j; /* coordinate dell'angolo in alto a sinistra */
  34.   unsigned d_i, d_j; /* coordinate dell'angolo in basso a destra */
  35. } obstacle_t;
  36.  
  37. /** Lista degli ostacoli, sempre ordinata in senso crescente. L'ordinamento
  38. e' definito come segue:
  39.  
  40. L'ostacolo [(x1,y1),(t1,q1)] precede [(x2,y2),(t2,q2)] se vale che
  41. se x1!= x2 e x1 < x2 oppure
  42. se x1 == x2 e y1!= y2 e y1 < y2 oppure
  43. se x1 == x2 e y1 == y2 e t1!= t2 e t1 < t2 oppure
  44. se x1 == x2 e y1 == y2 e t1 == t2 e q1!= q2 e q1 < q2
  45. */
  46. typedef struct list  {
  47.   obstacle_t * pobj; /* puntatore all'ostacolo */
  48.   struct list * next; /* puntatore al prossimo elemento della lista */
  49. } lista_t;
  50.  
  51. /* prototipi di tutte le funzioni */
  52.  
  53. void init_matrix (char** mat, unsigned n, unsigned m);
  54. void free_matrix (char*** pmat, unsigned n);
  55. int step (int* next_i, int* next_j, adj_t ad, char** mat, int n, int m);
  56. obstacle_t * string_to_obstacle (char * s);
  57. char * obstacle_to_string (obstacle_t * po, char* s, int n);
  58. int put_obstacle_in_matrix (obstacle_t * s,char ** mat, unsigned n, unsigned m);
  59. lista_t * put_obstacle_in_list (obstacle_t* p,lista_t* l);
  60. void free_list (lista_t ** plist);
  61.  
  62. /** (FORNITA DAI DOCENTI)
  63.     alloca una nuova matrice che rappresenta l'area di caduta utilizzando
  64.     la rappresentazione con array di puntatori a righe
  65.     (senza inizializzarla)
  66.    
  67.    \param n numero di righe
  68.    \param m numero di colonne
  69.  
  70.    \retval NULL se si e' verificato un errore (setta errno)
  71.    \retval p il puntatore alla matrice allocata
  72. */
  73. char** new_matrix (unsigned n, unsigned m);
  74.  
  75.  
  76. /** (FORNITA DAI DOCENTI)
  77.    stampa la matrice mat sul file "f" (gia' aperto) usando
  78.    -- il carattere '.' (EMPTY) per le posizioni vuote
  79.    -- il carattere '*' (FULL) per le posizioni piene
  80.    -- il carattere '@' (OBJECT) per le posizioni occupate dagli ostacoli
  81. (i caratteri utilizzati nelle macro che li definiscono)
  82.  
  83.    \param f il file in cui stampare (gia' aperto in scrittura)
  84.    \param mat il puntatore alla matrice
  85.    \param n numero di righe
  86.    \param n numero di colonne
  87. */
  88.  
  89.  
  90. void fprint_matrix (FILE * f, char ** a, unsigned n, unsigned m);
  91.  
  92.  
  93. /** inizializza la matrice mat settando tutti i valori a EMPTY
  94.    
  95.    \param mat puntatore alla matrice
  96.    \param n numero di righe
  97.    \param m numero di colonne
  98. */
  99. void init_matrix (char** mat, unsigned n, unsigned m){
  100.  
  101.     int i,j;
  102.    
  103.     if((mat == NULL) || (n == 0) || (m == 0)){ /* matrice vuota */
  104.         printf("Matrice vuota.\n");
  105.        
  106.     }
  107.     else{
  108.         for(i=0;i<n;i++){ /* i scorre sulle righe */
  109.             for(j=0;j<m;j++) /* j scorre sulle colonne */
  110.                 mat[i][j] = EMPTY; /* assegna ad ogni valore di riga e colonna il valore EMPTY */
  111.  
  112.         }
  113.     }
  114.     return;
  115. }
  116.  
  117. /** libera la memoria occupata dalla matrice e mette a NULL il puntatore pmat
  118.  
  119.     \param pmat puntatore al puntatore alla matrice da liberare
  120.     \param n numero di righe
  121.  */
  122. void free_matrix (char*** pmat, unsigned n){
  123.     int i; /* variabile per muoversi nel ciclo for */
  124.     char **s;
  125.     s = *pmat; /* s diventa il puntatore alla matrice da liberare */
  126.    
  127.     for(i=0;i<n;i++)
  128.         free(s[i]); /* dealloca la memoria di tutte le colonne della matrice */
  129.     free(s); /* dealloca  la memoria dell'array di puntatori alle righe */
  130.     *pmat = NULL; /* mette il puntatore alla matrice a NULL */
  131.     return;
  132. }
  133.  
  134. /** calcola la caduta della prossima particella restituendo le coordinate (i,j) del prossimo elemento dell'area da mettere a FULL
  135.  
  136.    \param next_i l'indirizzo della variabile dove scrivere il valore della coordinata i
  137.    \param next_j l'indirizzo della variabile dove scrivere il valore della coordinata j
  138.    \param ad tipo di adiacenza con cui stiamo lavorando (croce, diagonale o entrambe)
  139.    \param mat puntatore alla matrice
  140.    \param n numero di righe della matrice
  141.    \param m numero di colonne della matrice
  142.  
  143.    \SPECIFICA
  144.    il prossimo elemento da riempire viene calcolato simulando la caduta di una particella
  145.    a partire dalla posizione P0 di coordinate ( 0, M/2 ),
  146.    ad ogni passo, se mi trovo nella posizione Pi = (i,j) considero l'insieme U delle celle non ancora piene fra la tre celle
  147.               (i+1,j-1) (i+1,j) (i+1,j-1)
  148.    e scelgo in modo equiprobabile fra le celle in U, ad esempio nel caso in cui le tre celle contengano rispettivamente
  149.               EMPTY EMPTY FULL
  150.    U = { (i+1,j-1), (i+1,j) }
  151.    e scelgo fra i due elementi di U con probabilità 1/2.
  152.  
  153.    La caduta della particella si arresta quando di verifica uno dei due seguenti casi:
  154.    1) sono arrivato all'ultima riga (la N-1) (quindi mi sedimento sul fondo)
  155.    2) U e' vuoto
  156.    3) ho almeno una cella piena nell'intorno di (i,j) definito da dall'adiacenza "ad" ovvero
  157.       a) nessuno (NONE): in questo caso mi fermo solo se (i+1,j), (i+1,j-1) e (i+1,j+1) sono gia' piene (U e' vuoto)
  158.       b) croce (CROSS):
  159.                 (i-1,j)
  160.      (i,j-1)     <i,j>    (i,j+1)
  161.                 (i+1,j)  
  162.       c) diagonale (DIAGONAL)
  163.      (i-1,j-1)            (i-1,j+1)
  164.                  <i,j>    
  165.      (i+1,j-1)            (i+1,j+1)
  166.      d) croce e diagonale insieme (BOTH)
  167.      (i-1,j-1)   (i-1,j)        (i-1,j+1)
  168.       (i,j-1)     <i,j>          (i,j+1)
  169.      (i+1,j-1)   (i+1,j)        (i+1,j+1)
  170.  
  171.    In tutti i casi --> restituisco in *next_i
  172.    il valore di i e in *next_j il valore di j
  173.  
  174.    \retval 0 se le coordinate sono state calcolate correttamente
  175.    \retval -1 se il punto di caduta iniziale P0
  176.     al centro della prima riga è già FULL  
  177.     in questo caso non viene modificato il valore di *next_i *next_j
  178.  
  179. */
  180.  
  181. int step (int * next_i, int * next_j, adj_t ad, char ** mat, int n, int m){
  182.   /* i e j servono per muoversi all'interno della variabile e p assumerà un valore casuale tra 0 e 2 per scegliere in modo pseudocasuale il
  183.   prossimo passo */
  184.   int i=0,j,p;
  185.   /* j diventa la parte intera di m/2 in caso di m dispari, avendolo definito come int è un passaggio superfluo ma rassicurante */
  186.   j = (int) m/2;
  187.  
  188.   bool check = true; /* variabile che controlla se la particella sedimenta */
  189.  
  190.   /* la prima posizione della matrice è occupata oppure la matrice ha dimensioni sulle quali applicare la funzione ritorna errore */
  191.   if((mat[i][j] != EMPTY) || (m <= 1) || (n <= 1))
  192.     return -1;
  193.  
  194.  
  195.   switch(ad){ /* controlla il tipo di adiacenza */
  196.     case BOTH:{ /* adiacenza BOTH */
  197.     while(check){
  198.  
  199.         /* condizioni che fan sedimentare la particella */
  200.  
  201.         if(i == n-1) /* la particella è sul fondo */
  202.             {check = false; *next_i = i; *next_j = j;}
  203.        
  204.         else if(i == 0){ /* la particella è nella prima riga */
  205.             /* la particella non sedimenta nella posizione attuale quindi prosegue */
  206.             if( (mat[1][j-1] == EMPTY)&&(mat[1][j]== EMPTY)&&(mat[1][j+1] == EMPTY) ){
  207.                 i++;
  208.                 p = my_rand()%3;
  209.                 switch(p){
  210.                     case 0: j--; break;/* la particella prosegue a sinistra */
  211.                     case 1:; break; /* la particella prosegue dritta */
  212.                     case 2: j++; break;/* la particella prosegue a destra */
  213.                 }
  214.             }
  215.             /* la particella sedimenta nella posizione attuale */
  216.             else {check = false; *next_i = i; *next_j = j;}
  217.         }
  218.  
  219.         /* la particella è sul bordo sinistro e una delle posizioni attorno alla particella è FULL o OBSTACLE la particella sedimenta */
  220.         else if( (j == 0) &&
  221.         ( (mat[i-1][j] != EMPTY)||(mat[i-1][j+1] != EMPTY)||(mat[i][j+1] != EMPTY)||(mat[i+1][j] != EMPTY)||(mat[i+1][j+1] != EMPTY) ) )
  222.             {check = false; *next_i = i; *next_j = j;}
  223.  
  224.         /* la particella è sul bordo destro e una delle posizioni attorno alla particella è FULL o OBSTACLE la particella sedimenta */
  225.         else if( (j == (m-1)) &&
  226.         ( (mat[i-1][j] != EMPTY)||(mat[i-1][j-1] != EMPTY)||(mat[i][j-1] != EMPTY)||(mat[i+1][j] != EMPTY)||(mat[i+1][j-1] != EMPTY) ) )
  227.             {check = false; *next_i = i; *next_j = j;}
  228.  
  229.         /* la particella non è lungo i bordi e una delle posizioni attorno alla particella è FULL o OBSTACLE la particella sedimenta */
  230.         else if( (mat[i-1][j-1] != EMPTY)||(mat[i-1][j] != EMPTY)||(mat[i-1][j+1] != EMPTY)||(mat[i][j-1] != EMPTY)||(mat[i][j+1] != EMPTY)||
  231.         (mat[i+1][j-1] != EMPTY)||(mat[i+1][j] != EMPTY)||(mat[i+1][j+1] != EMPTY) )
  232.             {check = false; *next_i = i; *next_j = j;}
  233.  
  234.         else{ /* la particella non sedimenta nella posizione attuale e quindi procede */
  235.             i++;       
  236.             if(j == 0){ /* la particella è sul bordo sinistro */  
  237.                 p = my_rand()%2;
  238.                 switch(p){
  239.                     case 0:; break; /* la particella prosegue in linea retta */
  240.                     case 1: j++; break; /* la particella prosegue a destra */
  241.                 }
  242.             }
  243.             else if(j == (m-1)){ /* la particella è sul bordo destro */
  244.                 p = my_rand()%2;
  245.                 switch(p){
  246.                     case 0:; break; /* la particella prosegue in linea retta */
  247.                     case 1: j--;  break;/* la particella prosegue a sinistra */
  248.                 }
  249.  
  250.             }
  251.             else{ /* la particella non è lungo i bordi e procede in una delle 3 posizioni sottostanti */
  252.                 p = my_rand()%3;
  253.                 switch(p){
  254.                     case 0:; break; /* la particella prosegue in linea retta */
  255.                     case 1: j--; break; /* la particella prosegue a sinistra */
  256.                     case 2: j++; break; /* la particella prosegue a destra */  
  257.                 }
  258.             }
  259.         } /* else */
  260.     }  /* while */
  261.     }
  262.     case DIAGONAL:{
  263.     while(check){
  264.         /* condizioni che fan sedimentare la particella */
  265.         if(i == n-1) /* la particella è sul fondo */
  266.             {check = false; *next_i = i; *next_j = j;}
  267.  
  268.         else if(i == 0){ /* la particella è nella prima riga */
  269.             /* la particella non sedimenta nella posizione attuale quindi prosegue */
  270.             if( (mat[1][j-1] == EMPTY)&&(mat[1][j+1] == EMPTY) ){
  271.                 i++;
  272.                 if(mat[1][j] != EMPTY){ /* la particella non può proseguire dritta */
  273.                     p = my_rand()%2;
  274.                     switch(p){
  275.                         case 0: j--; break;/* la particella prosegue a sinistra */
  276.                         case 1: j++; break;/* la particella prosegue a destra */
  277.                     }
  278.                 }
  279.                 else{ /* la particella può proseguire in tutte le direzioni */
  280.                     p = my_rand()%3;
  281.                     switch(p){
  282.                         case 0: j--; break;/* la particella prosegue a sinistra */
  283.                         case 1: break;
  284.                         case 2: j++; break;/* la particella prosegue a destra */
  285.                     }
  286.                 }
  287.             }
  288.             /* la particella sedimenta nella posizione attuale */
  289.             else {check = false; *next_i = i; *next_j = j;}
  290.         }
  291.  
  292.  
  293.         /* la particella è sul bordo sinistro, una delle posizioni diagonali alla particella è occupata e la particella sedimenta */
  294.         else if( (j == 0) &&
  295.         ( (mat[i-1][j+1] != EMPTY)||(mat[i+1][j+1] != EMPTY) ) )
  296.             {check = false; *next_i = i; *next_j = j;}
  297.  
  298.         /* la particella è sul bordo destro, una delle posizioni diagonali alla particella è occupata e la particella sedimenta */
  299.         else if( (j == (m-1)) &&
  300.         ( (mat[i-1][j-1] != EMPTY)||(mat[i+1][j-1] != EMPTY) ) )
  301.             {check = false; *next_i = i; *next_j = j;}
  302.  
  303.         /* la particella non è lungo i bordi, una delle posizioni attorno alla particella è occupata e la particella sedimenta */
  304.         else if( (mat[i-1][j-1] != EMPTY)||(mat[i-1][j+1] != EMPTY)||(mat[i+1][j-1] != EMPTY)||(mat[i+1][j+1] != EMPTY) )
  305.             {check = false; *next_i = i; *next_j = j;}
  306.  
  307.         else{ /* la particella non sedimenta nella posizione attuale e quindi procede */
  308.             i++;
  309.             if(j == 0){ /* la particella è sul bordo sinistro */
  310.                 if( mat[i][j] != EMPTY ) /*la posizione sottostante la particella è occupata */
  311.                     j++; /* la particella può solo proseguire a destra */
  312.                 else{ /* la particella può proseguire in entrambe le direzioni */
  313.                     p = my_rand()%2;
  314.                     switch(p){
  315.                         case 0:; break; /* la particella prosegue in linea retta */
  316.                         case 1: j++; break; /* la particella prosegue a destra */
  317.                     }
  318.                 }
  319.             }
  320.             else if(j == (m-1)){ /* la particella è sul bordo destro */
  321.                 if( mat[i][j] != EMPTY) /*la posizione sottostante la particella è occupata */
  322.                     j--; /* la particella può solo proseguire a sinistra */
  323.                 else{ /* la particella può proseguire in entrambe le direzioni */
  324.                     p = my_rand()%2;
  325.                     switch(p){
  326.                         case 0:; break; /* la particella prosegue in linea retta */
  327.                         case 1: j--; break; /* la particella prosegue a sinistra */
  328.                     }
  329.                 }
  330.             }
  331.             else if( mat[i][j] != EMPTY ){ /* la particella non è lungo i bordi e la posizione sotto la particella è occupata */
  332.                 p = my_rand()%2;
  333.                 switch(p){
  334.                     case 0: j++; break;/* la particella prosegue a destra */
  335.                     case 1: j--; break;/* la particella prosegue a sinistra */ 
  336.                 }
  337.             }
  338.             else{ /* la particella non è lungo i bordi, la posizione sottostante non è occupata e procede in una delle 3 posizioni                sottostanti in modo pseudocasuale */
  339.                 p = my_rand()%3;
  340.                 switch(p){
  341.                     case 0:; break;/* la particella prosegue in linea retta */
  342.                     case 1: j--; break;/* la particella prosegue a sinistra */
  343.                     case 2: j++; break;/* la particella prosegue a destra */   
  344.                 }
  345.             }
  346.         }/* else */
  347.     } /* while */
  348.     break;}
  349.  
  350.  
  351.     case CROSS:{ /* adiacenza CROSS */
  352.     while(check){
  353.         /* condizioni che fanno sedimentare la particella */
  354.         if(i == (n-1)) /* la particella è sul fondo */
  355.             {check = false; *next_i = i; *next_j = j;}
  356.  
  357.         else if(i == 0){ /* la particella è nella prima riga */
  358.             /* la particella non sedimenta nella posizione attuale quindi prosegue */
  359.             if( mat[1][j] == EMPTY ){
  360.                 i++;
  361.                 if((mat[1][j-1] != EMPTY) && (mat[1][j+1] != EMPTY)) /* la particella non può proseguire lateralmente */
  362.                     {j = j;} /* la particella prosegue dritta */
  363.                 else if(mat[1][j-1] != EMPTY){ /* la particella non può proseguire a sinistra */
  364.                     p = my_rand()%2;
  365.                     switch(p){
  366.                         case 0: break;/* la particella prosegue dritta */
  367.                         case 1: j++; break;/* la particella prosegue a destra */
  368.                     }
  369.                 }
  370.                 else if(mat[1][j+1] != EMPTY){ /* la particella non può proseguire a destra */
  371.                     p = my_rand()%2;
  372.                     switch(p){
  373.                         case 0: break;/* la particella prosegue dritta */
  374.                         case 1: j--; break;/* la particella prosegue a sinistra */
  375.                     }
  376.                 }
  377.                 else{ /* la particella può proseguire in tutte le direzioni */
  378.                     p = my_rand()%3;
  379.                     switch(p){
  380.                         case 0: j--; break;/* la particella prosegue a sinistra */
  381.                         case 1: break;
  382.                         case 2: j++; break;/* la particella prosegue a destra */
  383.                     }
  384.                 }
  385.             }
  386.             /* la particella sedimenta nella posizione attuale */
  387.             else {check = false; *next_i = i; *next_j = j;}
  388.         }
  389.  
  390.         /* la particella è sul bordo sinistro e una delle posizioni attorno alla particella è occupata e la particella sedimenta */
  391.         else if( (j == 0) &&
  392.         ( (mat[i-1][j] != EMPTY)||(mat[i][j+1] != EMPTY)||(mat[i+1][j] != EMPTY) ) )
  393.             {check = false; *next_i = i; *next_j = j;}
  394.  
  395.         /* la particella è sul bordo destro e una delle posizioni attorno alla particella è occupata e la particella sedimenta */
  396.         else if( (j == (m-1)) &&
  397.         ( (mat[i-1][j] != EMPTY)||(mat[i][j-1] != EMPTY)||(mat[i+1][j] != EMPTY) ) )
  398.             {check = false; *next_i = i; *next_j = j;}
  399.  
  400.         /* la particella non è lungo i bordi e una delle posizioni attorno alla particella è occupata e la particella sedimenta */
  401.         else if( (mat[i-1][j] != EMPTY)||(mat[i][j-1] != EMPTY)||(mat[i][j+1] != EMPTY)||
  402.         (mat[i+1][j] != EMPTY) )
  403.             {check = false; *next_i = i; *next_j = j;}
  404.  
  405.         else{ /* la particella non sedimenta nella posizione attuale e quindi procede */
  406.             i++;       
  407.             if(j == 0){ /* la particella è sul bordo sinistro */  
  408.                 if( mat[i][j+1] != EMPTY ) /*la posizione a destra della particella è occupata */
  409.                     {} /* la particella può solo proseguire in linea retta */
  410.                 else{
  411.                     p = my_rand()%2;
  412.                     switch(p){
  413.                         case 0:; break;/* la particella prosegue in linea retta */
  414.                         case 1: j++; break;/* la particella prosegue a destra */
  415.                     }
  416.                 }
  417.             }
  418.             else if(j == (m-1)){ /* la particella è sul bordo destro */
  419.                 if( mat[i][j-1] != EMPTY ) /* la posizione a sinistra della particella è occupata */
  420.                     {} /* la particella può solo proseguire in linea retta */
  421.                 else{
  422.                     p = my_rand()%2;
  423.                     switch(p){
  424.                         case 0:; break; /* la particella prosegue in linea retta */
  425.                         case 1: j--; break; /* la particella prosegue a destra */
  426.                     }
  427.                 }
  428.             }
  429.             else if( (mat[i][j-1] != EMPTY) && (mat[i][j+1] != EMPTY) ) /* la posizione laterali sotto la particella sono occupate */
  430.                 {} /* la particella può solo proseguire in linea retta */
  431.             else if( mat[i][j-1] != EMPTY ){ /* solo la posizione laterale sinistra è occupata */
  432.                 p = my_rand()%2;
  433.                 switch(p){
  434.                     case 0: j++; break; /* la particella prosegue a destra */
  435.                     case 1: ; break; /* la particella prosegue in linea retta */   
  436.                 }
  437.             }
  438.             else if( mat[i][j+1] != EMPTY ){ /* solo la posizione laterale destra è occupata */
  439.                 p = my_rand()%2;
  440.                 switch(p){
  441.                     case 0: j--; break; /* la particella prosegue a sinistra */
  442.                     case 1: ; break; /* la particella prosegue in linea retta */   
  443.                 }
  444.             }
  445.             else{ /* la particella non è lungo i bordi, la posizioni laterali sottostanti non sono occupate quindi la particella procede               in una delle 3 posizioni sottostanti in modo pseudocasuale */
  446.                 p = my_rand()%3;
  447.                 switch(p){
  448.                     case 0:; break; /* la particella prosegue in linea retta */
  449.                     case 1: j--; break; /* la particella prosegue a sinistra */
  450.                     case 2: j++; break; /* la particella prosegue a destra */  
  451.                 }
  452.             }
  453.         } /* else */
  454.     } /* while */
  455.     break;}
  456.  
  457.     case NONE:{ /* adiacenza NONE */
  458.     while(check){
  459.         /* condizioni che fan sedimentare la particella */
  460.         if(i == (n-1)) /* la particella è sul fondo */
  461.             {check = false; *next_i = i; *next_j = j;}
  462.  
  463.         /* la particella è sul bordo sinistro, le posizioni sotto la particella sono occupate e la particella sedimenta */
  464.         else if( (j == 0) && ( (mat[i+1][j+1] != EMPTY)||(mat[i+1][j] != EMPTY) ) )
  465.             {check = false; *next_i = i; *next_j = j;}
  466.  
  467.         /* la particella è sul bordo destro, le posizioni sotto la particella sono occupate e la particella sedimenta */
  468.         else if( (j == (m-1)) && ( (mat[i+1][j] != EMPTY)&&(mat[i+1][j-1] != EMPTY) ) )
  469.             {check = false; *next_i = i; *next_j = j;}
  470.  
  471.         /* la particella non è lungo i bordi, le posizioni sotto alla particella sono occupate e la particella sedimenta */
  472.         else if( (mat[i+1][j] != EMPTY)&&(mat[i+1][j-1] != EMPTY)&&(mat[i+1][j+1] != EMPTY) )
  473.             {check = false; *next_i = i; *next_j = j;}
  474.  
  475.         else{ /* la particella non sedimenta nella posizione attuale e quindi procede */
  476.             i++;       
  477.             if(j == 0){ /* la particella è sul bordo sinistro */  
  478.                 if( mat[i][j+1] != EMPTY ) /*la posizione laterale destra è occupata */
  479.                     {j=j;} /* la particella può solo proseguire in linea retta */
  480.                 else if (mat[i][j] != EMPTY) /* la posizione sotto la particella è occupata */
  481.                     j++; /* la particella può proseguire solo a destra */
  482.                 else{ /* nessuna delle posizioni sottostanti è occupata */
  483.                     p = my_rand()%2;
  484.                     switch(p){
  485.                         case 0:; break; /* la particella prosegue in linea retta */
  486.                         case 1: j++;break;  /* la particella prosegue a destra */
  487.                     }
  488.                 }
  489.             }
  490.             else if(j == (m-1)){ /* la particella è sul bordo destro */
  491.                 if( mat[i][j-1] != EMPTY ) /* la posizione laterale sinistra è occupata */
  492.                     {} /* la particella può solo proseguire in linea retta */
  493.                 else if (mat[i][j] != EMPTY) /* la posizione sotto la particella è occupata */
  494.                     j--; /* la particella può proseguire solo a sinistra */
  495.                 else{ /* nessuna delle posizioni sottostanti è occupata */
  496.                     p = my_rand()%2;
  497.                     switch(p){
  498.                         case 0:; break;  /* la particella prosegue in linea retta */
  499.                         case 1: j--; break; /* la particella prosegue a sinistra */
  500.                     }
  501.                 }
  502.             }
  503.             else if( (mat[i][j-1] != EMPTY) && (mat[i][j+1] != EMPTY) ) /* la posizione laterali sotto la particella sono occupate */
  504.                 {} /* la particella può solo proseguire in linea retta */
  505.  
  506.             /* solo la posizione laterale sinistra e quella sottostante sono occupate */
  507.             else if( (mat[i][j-1] != EMPTY) && (mat[i][j] != EMPTY) )
  508.                 j++; /* la particella può proseguire solo a destra */
  509.  
  510.             /* solo la posizione laterale destra e quella sottostante sono occupate */
  511.             else if( (mat[i][j+1] != EMPTY) && (mat[i][j] != EMPTY) )
  512.                 j--; /* la particella può proseguire solo a sinistra */
  513.            
  514.             else if( mat[i][j+1] != EMPTY ){ /* solo la posizione laterale destra è occupata */
  515.                 p = my_rand()%2;
  516.                 switch(p){
  517.                     case 0: j--; break; /* la particella prosegue a sinistra */
  518.                     case 1: ; break; /* la particella prosegue in linea retta */   
  519.                 }
  520.             }
  521.  
  522.             else if( mat[i][j] != EMPTY ){ /* solo la posizione sottostante è occupata */
  523.                 p = my_rand()%2;
  524.                 switch(p){
  525.                     case 0: j--; break; /* la particella prosegue a sinistra */
  526.                     case 1: j++; break; /* la particella prosegue a destra */  
  527.                 }
  528.             }
  529.  
  530.             else if( mat[i][j-1] != EMPTY ){ /* solo la posizione laterale sinistra è occupata */
  531.                 p = my_rand()%2;
  532.                 switch(p){
  533.                     case 0: j++; break; /* la particella prosegue a destra */
  534.                     case 1: ; break; /* la particella prosegue in linea retta */   
  535.                 }
  536.             }
  537.             else{ /* la particella non è lungo i bordi, la posizioni laterali sottostanti non sono occupate quindi la particella procede               in una delle 3 posizioni sottostanti in modo pseudocasuale */
  538.                 p = my_rand()%3;
  539.                 switch(p){
  540.                     case 0:; break; /* la particella prosegue in linea retta */
  541.                     case 1: j--; break; /* la particella prosegue a sinistra */
  542.                     case 2: j++; break; /* la particella prosegue a destra */  
  543.                 }
  544.             }
  545.         } /* else */
  546.     }  /* while */
  547.     break;} /* case */
  548.  
  549.   }  /* switch */
  550. return 0;
  551. }
  552.  
  553.  
  554.  
  555. /** legge la rappresentazione di un ostacolo come stringa di 4 estremi interi
  556.     (es. "0 0 3 4" rapresenta i due estremi (0,0) superiore sinistro e (3,4) inferiore destro)
  557.     e crea sullo heap la corrispondente struttura obstacle_t
  558.     controllando anche che le due coordinate siano consistenti ovvero detta (si,sj) la coordinata in alto a sinistra e (di,dj)
  559.     quella in basso a destra deve essere vero che
  560.     si <= di && sj <= dj
  561.  
  562.     \param s la stringa contenente gli estremi (es. "0 0 3 4")
  563.  
  564.     \retval p il puntatore alla nuova struttura obstacle_t creata (se la conversione ha avuto successo)
  565.     \retval NULL altrimenti
  566. */
  567.  
  568.  
  569.  
  570. obstacle_t * string_to_obstacle (char * s){
  571.     int i = 0;  /* variabile per spostarsi all'interno della stringa */
  572.     obstacle_t *p;  /*creo il puntatore all'ostacolo e l'ostacolo */
  573.  
  574.     p = calloc(1,sizeof(obstacle_t)); /* alloco l'ostacolo in memoria con i valori inizializzati a 0 */
  575.  
  576.         /* ciclo che si ferma quando il valore della stringa è ' ', cioè cambia la coordinata */
  577.     while(s[i] != ' '){
  578.  
  579.         /** assegno a s_i il valore della stringa prima dello spazio facendo sì che s_i contenga il valore del precedente (s_i*10), così          viene spostato nella cifra successiva e sommandogli il valore attuale della stringa convertito da char a int (questo procedimento           viene effettuato su tutte le coordinate) */
  580.         p -> s_i = (p -> s_i)*10 + ((unsigned) s[i] -'0');     
  581.         i++; /* avanza di posizione nella stringa */
  582.     }
  583.  
  584.     i++; /* avanza di posizione nella stringa per superare il primo ' ' */
  585.     while(s[i] != ' '){
  586.         p -> s_j = (p -> s_j)*10 + ((unsigned) s[i] -'0'); /* assegno a s_j il secondo valore della stringa prima dello spazio */
  587.         i++;
  588.     }
  589.  
  590.     i++; /* avanza di posizione nella stringa per superare il secondo ' ' */
  591.     while(s[i] != ' '){
  592.         p -> d_i = (p -> d_i)*10 + ((unsigned) s[i] -'0'); /* assegno a s_i il terzo valore della stringa prima dello spazio */
  593.         i++;
  594.     }
  595.  
  596.     i++; /* avanza di posizione nella stringa per superare il terzo ' ' e il ciclo che segue avanza fino al carattere terminatore della stringa*/
  597.  
  598.     while(s[i] != '\0'){
  599.         p -> d_j = (p -> d_j)*10 + ((unsigned) s[i] -'0'); /* assegno a s_i il qarto valore della stringa prima del carattere terminatore */
  600.         i++;
  601.     }
  602.  
  603.     /* se le coordinate inserite sono insensate ritorna NULL */
  604.     if ( (p->s_i > p->d_i) || (p->s_j > p->d_j) )
  605.         return NULL;
  606.     /* altrimenti ritorna il puntatore all'ostacolo creato */
  607.     return p;
  608. }
  609.  
  610.  
  611.  
  612.  
  613.  
  614. /** crea la rappresentazione di un ostacolo come stringa con i 4 estremi (es. "0 0 3 4" rapresenta i due estremi (0,0) superiore sinistro e (3,4) inferiore destro)
  615.     \param po puntatore all'ostacolo
  616.     \param s puntatore all'array di caratteri dove scrivere la stringa risultato della conversione
  617.     \param n lunghezza dell'array s
  618.  
  619.     \retval s il puntatore al primo carattere della stringa (se la conversione ha avuto successo)
  620.     \retval NULL altrimenti
  621. */
  622.  
  623.  
  624. char * obstacle_to_string (obstacle_t * po, char * s, int n){
  625.  
  626.     /* definizione variabili */
  627.     unsigned i=0,j=0,prec=0,count=0,hold,check, s_i, s_j, d_i, d_j;
  628.  
  629.     if(n <= 8)  /* se l'array non è abbastanza lungo ritorna NULL */
  630.         return NULL;
  631.  
  632.     /** variabili contenenti i valori dell'ostacolo per non modificare i valori delle coordinate effettive durante la funzione */
  633.     s_i = po->s_i;
  634.     s_j = po->s_j;
  635.     d_i = po->d_i;
  636.     d_j = po->d_j;
  637.    
  638.    
  639.     /* i procedimenti nello specifico vengono spiegati solo per il primo valore */
  640.     if(s_i == 0){ /* nel caso s_i sia 0 viene attribuito al primo valore della stringa 0 */
  641.         s[j] = '0';
  642.         j++; /* j tiene conto dell'avanzamento nella scrittura della stringa */
  643.     }
  644.  
  645.    
  646.     while( (s_i/1) >= 1 ){ /* ciclo che conta le cifre di s_i in count, quando s_i = 0 viene interrotto */
  647.         count++;
  648.         /* per ogni cifra si avanza nella stringa di una posizione e successivamente la stringa verrà riempita con i char corrispondenti */
  649.         j++;
  650.        
  651.         /* s_i perde una cifra ad ogni ciclo fino ad arrivare a 0 */
  652.         s_i = (int) (s_i/10);
  653.     }
  654.  
  655.     /* s_i torna al suo valore originale */
  656.     s_i = po->s_i;
  657.  
  658.     /* prec contiene il valore 0 per s_i ma successivamente conterrà la posizione sucessiva all'ultimo ' ' riempito
  659.     il ciclo fa andare i dall'ultima posizione riempita e avanza per il numero di cifre di s_i */
  660.     for(i=prec;i<j;i++){
  661.         count--;
  662.  
  663.         /* hold contiene il valore della cifra corrente di s_i, in quanto divide il valore di s_i per 10^count, dove count è il numero di          cifre rimanenti -1 */
  664.         hold = (int) (s_i/(pow(10,count)));
  665.    
  666.         /* il valore precedentemente calcolato di hold viene convertito in char da int e inserito nella posizione corrente della            stringa */
  667.         s[i] = (char) hold +'0';
  668.  
  669.         /* s_i diventa il resto della divisione tra se stesso e 10^(n° delle sue cifre -1), quindi è come se perdesse la sua prima cifra,             nel caso in cui questa cifr fosse 0 s_i non cambia */
  670.         s_i = (s_i%( (int) ((pow(10,count))) ));
  671.  
  672.     }
  673.  
  674.     /* alla posizione j viene assegnato ' ' */
  675.     s[j] = ' ';
  676.  
  677.     /* j aumenta */
  678.     j++;
  679.    
  680.     if(s_j == 0){
  681.         s[j] = '0';
  682.         j++;
  683.     }
  684.     /* prec indica la posizione successiva all'ultimo ' ' riempito */
  685.     prec = j;
  686.  
  687.     while( (s_j/1) >= 1 ){ /*ciclo che conta le cifre di s_j in count */
  688.         count++;
  689.         j++;       
  690.         s_j = s_j/10;
  691.     }
  692.     s_j = po->s_j;
  693.     for(i=prec;i<j;i++){
  694.         count--;
  695.         hold = (int) (s_j/(pow(10,count)));
  696.  
  697.         s[i] = (char) hold +'0' ;
  698.    
  699.         s_j = (s_j%( (int) ((pow(10,count))) ));
  700.        
  701.     }
  702.     s[j] = ' ';
  703.     j++;
  704.  
  705.  
  706.     if(d_i == 0){
  707.         s[j] = '0';
  708.         j++;
  709.     }
  710.  
  711.     prec = j;
  712.    
  713.     while( (d_i/1) >= 1 ){ /*ciclo che conta le cifre di d_i in count */
  714.         count++;
  715.         j++;       
  716.         d_i = d_i/10;
  717.     }
  718.     d_i = po->d_i;
  719.     for(i=prec;i<j;i++){
  720.         count--;
  721.         hold = (int) (d_i/(pow(10,count)));
  722.        
  723.         s[i] = (char) hold +'0' ;
  724.        
  725.         d_i = (d_i%( (int) ((pow(10,count))) ));
  726.        
  727.     }
  728.     s[j] = ' ';
  729.     j++;
  730.  
  731.  
  732.     if(d_j == 0){
  733.         s[j] = '0';
  734.         j++;
  735.     }
  736.     prec = j;
  737.  
  738.     while( (d_j/1) >= 1 ){ /*ciclo che conta le cifre di d_j in count */
  739.         count++;
  740.         j++;       
  741.         d_j = d_j/10;
  742.     }
  743.     d_j = po->d_j;
  744.     for(i=prec;i<j;i++){
  745.         count--;
  746.         hold = (int) (d_j/(pow(10,count)));
  747.        
  748.         s[i] = (char) hold +'0' ;
  749.        
  750.         d_j = (d_j%( (int) ((pow(10,count))) ));
  751.        
  752.     }
  753.  
  754.     /* la posizione seguente a quella contenente l'ultima cifra di d_j assume quella del carattere terminatore della stringa */
  755.     s[j] = '\0';
  756.    
  757.     /* ritorna il puntatore alla stringa */
  758.     return s;
  759. }
  760.  
  761.  
  762.  
  763. /** inserisce nella matrice di caduta l'ostacolo s marcando gli elementi corrispondenti all'ostacolo con OBSTACLE
  764.   \param s puntatore all'ostacolo da inserire
  765.    \param mat puntatore alla matrice
  766.    \param n numero di righe
  767.    \param m numero di colonne
  768.  
  769.   \retval 0 se tutto è andato bene
  770.   \retval -1 se l'ostacolo è incompatibile con l'area di caduta (es. le coordinate sono maggiori del numero di righe/colonne)
  771. */
  772. int put_obstacle_in_matrix (obstacle_t * s,char ** mat, unsigned n, unsigned m){
  773.  
  774.     int i,j; /*variabili per muoversi all'interno della matrice */
  775.  
  776.     if( ( (*s).s_i > (*s).d_i ) || ( s->s_j > s->d_j ) ) /* controllo che le coordinate abbiano senso */
  777.         return -1;
  778.  
  779.     if( (s->s_i >= n) || (s->d_i >= n) || (s->s_j >= m) || (s->d_j >= m) ) /* le coordinate sono troppo grandi per la matrice */
  780.         return -1;
  781.  
  782.     for(i = (s->s_i); i <= (s->d_i); i++)       /* i parte da s_i e termina in d_i */
  783.         for(j = (s->s_j); j <= (s->d_j); j++)   /* j parte da s_j e finisce in d_j */
  784.             mat[i][j] = OBSTACLE; /* assegna al valore corrispondente della matrice il valore OBSTACLE */
  785.     return 0;
  786.  
  787. }
  788.  
  789. /** inserisce un ostacolo nella lista mantenendo l'ordinamento crescente
  790.   \param p l'ostacolo da inserire (viene inserito direttamente senza effettuare copie)
  791.   \param l il puntatore alla testa della lista
  792.  
  793.   \retval l il puntatore alla nuova testa della lista (dopo l'inserimento)
  794.  
  795. */
  796. lista_t * put_obstacle_in_list (obstacle_t* p,lista_t * l){
  797.  
  798.     lista_t *elem, *succ, *prec; /* creo il puntatore al nuovo elemento della lista e due per scorrere la lista  */
  799.  
  800.     elem = malloc(sizeof(lista_t)); /* creo il nuovo elemento della lista */
  801.  
  802.     bool check = true; /* variabile booleana messa a FALSE quando l'ostacolo trova il suo posto nella lista */
  803.  
  804.     if(l == NULL){ /* lista vuota */
  805.         elem->next = NULL; /* metto il puntatore del primo elemento della lista a NULL */
  806.         l = elem;   /* metto l come puntatore al primo elemento della lista */
  807.         elem -> pobj = p; /* assegno al nuovo elemento l'ostacolo dato in input */
  808.         return l; /* chiudo la funzione */
  809.     }
  810.  
  811.     elem -> pobj = p; /* assegno al nuovo elemento l'ostacolo dato in input */
  812.     succ = l;  /* s punta alla testa della lista */
  813.     prec = succ;
  814.  
  815.     /* l'elemento nuovo va disposto in testa alla lista non vuota */
  816.     if( ((p->s_i) < (succ->pobj->s_i)) || ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) < (succ->pobj->s_j)) ) ||
  817.     ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) < (succ->pobj->d_i)) ) ||
  818.     ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) == (succ->pobj->d_i)) &&
  819.     ((p->d_j) < (succ->pobj->d_j)) ) ){
  820.  
  821.     check = false; /* salta il while */
  822.     l = elem; /* l punta al nuovo elemento */
  823.     elem->next = succ; /* il nuovo elemento punta al successivo */
  824.     }
  825.    
  826.    
  827.     while(check){
  828.  
  829.         if((succ->next) == NULL){ /* fine lista */
  830.  
  831.             /* l'elemento è già presente nella lista ed è l'ultimo */
  832.             if( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) == (succ->pobj->d_i)) &&
  833.             ((p->d_j) == (succ->pobj->d_j)) ){
  834.             return l; /* chiudo la funzione */
  835.             }
  836.  
  837.             /* l'elemento nuovo va disposto prima dell'ultimo */
  838.             if( ((p->s_i) < (succ->pobj->s_i)) || ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) < (succ->pobj->s_j)) ) ||
  839.             ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) < (succ->pobj->d_i)) ) ||
  840.             ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) == (succ->pobj->d_i)) &&
  841.             ((p->d_j) < (succ->pobj->d_j)) ) ){
  842.  
  843.                 prec->next = elem;
  844.                 elem->next = succ;
  845.                 return l;
  846.             }
  847.             else{
  848.             succ->next = elem;  /* l'ultimo elemento della lista punta a quello creato */
  849.             elem->next = NULL; /* pongo il nuovo elemento come ultimo elemento della lista */
  850.             return l;
  851.             }
  852.         }
  853.  
  854.         /* l'elemento è già presente nella lista */
  855.         if( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) == (succ->pobj->d_i)) &&
  856.         ((p->d_j) == (succ->pobj->d_j)) ){
  857.         return l; /* chiudo la funzione */
  858.         }
  859.  
  860.         /* il nuovo elemento va disposto prima di quello attuale */
  861.         if( ((p->s_i) < (succ->pobj->s_i)) || ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) < (succ->pobj->s_j)) ) ||
  862.         ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) < (succ->pobj->d_i)) ) ||
  863.         ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) == (succ->pobj->d_i)) &&
  864.         ((p->d_j) < (succ->pobj->d_j)) ) ){
  865.             check = false;
  866.             prec->next = elem; /* l'elemento precedente punta a quello nuovo */
  867.             elem->next = succ; /* l'elemento nuovo punta a quello successivo */
  868.            
  869.         }
  870.         /* il nuovo elemento non va disposto prima di quello attuale */
  871.         else if( ((p->s_i) > (succ->pobj->s_i)) || ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) > (succ->pobj->s_j)) ) ||
  872.         ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) > (succ->pobj->d_i)) ) ||
  873.         ( ((p->s_i) == (succ->pobj->s_i)) && ((p->s_j) == (succ->pobj->s_j)) && ((p->d_i) == (succ->pobj->d_i)) &&
  874.         ((p->d_j) > (succ->pobj->d_j)) ) ){
  875.        
  876.         /* prec e succ avanzano nella lista facendo sempre si che prec punti sempre all'elemento precedente a succ e succ a quello successivo*/
  877.         prec = succ;
  878.         succ = succ->next;
  879.         }
  880.        
  881.  
  882.        
  883.  
  884.  
  885.  
  886.     }
  887.     return l;
  888. }
  889.  
  890.  
  891. /** libera la memoria occupata dalla lista mettendo a NULL il puntatore alla lista
  892.    \param plist puntatore al puntatore della lista da deallocare
  893. */
  894.  
  895. void free_list (lista_t ** plist){
  896.     lista_t *f;
  897.     f = *plist; /* f punta alla testa della lista */
  898.  
  899.     /* se siamo all'ultimo elemento della lista */ 
  900.     if(f->next == NULL){
  901.         free(f->pobj); /* libera la memoria dell'oggetto a cui punta l'oggetto pobj della lista */
  902.         free(f); /* libera la memoria dell'ultimo elemento della lista */
  903.         *plist = NULL; /* mette il puntatore all'ultimo elemento della lista (ormai deallocato) a NULL */
  904.         return;
  905.     }
  906.  
  907.     /* se l'elemento della lista esaminato non è l'ultimo procede */  
  908.     free_list(&(f->next)); /* richiama la funzione sul prossimo elemento della lista */
  909.     free(f->pobj); /* libera la memoria dell'oggetto a cui punta l'oggetto pobj della lista */
  910.     free(f); /* libera la memoria dell' elemento attuale della lista */
  911.     *plist = NULL; /* mette il puntatore all'elemento attuale della lista a NULL */
  912.     return;
  913. }
  914.  
  915.  
  916. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement