#include "baralho.h" #include "mesa.h" /* Inicia a estrutura de dados para conter as imagens individualizadas de cartas. Os parâmetros indicam o nome do arquivo com a imagem original em PPM, as dimensões de cada carta na imagem original, o valor da carta mais à esquerda, e a ordem dos naipes na imagem (de cima para baixo.) */ Baralho init (char *imgFile, int cw, int ch, char primCarta, char *ordNaipes) { // largura altura /* Baralho é do tipo Carta**, o baralho é uma matriz de cartas. É a imagem original com "recortes" nas cartas. */ Baralho bar; int i, j, aux; /* Inicializa a variavel global ENTRADA com a imagem das cartas. */ ENTRADA = fopen(imgFile, "rb"); /* Inicializa cabeçalho das cartas. */ cabeca.magic[0] = 'P'; cabeca.magic[1] = '6'; cabeca.magic[2] = '\n'; cabeca.magic[3] = '\0'; cabeca.w = cw; cabeca.h = ch; cabeca.maxval = 255; /* Ordena os vetores de valores e de naipes de modo que o primeiro elemento dos vetor de valores seja o valor que foi passado como parâmetro (primCarta) e o vetor de naipes seja igual ao vetor de naipes passado como parâmetro (*ordNaipes). */ while (vals[0] != primCarta) { aux = vals[0]; for (i = 0; i < 12; i++) vals[i] = vals[i+1]; vals[i] = aux; } for (i = 0; i < NAIPES; i++) naipes[i] = ordNaipes[i]; /* Aloca um vetor de quatro posições, uma para cada naipe. */ bar = (Baralho)malloc(sizeof(Carta*)*NAIPES); /* Aloca 13 cartas para cada naipe. */ for (i = 0; i < NAIPES; i++) bar[i] = (Carta*)malloc(sizeof(Carta)*CARTAS); /* Aloca o espaço para a imagem de cada carta. */ for (i = 0; i < NAIPES; i++) { for (j = 0; j < CARTAS; j++) { bar[i][j].img = (Pixel*)malloc(sizeof(Pixel)*cw*ch); /* Atribui o valor e o naipe de cada carta. */ bar[i][j].valor = vals[j]; bar[i][j].naipe = naipes[i]; } } return bar; } /* Lê a imagem do arquivo principal e preenche a estrutura de dados gerada por \textsf{init()}. */ /* Baralho de 52 cartas: cartas com 72 x 96 pixels. Intervalo entre cartas: 1 pixel. Intervalo entre naipes: 2 pixels. */ Baralho geraBaralho (Baralho cartas) { Pixel *p; char s[4]; int col, lin, maxval; int i, j, k, l, pos; pos = 0; /* É alocado o espaço do pixel a ser lido e são obtidas as informações da imagem original ("valor mágico", numero de colunas, numero de linhas e maxval). */ p = (Pixel*)malloc(sizeof(Pixel)); fgets(s, 4, ENTRADA); fscanf(ENTRADA, "%d %d", &col, &lin); fscanf(ENTRADA, "%d", &maxval); fgetc(ENTRADA); /* Dois lassos para pegar as cartas. Um lasso interno para a variação dos valores (horizontal) e um lasso externo para a variação dos naipes (vertical). */ for (i = 0; i < NAIPES; i++) { for (j = 0; j < CARTAS; j++) { /* Dois lassos para pegar os pixels da carta. Um lasso interno para a variação horizontal e um lasso externo para a variação vertical. */ for (k = 0; k < cabeca.h; k++) { for (l = 0; l < cabeca.w; l++, pos++) { fread(p, sizeof(Pixel), 1, ENTRADA); cartas[i][j].img[pos] = *p; } fseek(ENTRADA, (col - cabeca.w) * (sizeof(Pixel)), SEEK_CUR); } fseek(ENTRADA, sizeof(Pixel) + (cabeca.w * sizeof(Pixel)) - (col * (sizeof(Pixel)) * cabeca.h), SEEK_CUR); fseek(ENTRADA, sizeof(Pixel), SEEK_CUR); pos = 0; } fseek(ENTRADA, col * sizeof(Pixel), SEEK_CUR); fseek(ENTRADA, col * cabeca.h * sizeof(Pixel), SEEK_CUR); fseek(ENTRADA, -sizeof(Pixel), SEEK_CUR); } return cartas; } /* Gera a imagem PPM de uma carta individual, pronta para uso. */ Carta getCarta (char naipe, char valor, Baralho cartas) { int i, j; if ((naipe != 'P' && naipe != 'E' && naipe != 'C' && naipe != 'O') || (valor != 'A' && valor != '2' && valor != '3' && valor != '4' && valor != '5' && valor != '6' && valor != '7' && valor != '8' && valor != '9' && valor != 'D' && valor != 'J' && valor != 'Q' && valor != 'K')) { fprintf(stderr, "erro. carta inexistente.\n"); return; } /* Dois contadores para encontrar a posição do naipe e do valor desejados. */ for (i = 0; naipes[i] != naipe; i++); for (j = 0; vals[j] != valor; j++); return cartas[i][j]; } /* Gera arquivo com imagem de uma carta individual em formato PPM. Nome do arquivo tem formato ``valor-naipe.ppm'' (e.g., ``A-C.ppm'', ``2-P.ppm'', etc.). */ void geraCarta (char naipe, char valor, Baralho cartas) { int i, j; char nome[8]; FILE *SAIDA; Carta card; if ((naipe != 'P' && naipe != 'E' && naipe != 'C' && naipe != 'O') || (valor != 'A' && valor != '2' && valor != '3' && valor != '4' && valor != '5' && valor != '6' && valor != '7' && valor != '8' && valor != '9' && valor != 'D' && valor != 'J' && valor != 'Q' && valor != 'K')) { fprintf(stderr, "erro. carta inexistente.\n"); return; } /* Atribui à string "nome" o nome do arquivo de saida desejado. */ nome[0] = valor; nome[1] = '-'; nome[2] = naipe; nome[3] = '.'; nome[4] = 'p'; nome[5] = 'p'; nome[6] = 'm'; nome[7] = '\0'; SAIDA = fopen(nome, "wb+"); card = getCarta(naipe, valor, cartas); /* Imprime no arquivo os dados contidos no cabeçalho. */ fprintf(SAIDA, "%c%c%c\n", cabeca.magic[0], cabeca.magic[1], cabeca.magic[2]); fprintf(SAIDA, "%d %d\n", cabeca.w, cabeca.h); fprintf(SAIDA, "%d\n", cabeca.maxval); /* Imprime no arquivo todos os pixels contidos na carta desejada. */ fwrite(card.img, sizeof(Pixel), cabeca.w * cabeca.h, SAIDA); fclose(SAIDA); } /* Cria um monte vazio (sem cartas), que pode ser preenchido usando colocaCarta() e esvaziado com tiraCarta(). */ Monte criaMonte (int n) { Monte deck; int i; /* Aloca memória para o monte. O número de espaços de memória alocados será o número de baralhos (n) vezes o numero de valores (CARTAS) vezes o número de naipes (NAIPES) mais 1. Esse último espaço de memória alocado servirá como uma barreira para não acessar memória inválida. Como CARTAS e NAIPES são constantes: caso n = 0: memória alocada = 1 caso n = 1: memória alocada = 53 caso n = 2: memória alocada = 105 (...) E para cada um desses espaços são alocados mais 3 espaços de memória (valor, naipe e '\0') */ deck = (Monte)malloc(sizeof(char*) * (n * CARTAS * NAIPES + 1)); for (i = 0; i < n * CARTAS * NAIPES + 1; i++) { deck[i] = (char*)malloc(sizeof(char) * 3); /* Inicializa a memória alocada com o char '0'. */ deck[i][0] = '0'; deck[i][1] = '0'; deck[i][2] = '\0'; } return deck; } /* Retorna a primeira carta de um monte, que é retirada do topo deste. */ Carta tiraCarta (Monte deck, Baralho bar) { int i, j; char valor, naipe; i = 0; valor = deck[0][0]; naipe = deck[0][1]; while (deck[i][0] != '0' && deck[i][1] != '0') { deck[i][0] = deck[i+1][0]; deck[i][1] = deck[i+1][1]; i++; } if (valor == '0' && naipe == '0') { fprintf(stderr, "erro. o monte esta vazio.\n"); return; } /* Encontra dentro do baralho a carta que possui o valor e o naipe que foram retirados do monte. Essa rotina é necessária pois a imagem da carta está armazenada no Baralho, e não no Monte. */ i = 0; j = 0; while (bar[i][j].naipe != naipe) i++; while (bar[i][j].valor != valor) j++; return bar[i][j]; } /* Coloca uma carta no topo de um monte. Retorna o Monte com a nova carta no topo. */ Monte colocaCarta (int n, Carta c, Monte deck) { unsigned int i = 0; unsigned int cont = 0; /* A mensagem de erro é mostrada caso seja tentado empilhar uma carta inexistente */ if ((c.naipe != 'P' && c.naipe != 'E' && c.naipe != 'C' && c.naipe != 'O') || (c.valor != 'A' && c.valor != '2' && c.valor != '3' && c.valor != '4' && c.valor != '5' && c.valor != '6' && c.valor != '7' && c.valor != '8' && c.valor != '9' && c.valor != 'D' && c.valor != 'J' && c.valor != 'Q' && c.valor != 'K')) { fprintf(stderr, "erro. carta inexistente.\n"); return; } while (deck[i][0] != '0' && deck[i][1] != '0') i++; if (i == 0) { deck[0][0] = c.valor; deck[0][1] = c.naipe; return deck; } /* A mensagem de erro é mostrada caso seja tentado empilhar uma carta em uma pilha cheia. */ if (i >= (n * NAIPES * CARTAS) - 1) { fprintf(stderr, "erro. monte lotado, impossivel de empilhar.\n"); return; } for(; i > 0; i--) { deck[i][0] = deck[i-1][0]; deck[i][1] = deck[i-1][1]; } deck[0][0] = c.valor; deck[0][1] = c.naipe; return deck; } /* Rotina para trocar a carta em deck[i] com a carta em deck[ir]. i é a posição atual e ir é a posição que foi randomizada. */ void troca (Monte deck, int i, int ir) { Monte aux; aux = (Monte)malloc(sizeof(char*)); aux[0] = (char*)malloc(sizeof(char) * 3); aux[0][0] = deck[i][0]; aux[0][1] = deck[i][1]; aux[0][2] = deck[i][2]; deck[i][0] = deck[ir][0]; deck[i][1] = deck[ir][1]; deck[i][2] = deck[ir][2]; deck[ir][0] = aux[0][0]; deck[ir][1] = aux[0][1]; deck[ir][2] = aux[0][2]; } /* Gera um monte contendo todas as n*52 cartas embaralhadas em ordem aleatória */ Monte embaralha (Monte deck) { int i, ir; int numCartas; i = 0; while (deck[i][0] != '0' && deck[i][1] != '0') i++; i--; numCartas = i; /* As cartas do monte são embaralhadas. */ srand(time(0)); for (i = 0; i < numCartas; i++) { ir = rand() % (numCartas); troca(deck, i, ir); } return deck; }