// Laboratorio 5 - Esercizio 2 // Matteo Schiff - s295565 #include #include #include typedef struct tile_s { char c_o, c_v; // colore orizzontale e verticale int p_o, p_v; // punti orizzontali e verticali } tile; typedef struct cell_s { int id, rot; // id tile e rotazione } cell; void readTiles(tile **tiles, int *N, char *filename) { FILE *fp; if ((fp = fopen(filename, "r")) == NULL) { printf("Errore nell'apertura del file %s",filename); exit(1); } fscanf(fp, "%d", N); *tiles = (tile *) malloc(*N * sizeof(tile)); for (int i = 0; i < *N; i++) { fscanf(fp, " %c %d %c %d", &((*tiles)[i].c_o), &((*tiles)[i].p_o), &((*tiles)[i].c_v), &((*tiles)[i].p_v)); } fclose(fp); } void readBoard(cell ***board, int *R, int *C, char *filename) { FILE *fp; if ((fp = fopen(filename, "r")) == NULL) { printf("Errore nell'apertura del file %s",filename); exit(1); } fscanf(fp, "%d %d", R, C); *board = (cell **) malloc(*R * sizeof(cell *)); for (int i = 0; i < *R; i++) { (*board)[i] = (cell *) malloc(*C * sizeof(cell)); for (int j = 0; j < *C; j++) { fscanf(fp, " %d/%d", &(*board)[i][j].id, &(*board)[i][j].rot); } } fclose(fp); } // funzione helper per ottenere il colore di un tile conoscendone la posizione // se `vert` è true restituisce il colore sulla verticale char getTileColor(tile *tiles, cell **board, int x, int y, bool vert) { cell c = board[x][y]; if (c.rot ^ vert) return tiles[c.id].c_v; return tiles[c.id].c_o; } // funzione helper per ottenere il punteggio di un tile conoscendone la posizione // se `vert` è true restituisce il punteggio sulla verticale char getTilePoints(tile *tiles, cell **board, int x, int y, bool vert) { cell c = board[x][y]; if (c.rot ^ vert) return tiles[c.id].p_v; return tiles[c.id].p_o; } int calcolaPunteggio(int R, int C, tile *tiles, cell **board) { int points = 0; for (int i = 0; i < R; i++) { char color = getTileColor(tiles, board, i, 0, false); int temp_points = getTilePoints(tiles, board, i, 0, false); bool ok = true; for (int j = 1; ok && j < C; j++) { if (color != getTileColor(tiles, board, i, j, false)) ok = false; temp_points += getTilePoints(tiles, board, i, j, false); } // Aggiungo i punti solo se la riga è dello stesso colore if (ok) { points += temp_points; } } for (int i = 0; i < C; i++) { char color = getTileColor(tiles, board, 0, i, true); int temp_points = getTilePoints(tiles, board, 0, i, true); bool ok = true; for (int j = 1; ok && j < R; j++) { if (color != getTileColor(tiles, board, j, i, true)) ok = false; temp_points += getTilePoints(tiles, board, j, i, true); } // Aggiungo i punti solo se la colonna è dello stesso colore if (ok) { points += temp_points; } } return points; } void cercaMassimoR(int R, int C, int N, tile *tiles, bool * taken, cell **board, int depth, int * max, cell **sol) { // Terminazione if (depth == R*C) { int punteggio = calcolaPunteggio(R, C, tiles, board); if (punteggio > *max) { *max = punteggio; // Copio soluzione for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { sol[i][j] = board[i][j]; } } } return; } int r = depth / C; int c = depth % C; // Provo ad aggiungere un tile solo se nella casella non è già presente un altro tile if (board[r][c].id == -1 && board[r][c].rot == -1) { for (int i = 0; i < N; i++) { if (!taken[i]) { taken[i] = true; board[r][c].id = i; // Aggiungo in un verso board[r][c].rot = 0; cercaMassimoR(R, C, N, tiles, taken, board, depth + 1, max, sol); // Aggiungo nell'altro verso board[r][c].rot = 1; cercaMassimoR(R, C, N, tiles, taken, board, depth + 1, max, sol); taken[i] = false; } } // Pulisco la casella, in modo che nella esplorazione successiva // la funzione inserisca un altra tessera board[r][c].id = -1; board[r][c].rot = -1; } else { cercaMassimoR(R, C, N, tiles, taken, board, depth + 1, max, sol); } } cell ** cercaMassimo(int R, int C, int N, tile *tiles, cell **board) { int max = 0; bool *taken = (bool *) malloc(N * sizeof(bool)); // Rimuovo dalla lista delle tessere disponibili quelle che sono già presenti sulla board for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { if (board[i][j].id != -1) taken[board[i][j].id] = true; } } cell **solution = (cell **) malloc(R * sizeof(cell *)); for (int i = 0; i < R; i++) { solution[i] = (cell *) malloc(C * sizeof(cell)); } cercaMassimoR(R,C,N,tiles,taken,board,0,&max,solution); free(taken); return solution; } void freeSolution(cell **solution, int R) { for (int i = 0; i < R; i++) { free(solution[i]); } free(solution); } // Disegna la board void printBoard(int R, int C, cell **board, tile * tiles) { for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { tile t = tiles[board[i][j].id]; if (board[i][j].rot) { printf(" %c ", t.c_o); } else { printf(" %c ", t.c_v); } } putchar('\n'); for (int j = 0; j < C; j++) { tile t = tiles[board[i][j].id]; if (board[i][j].rot) { printf("%c %d ", t.c_v, t.p_v); } else { printf("%c %d ", t.c_o, t.p_o); } } putchar('\n'); for (int j = 0; j < C; j++) { tile t = tiles[board[i][j].id]; if (board[i][j].rot) { printf(" %d ", t.p_o); } else { printf(" %d ", t.p_v); } } putchar('\n'); putchar('\n'); } } int main(int argc, char const *argv[]) { tile *tiles; cell **board; int N, R, C; readTiles(&tiles, &N, "tiles.txt"); readBoard(&board, &R, &C, "board.txt"); cell **solution = cercaMassimo(R,C,N,tiles,board); printBoard(R, C, solution, tiles); freeSolution(solution, R); free(tiles); free(board); return 0; }