246 lines
6.7 KiB
C
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;
|
|
}
|