001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<time.h>
004:
005: // un po' di costanti che usero' per memorizzare la situazione griglia
006: #define VUOTO 0
007: #define NAVE 1
008: #define COLPITO -1
009: #define COLPOAVUOTO 3
010:
011: void place_ship(int n, int grid[n][n], int l);
012: void print_grid(int n, int grid[n][n]);
013: int shoot(int n, int grid[n][n], int c, int r);
014:
015: int main(int argc, char **argv){
016:
017: // genero casualmente la dimensione della griglia nell'intervallo [9,13]
018: srand(time(0));
019: const int n = rand()%5 + 9;
020:
021: // definiamo la griglia allocando dinamicamente un array bidimensionale n x n in cui, inizialmente, pongo tutte le celle a 0 (vuoto)
022: int grid[n][n];
023: for(int c = 0; c < n; ++c)
024: for(int r = 0; r < n; ++r)
025: grid[r][c] = VUOTO;
026:
027: // invoco la funzione place_ship() per inserire le navi come da testo
028: place_ship(n, grid, 4);
029: place_ship(n, grid, 3);
030: place_ship(n, grid, 3);
031: place_ship(n, grid, 2);
032: place_ship(n, grid, 2);
033: place_ship(n, grid, 2);
034: place_ship(n, grid, 1);
035: place_ship(n, grid, 1);
036: place_ship(n, grid, 1);
037: place_ship(n, grid, 1);
038: int n_ship_cells = 4 + 3 + 3 + 2 + 2 + 2 + 1 + 1 + 1 + 1; // tengo traccia di quante celle sono occupate da navi
039:
040: // stampa di debug
041: print_grid(n, grid);
042:
043: // entro in ciclo che terminero' solo quanto avro' colpito tutte le navi in tutte le celle
044: while(n_ship_cells)
045: {
046: printf("Inserire le coordinate per il tentativo (griglia %dx%d): ", n, n);
047: int r, c;
048: scanf("%d%d", &r, &c); // per semplicita' uso coordinate solo numeriche
049: int colpito = shoot(n, grid, c - 1, r - 1); // tradizionalmente le coordinate partono da 1, correggo nel caso degli array
050: if(colpito)
051: {
052: printf("Colpito!\n");
053: --n_ship_cells;
054: }
055: else
056: {
057: printf("Niente...\n");
058: }
059: print_grid(n, grid);
060: }
061:
062: return 0;
063: }
064:
065: void place_ship(int n, int grid[n][n], int l)
066: {
067: // in questa funzione devo piazzare una nava di lunghezza l in una posizione casuale
068: // anche il fatto che sia in orizzontale e verticale va deciso casualmente
069: // pero' devo anche considerare che ci stia e non si sovrapponga ad altre navi gia' precedentemente inserite
070: // quindi genero casualmente coordinate e direzione e ripeto fino a che le condizioni non sono soddisfatte
071: // una volta stabilito che ci sta imposto ad '1' tutte le celle della griglia che la contengono
072:
073: // entro in un ciclo da cui esco se e solo se le coordinate generate e la direzione generata sono tali da poter piazzare
074: // la nave senza che esca dai bordi o si sovrapponga ad altre navi
075: int c, r, dir; // variabili che uso per memorizzare coordinate e direzione scelte casualmente
076: while(1)
077: {
078: // genero coordinate e direzioni casuali per piazzare nave
079: c = rand()%n; // colonna
080: r = rand()%n; // riga
081: dir = rand()%2; // 0 -> orizzontale, 1 -> verticale
082:
083: // controllo che non esca
084: if(!dir & c+l >= n) // controllo che non esca in orizzontale
085: continue; // ripeto
086:
087: if(dir & r+l >= n) // controllo che non esca in verticale
088: continue; // ripeto
089:
090: // guardo tutte le celle dove dovrei piazzarla se per caso sono gia' occupate
091: int conflitto = 0; // variabile che uso per capire se "incontro" altre navi
092:
093: if(!dir)
094: {
095: for(int i = c; i < (c + l); ++i)
096: if(grid[r][i] == NAVE)
097: conflitto = 1;
098: }
099: else
100: {
101: for(int i = r; i < (r + l); ++i)
102: if(grid[i][c] == NAVE)
103: conflitto = 1;
104: }
105:
106: if(conflitto) // diventa 1 se e solo se nella posizione generata casualmente si sovrapporrebbe ad altre navi
107: continue; // ripeto
108:
109: // se arrivo qui la nave ci starebbe e di conseguenza esco dal ciclo
110: break;
111: }
112:
113: // piazzo la nave
114:
115: if(!dir)
116: for(int i = c; i < (c + l); ++i)
117: grid[r][i] = NAVE;
118: else
119: for(int i = r; i < (r + l); ++i)
120: grid[i][c] = NAVE;
121: }
122:
123:
124: // funzione di stampa (molto minimale)
125: void print_grid(int n, int grid[n][n])
126: {
127: printf("%dx%d grid:\n", n, n);
128:
129: // stampo coordinate colonne
130: printf(" ");
131: for(int r = 0; r < n; ++r)
132: {
133: printf("%c", 'A' + r);
134: }
135: printf("\n");
136:
137: for(int r = 0; r < n; ++r)
138: {
139: printf(" %2d", r+1); // coordinate righe
140: for(int c = 0; c < n; ++c)
141: {
142: switch(grid[r][c])
143: {
144: case NAVE: // nave
145: printf("#");
146: break;
147: case COLPITO: // nave colpita
148: printf("*");
149: break;
150: case VUOTO: // cella vuota
151: printf(" ");
152: break;
153: case COLPOAVUOTO: // colpo a vuoto
154: printf(".");
155: break;
156: }
157: }
158: printf("\n");
159: }
160: }
161:
162: int shoot(int n, int grid[n][n], int c, int r)
163: {
164: if(grid[r][c] == NAVE) // c'e' una nave in quelle coordinate?
165: {
166: grid[r][c] = COLPITO; // segno il colpo e restituisco 1
167: return 1;
168: }
169:
170: // altrimenti era una cella vuota (o comunque dove avevo gia' sparato)
171: grid[r][c] = COLPOAVUOTO;
172: return 0;
173: }
174: