1
0
Files
2024-03-22 17:37:24 +01:00

246 lines
6.7 KiB
C

// Laboratorio 5 - Esercizio 2
// Matteo Schiff - s295565
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
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;
}