001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<ctype.h>
004: #include<string.h>
005: 
006: 
007: /* INSERITE/MODIFICATE QUI I PROTOTIPI DELLE VOSTRE FUNZIONI */
008: void salva(char **, int);
009: void stampa(char **, int);
010: void step(char **, int);
011: int vicinato(char **, int, int, int);
012: 
013: /* FUNZIONI GIA' DEFINITE, NON MODIFICARE */
014: char menu(void);
015: 
016: int main(int argc, char **argv){
017: 
018:   /* DEFINIRE QUI OPPORTUNA STRUTTURA DATI */
019:   char **grid = NULL;
020:   int grid_size = 0;
021: 
022:   int iter;
023:   char scelta;
024:   while(1)
025:   {
026:     scelta = menu();
027:     switch (scelta)
028:     {
029:       case 'Q':
030:   printf("Bye\n");
031:   exit(EXIT_SUCCESS);
032:       case 'L':
033:   {
034:     char filename[1000];
035:     printf("Nome del file da aprire: ");
036:     scanf(" %s", filename);
037:     FILE *fp=fopen(filename, "r");
038:     if(!fp)
039:     {
040:       perror("APERTURA FILE FALLITA");
041:       break;
042:     }
043:     fscanf(fp, "%d", &grid_size); // leggo dimensione griglia
044: 
045:     // la alloco
046:     if(grid){  // se avevo gia' letto altri file, disalloco precedenti griglie
047:       // prima disalloco righe
048:       for(int r = 0; r < grid_size; ++r) 
049:         free(grid[r]);
050:       // e poi array dei puntatori alle righe
051:       free(grid);  
052:     }
053:     grid = malloc(grid_size * sizeof(char *));
054:     for(int r = 0; r < grid_size; ++r)
055:       grid[r] = malloc(grid_size * sizeof(char));
056: 
057:     // la inizializzo come vuota (ovvero tutti '.')
058:     for(int r = 0; r < grid_size; ++r)
059:       for(int c = 0; c < grid_size; ++c)
060:         grid[r][c] = '.';
061: 
062:     // leggo gli altri parametri e modifico griglia
063:     int r, c;
064:     while(fscanf(fp, "%d%d", &r, &c) == 2)
065:       grid[r][c] = '*';
066:     fclose(fp);
067:   }
068:   break;
069:       case 'P':
070:   stampa(grid, grid_size);
071:   break;
072:       case 'R':
073:   printf("Quante iterazioni? ");
074:   scanf("%d", &iter);
075:   for(int i=0; i<iter; ++i)
076:   {
077:     step(grid, grid_size);
078:     stampa(grid, grid_size);
079:     printf("-----------------------------------\n");
080:   }
081:   break;
082:       case 'S':
083:   salva(grid, grid_size);
084:   break;
085: 
086:     }
087:   }
088: 
089: 
090:   return 0;
091: }
092: 
093: int vicinato(char **g, int n, int r, int c)
094: {
095:   // quante cellule ho negli 8 vicini?
096:   int cellule_vicine = 0;
097:   // guardo gli 8 vicini, in pratica mi devo spostare di +/-1 rispetto le coordinate della cella
098:   for(int offset_r = -1; offset_r <= 1; ++offset_r)
099:     for(int offset_c = -1; offset_c <= 1; ++offset_c)
100:     {
101:       // escludo la cella stessa
102:       if(!offset_r && !offset_c)
103:   continue;
104:       // calcolo coordinate vicino in esame
105:       int c_vicino = c + offset_c;
106:       int r_vicino = r + offset_r;
107: 
108:       // se fuori dai bordi aggiusto
109:       if(c_vicino < 0)
110:   c_vicino = n - 1;
111:       if(r_vicino < 0)
112:   r_vicino = n - 1;
113:       if(c_vicino == n)
114:   c_vicino = 0;
115:       if(r_vicino == n)
116:   r_vicino = 0;
117: 
118:       //dopo eventuali correzioni posso usarle
119:       if(g[r_vicino][c_vicino] == '*')
120:   cellule_vicine++;
121:     }
122:   return cellule_vicine;
123: }
124: 
125: void step(char **g, int n)
126: {
127:   // devo allocare griglia temporanea su cui scrivero' il risultato dell'evoluzione
128:   // qui posso usare VLA
129:   char tmp[n][n];
130: 
131:   // cella per cella calcolo il nuovo valore
132:   for(int r = 0; r < n; ++r)
133:     for(int c = 0; c < n; ++c)
134:     {
135:       int cellule_vicine = vicinato(g, n, r, c);
136: 
137:       // applico regole testo
138:       if(g[r][c] == '*')
139:       {
140:   if(cellule_vicine < 2)
141:     tmp[r][c] ='.';
142:   else if(cellule_vicine == 2 || cellule_vicine == 3)
143:     tmp[r][c] ='*';
144:   else if(cellule_vicine > 3)
145:     tmp[r][c] ='.';
146:       }
147:       else
148:       {
149:   if(cellule_vicine == 3)
150:     tmp[r][c] ='*';
151:   else
152:     tmp[r][c] ='.';
153:       }
154:     }
155:   // aggiorno griglia copiandovi la temporanea
156:   for(int r = 0; r < n; ++r)
157:     for(int c = 0; c < n; ++c)
158:       g[r][c] = tmp[r][c];
159: 
160: }
161: 
162: void stampa(char **g, int n)
163: {
164:   for(int r = 0; r < n; ++r)
165:   {
166:     for(int c = 0; c < n; ++c)
167:       printf("%c", g[r][c]);
168:     printf("\n");
169:   }
170: 
171: }
172: 
173: void salva(char **g, int n)
174: {
175:   char filename[1000];
176:   printf("Nome del file in cui salvare: ");
177:   scanf(" %s", filename);
178:   FILE *fp=fopen(filename, "w");
179:   if(!fp)
180:   {
181:     perror("APERTURA FILE PER SALVARE FALLITA");
182:     return;
183:   }
184:   // scrive nel file la dimensione
185:   fprintf(fp, "%d\n", n);
186: 
187:   // e le coordinate di tutte le cellule vive
188:   for(int r = 0; r < n; ++r)
189:     for(int c = 0; c < n; ++c)
190:       if(g[r][c] == '*')
191:   fprintf(fp, "%d %d\n", r, c);
192: 
193:   fclose(fp);
194: }
195: 
196: /***************************************************
197:   LE SEGUENTI FUNZIONI NON VANNO MODIFICATE
198: ***************************************************/
199: 
200: // stampa menu' e chiede scelta a utente
201: char menu(void)
202: {
203:   char c;
204: 
205:   printf("MENU': L - load, S - save, R - evolve, P - print, Q - exit: ");
206:   scanf(" %c", &c);
207:   while(getchar() != '\n'); // clean input buffer
208: 
209:   c = toupper(c);
210:   return c;
211: }
212: 
213: 
214: