diff --git a/src/baralho.c b/src/baralho.c new file mode 100644 index 0000000000000000000000000000000000000000..c447040458bda14d6f3cd515034550dfdd029904 --- /dev/null +++ b/src/baralho.c @@ -0,0 +1,307 @@ +#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; +} \ No newline at end of file