001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<ctype.h>
004: #include<string.h>
005: 
006: 
007: /* INSERITE QUI LA DEFINIZIONE DELLE EVENTUALI struct NECESSARIE */
008: 
009: struct turtle
010: {
011:   int riga, colonna;
012:   int direzione;
013:   int penna;
014: };
015: 
016: 
017: /* INSERITE/MODIFICATE QUI I PROTOTIPI DELLE VOSTRE FUNZIONI */
018: void avanza(struct turtle *, char **, int, int);
019: void stampa(struct turtle *, char **, int, int);
020: void stampa_tartaruga(const struct turtle *);
021: void ruota(struct turtle *);
022: void toggle(struct turtle *, char **, int, int);
023: char comando(FILE *);
024: 
025: /* FUNZIONI GIA' DEFINITE, NON MODIFICARE */
026: char menu(void);
027: 
028: int main(int argc, char **argv){
029: 
030:   /* DEFINIRE QUI OPPORTUNA STRUTTURA DATI */
031: 
032:   /* griglia ovvero array bidimensionale di char e relative dimensioni */
033:   char **griglia = NULL;
034:   int righe = 0, colonne = 0;
035: 
036:   /* tartaruga */
037:   struct turtle tartaruga;
038: 
039:   FILE *fp=NULL;
040:   int iter;
041:   char scelta;
042:   while(1)
043:   {
044:     scelta = menu();
045:     switch (scelta)
046:     {
047:       case 'Q':
048:   if(fp) fclose(fp);
049:   printf("Bye\n");
050:   exit(EXIT_SUCCESS);
051:       case 'L':
052:   {
053:     char filename[1000];
054:     printf("Nome del file da aprire: ");
055:     scanf(" %s", filename);
056:     if(fp) // se avevo gia' letto altri file devo chiudere...
057:       fclose(fp);
058:     fp=fopen(filename, "r");
059:     if(!fp)
060:     {
061:       perror("APERTURA FILE FALLITA");
062:       break;
063:     }
064: 
065:     // la alloco
066:     if(griglia) // se avevo gia' letto altri file, disalloco precedenti griglie
067:     {
068:       // disalloco righe
069:       for(int r = 0; r < righe; ++r)
070:         free(griglia[r]);
071: 
072:       // disalloco puntatori righe
073:       free(griglia);   
074:     }
075: 
076: 
077:     // ok, posso iniziare a leggere i dati
078:     fscanf(fp, "%d %d", &righe, &colonne); // leggo dimensioni griglia
079: 
080:     // alloco puntatori righe
081:     griglia = malloc(righe * sizeof(char *));
082:     // alloco righe
083:     for(int r = 0; r < righe; ++r)
084:       griglia[r] = malloc(colonne * sizeof(char));
085: 
086:     // la inizializzo come vuota (ovvero tutti '.')
087:     for(int r = 0; r < righe; ++r)
088:       for(int c = 0; c < colonne; ++c)
089:         griglia[r][c] = '.';
090: 
091:     // leggo parametri tartaruga
092:     fscanf(fp, "%d %d %d %d", &tartaruga.riga, &tartaruga.colonna, &tartaruga.direzione, &tartaruga.penna);
093:     // nel caso penna giu' inizio a segnare
094:     if(tartaruga.penna)
095:       griglia[tartaruga.riga][tartaruga.colonna] = 'X';
096: 
097:     // elimino "a capo" dopo parametri tartaruga
098:     getc(fp);
099: 
100:   }
101:   break;
102:       case 'R':
103:   int iter;
104:   printf("Quante iterazioni? ");
105:   scanf("%d", &iter);
106:   for(int i=0; i<iter; ++i)
107:   {
108:     char command = comando(fp);
109:     if(command == '\0')
110:     {
111:       printf("Non ci sono piu' comandi\n");
112:       break;
113:     }
114:     printf("Ho letto %c\n", command);
115:     if(command == 'A')
116:       avanza(&tartaruga, griglia, righe, colonne);
117:     else if(command == 'D')
118:       ruota(&tartaruga);
119:     else if(command == 'T')
120:       toggle(&tartaruga, griglia, righe, colonne);
121:     stampa(&tartaruga, griglia, righe, colonne);
122:   }
123:   break;
124:       case 'T':
125:   stampa_tartaruga(&tartaruga);
126:   break;
127:       case 'P':
128:   stampa(&tartaruga, griglia, righe, colonne);
129:   break;
130: 
131:     }
132:   }
133: 
134: 
135:   return 0;
136: }
137: 
138: char comando(FILE *fp)
139: {
140:   if(!fp) return '\0'; // va controllato anche se il file fosse stato precedentemente aperto
141:   int c = fgetc(fp);
142:   if(c != EOF && (c == 'T' || c == 'D' || c == 'A')) return c; // restituisco valore se e solo se non sono arrivato a fine file e comando letto e' uno di quelli previsti
143:   else return '\0';
144: }
145: 
146: void stampa_tartaruga(const struct turtle *t)
147: {
148:   printf("La tartaruga si trova nella posizione (%d,%d), orientata di %d gradi e la penna e' %s\n",
149:       t->riga, t->colonna, t->direzione, (t->penna?"giu'":"su"));
150: }
151: 
152: void toggle(struct turtle *t, char **g, int righe, int colonne)
153: {
154:   t->penna = (t->penna?0:1);
155:   if(t->penna)
156:     g[t->riga][t->colonna] = 'X';
157: }
158: 
159: void ruota(struct turtle *t)
160: {
161:   t->direzione = (t->direzione + 270)%360;
162: }
163: 
164: void avanza(struct turtle *t, char **g, int righe, int colonne)
165: {
166:   // variabili temporanee per calcolo nuova posizione
167:   int riga_tartaruga    = t->riga;
168:   int colonna_tartaruga = t->colonna;
169: 
170:   switch(t->direzione) // la scelta di memorizzare l'angolo e' apparentemente la piu' semplice ma non si presta benissimo in fase di utilizzo, sarebbe stato piu' pratico memorizzare il vettore direzione
171:   {
172:     case 0:
173:       ++colonna_tartaruga;
174:       break;
175:     case 90:
176:       --riga_tartaruga;
177:       break;
178:     case 180:
179:       --colonna_tartaruga;
180:       break;
181:     case 270:
182:       ++riga_tartaruga;
183:       break;
184:     default:
185:       printf("Errore in avanza(): direzione %d non prevista\n", t->direzione);
186:       exit(EXIT_FAILURE);
187:   }
188: 
189:   // controllo se sono rimasto entro la griglia
190:   if(colonna_tartaruga < 0 || colonna_tartaruga >= colonne || riga_tartaruga < 0 || riga_tartaruga >= righe)
191:     return; // se sono al di fuori dei confini della griglia esco senza aggiornare niente
192: 
193:   // aggiorno posizione tartaruga e, nel caso, scrivo sulla griglia
194:   t->riga    = riga_tartaruga;
195:   t->colonna = colonna_tartaruga;
196:   if(t->penna)
197:     g[t->riga][t->colonna] = 'X';
198: }
199: 
200: void stampa(struct turtle *t, char **g, int righe, int colonne)
201: {
202:   for(int r = 0; r < righe; ++r)
203:   {
204:     for(int c = 0; c < colonne; ++c)
205:       if(c != t->colonna || r != t->riga)
206:   printf("%c", g[r][c]);
207:       else
208:   printf(t->penna?"o":"O");
209:     printf("\n");
210:   }
211: }
212: 
213: /***************************************************
214:   LE SEGUENTI FUNZIONI NON VANNO MODIFICATE
215: ***************************************************/
216: 
217: // stampa menu' e chiede scelta a utente
218: char menu(void)
219: {
220:   char c;
221: 
222:   printf("MENU': L - load, R - run, P - print grid, T - print turtle status, Q - exit: ");
223:   scanf(" %c", &c);
224:   while(getchar() != '\n'); // clean input buffer
225: 
226:   c = toupper(c);
227:   return c;
228: }
229: 
230: 
231: