Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Projeto Intermédio de Programação: JOGO DE BLACKJACK
- * Autor: Rúben Dos Santos Gomes
- * Nº de aluno: 84180 / ist425480
- * Data de realização: 18 de Março de 2016
- * Descrição do jogo: 4 jogadores que jogam contra a casa, que vão ganhando ou perdendo dinheiro consoante as jogadas que efetuarem
- */
- #include <SDL2/SDL.h>
- #include <SDL2/SDL_ttf.h>
- #include <SDL2/SDL_image.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <stdbool.h>
- #define STRING_SIZE 100 // max size for some strings
- #define WIDTH_WINDOW 900 // window width
- #define HEIGHT_WINDOW 525 // window height
- #define MAX_DECK_SIZE 52 // number of max cards in the deck
- #define MAX_CARD_HAND 11 // 11 cards max. that each player can hold
- #define CARD_WIDTH 67 // card width
- #define CARD_HEIGHT 97 // card height
- #define WINDOW_POSX 500 // initial position of the window: x
- #define WINDOW_POSY 250 // initial position of the window: y
- #define EXTRASPACE 150
- #define MARGIN 5
- #define MAX_PLAYERS 4 // number of maximum players
- #define MAX_POINTS 21 // máximo de pontos que um jogador pode ter, para ganhar
- #define MIN_HOUSE_POINTS 17 // mínimo de pontos que a casa deve ter
- // declaration of the functions related to graphical issues
- void InitEverything(int , int , TTF_Font **, SDL_Surface **, SDL_Window ** , SDL_Renderer ** );
- void InitSDL();
- void InitFont();
- SDL_Window* CreateWindow(int , int );
- SDL_Renderer* CreateRenderer(int , int , SDL_Window *);
- int RenderText(int , int , const char* , TTF_Font *, SDL_Color *, SDL_Renderer * );
- int RenderLogo(int , int , SDL_Surface *, SDL_Renderer * );
- void RenderTable(int newgame, int pontoscasa, int [], int pontos [], int player, TTF_Font *, SDL_Surface **, SDL_Renderer * );
- void RenderCard(int , int , int , SDL_Surface **, SDL_Renderer * );
- void RenderHouseCards(int [], int , SDL_Surface **, SDL_Renderer * );
- void RenderPlayerCards(int [][MAX_CARD_HAND], int [], SDL_Surface **, SDL_Renderer * );
- void LoadCards(SDL_Surface **);
- void UnLoadCards(SDL_Surface **);
- // definition of some strings: they cannot be changed when the program is executed !
- const char myName[] = "Ruben Gomes";
- const char myNumber[] = "IST425480";
- const char * playerNames[] = {"Player 1", "Player 2", "Player 3", "Player 4"};
- //PROTÓTIPO DAS FUNÇÕES CRIADAS POR MIM
- void LerParametrosJogo ( int *num_baralhos, int *valor_inicial, int *dinheiro_apostado );
- void InicializarBaralho (int num_baralhos, int VetorCartas []);
- void BaralharCartas(int vetorcartas[], int num_baralhos);
- int CalcPontos (int playercards[][MAX_CARD_HAND], int player, int posicao_player_hand []);
- int CalcPontosCasa (int pos_house_hand, int house_cards[]);
- void NewGame(int money [], int i, int vetorcartas[], int pos_player_hand[], int *pos_house_hand, int player_cards[][MAX_CARD_HAND], int house_cards [], int valorinicial, int valoraposta);
- void VerificarPontos (int pontos [], int money [], int valoraposta, int pontoscasa, int pos_player_hand [], int pos_house_hand);
- void CalculaGanhosEmpatesPerdidos(int pos_house_hand, int money [], int valoraposta, int pontoscasa, int pontos [], int ganhos [], int perdidos [], int empates [], int pos_player_hand []);
- void RetirarDinheiroAposta(int money [], int valoraposta);
- int CalcSaldoCasa (int valorinicial, int money []);
- /**
- * main function: entry point of the program
- * only to invoke other functions !
- */
- int main( int argc, char* args[] )
- {
- SDL_Window *window = NULL;
- SDL_Renderer *renderer = NULL;
- TTF_Font *serif = NULL;
- SDL_Surface *cards[MAX_DECK_SIZE+1], *imgs[2];
- SDL_Event event;
- int delay = 300;
- int quit = 0;
- int money[MAX_PLAYERS] = {110, 110, 110, 110};
- int player_cards[MAX_PLAYERS][MAX_CARD_HAND] = {{0}};
- int house_cards[MAX_CARD_HAND] = {0};
- int pos_house_hand = 0;
- int pos_player_hand[MAX_PLAYERS] = {0};
- //VARIÁVEIS CRIADAS POR MIM RELATIVAS AO FUNCIONAMENTO DO JOGO
- int VetorCartas[6*MAX_DECK_SIZE]; //O máximo de baralhos de cada jogo é 6, logo o VetorCartas que representa o conjunto de baralhos tem dimensão 6 * (número de cartas em cada baralho)
- int num_baralhos = 0, valorinicial = 0, valoraposta = 0; //Pârametros do jogo
- int i = 0, h= 0; //Variáveis usadas em ciclo
- int pos = 0, player = 0; //Variáveis usadas como índice do array player_cards[player][pos]: player representa o jogador, e pos a posição da carta.
- int pontos [MAX_PLAYERS + 1] = {0}, pontoscasa = 0; //pontos [] é um vetor de 5 posições, em que cada posição é referente aos pontos de cada jogador. pontoscasa representa os pontos da casa
- int newgame = 1; //newgame está 1 enquanto a jogada decorre, usada para impossibilitar fazer um novo jogo no decorrer de uma jogada.
- int ganhos [MAX_PLAYERS] = {0}, empates [MAX_PLAYERS] = {0}, perdidos [MAX_PLAYERS] = {0}; //Armazenam o número de jogos ganhos, empatados e perdidos de cada jogador ao longo do jogo.
- int attmoney = 0;//Enquanto attmoney = 0 não atualiza o dinheiro
- int saldo_casa = 0;//No final de cada jogada esta vaŕiável é atualizada, e representa o dinheiro que a casa perdeu ou ganhou
- int count_ases = 0;//É usado para o caso específico de ocorrer soft hand (count_ases == 1 e pontos_casa == 17)
- int softhand_ciclo = 0;//variável usada em ciclo para percorrer todas as cartas da casa e averiguar o numero de ases
- int jogada = 1;//Variável que não interfere com o funcionamento do jogo, apenas server para imprimir no terminal em que jogada estamos
- FILE *filestats;//ponteiro usado para a escrita de ficheiros
- //LÊ OS PARÂMETROS DO JOGO (Nº DE BARALHOS, DINHEIRO INICIAL, VALOR FIXO DE CADA APOSTA)
- LerParametrosJogo (&num_baralhos,&valorinicial,&valoraposta);
- //ATUALIZA O DINHEIRO DE CADA JOGADOR NA INTERFACE GRÁFICA CONSOANTE O VALOR INICIAL E O VALOR DA APOSTA
- //É logo retirado ao jogador o valor da aposta para a 1º jogada
- for (player = 0; player < MAX_PLAYERS; player++)
- {
- money[player] = valorinicial - valoraposta;
- }
- //INICIALIZA O VETOR DAS CARTAS
- //Preenche as posições do vetor não utilizados com o valor -1 para detetar se restam muitas cartas no baralho
- //Se o valor -1 estiver próximo inicializa-se o vetor e baralha-se como no início
- InicializarBaralho(num_baralhos, VetorCartas);
- //BARALHA O VETOR DAS CARTAS
- BaralharCartas (VetorCartas, num_baralhos);
- // initialize graphics
- InitEverything(WIDTH_WINDOW, HEIGHT_WINDOW, &serif, imgs, &window, &renderer);
- // loads the cards images
- LoadCards(cards);
- // put down some cards just for testing purposes: for you to remove !
- // DISTRIBUIÇÃO DA 1ª MÃO
- i = 0, h = 0;
- for(pos = 0; pos <= 1; pos++)
- {
- for(player = 0; player < MAX_PLAYERS; player++)
- {
- player_cards [player][pos] = VetorCartas [i];
- i++;
- }
- house_cards[h] = VetorCartas [i];
- if (h == 0) //Após ser distribuida a 1ª carta à casa incrementa-se a posição o VetorCartas para que seja a próxima carta do Baralho a ser distribuida ao jogador.
- i++; //No entanto, após ser distribuida a 2ª carta à casa não incrementamos a posição porque no "case SDLk_h:" (hit) uma das primeiras instruções é i++, ou seja incrementar a posição do vetor das cartas.
- h++;
- }
- pos_player_hand[0] = 2; //Cada jogador começa com 2 cartas.
- pos_player_hand[1] = 2;
- pos_player_hand[2] = 2;
- pos_player_hand[3] = 2;
- pos_house_hand = 1; //A casa começa com uma carta virada para cima e outra para baixo.
- //CÁLCULA OS PONTOS QUE CADA JOGADOR TEM APÓS A DISTRIBUIÇÃO DAS CARTAS
- pontos[0] = CalcPontos(player_cards,0,pos_player_hand);
- pontos[1] = CalcPontos(player_cards,1,pos_player_hand);
- pontos[2] = CalcPontos(player_cards,2,pos_player_hand);
- pontos[3] = CalcPontos(player_cards,3,pos_player_hand);
- pos = 1;
- player = 0; //PASSA A DECISÃO AO PRIMEIRO JOGADOR
- while( quit == 0 )
- {
- //Enquanto o jogador não tiver cartas por ter perdido o jogo, incrementa-se o jogador.
- while ((money [player] < valoraposta) && (pos_player_hand [player] == 0) && (player < 4))
- {
- player++;
- }
- //Se o Baralho estiver quase a chegar ao fim inicializa-se o vetor e baralha-se e informa-se o utilizador.
- //É utilizado o número 9, porque o maior número de cartas a ser distribuido consecutivamente sem passar por esta condição é 8, quando é distribuida a 1ª mão
- if (VetorCartas [i + 9] == -1)
- {
- InicializarBaralho(num_baralhos, VetorCartas);
- BaralharCartas(VetorCartas, num_baralhos);
- i=0;
- printf("\nDevido à possibilidade das cartas se esgotarem durante a jogada foram adicionadas cartas baralhadas!!!\n");
- }
- //No entanto, como forma de previnir, caso o baralho esgote, o jogo fecha e informa-se o utilizador da causa.
- else if (VetorCartas [i] == -1)
- {
- printf("\nEsgotaram-se as cartas! Por favor, inicie um novo jogo...\n");
- exit(EXIT_FAILURE);
- }
- // while there's events to handle
- while( SDL_PollEvent( &event ) )
- {
- //Caso o jogador saia do jogo, clicando no X, a janela fecha e é guardado um ficheiro com as estatísticas desse jogo.
- if( event.type == SDL_QUIT )
- {
- quit = 1;
- filestats = fopen("Estatísticas.txt","wt");
- fprintf(filestats,"Jogador\t\tGanhos \t\tEmpates \t\tPerdidos\t\t Dinheiro final\n");
- fprintf(filestats,"Player1\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\n", ganhos[0], empates[0], perdidos[0],money[0]);
- fprintf(filestats,"Player2\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\n", ganhos[1], empates[1], perdidos[1],money[1]);
- fprintf(filestats,"Player3\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\n", ganhos[2], empates[2], perdidos[2],money[2]);
- fprintf(filestats,"Player4\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\n", ganhos[3], empates[3], perdidos[3],money[3]);
- fprintf(filestats,"Variação do saldo da casa = %d", saldo_casa);
- fclose(filestats);
- }
- else if ( event.type == SDL_KEYDOWN )
- {
- switch ( event.key.keysym.sym )
- {
- //Caso o jogador prima a tecla q, a janela fecha, e é guardado um ficheiro com as estatísticas do jogo.
- case SDLK_q:
- quit = 1;
- filestats = fopen("Estatísticas.txt","wt");
- fprintf(filestats,"Jogador\t\tGanhos \t\tEmpates \t\tPerdidos\t\t Dinheiro final\n");
- fprintf(filestats,"Player1\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\n", ganhos[0], empates[0], perdidos[0],money[0]);
- fprintf(filestats,"Player2\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\n", ganhos[1], empates[1], perdidos[1],money[1]);
- fprintf(filestats,"Player3\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\n", ganhos[2], empates[2], perdidos[2],money[2]);
- fprintf(filestats,"Player4\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\t\t\t\t\t%d\n", ganhos[3], empates[3], perdidos[3],money[3]);
- fprintf(filestats,"Variação do saldo da casa = %d", saldo_casa);
- fclose(filestats);
- break;
- //Se o jogador fizer stand (tecla s)
- case SDLK_s:
- pontos [player] = CalcPontos(player_cards, player, pos_player_hand);
- pos = 1;
- player++;
- break;
- //Se o jogador fizer hit (tecla h)
- case SDLK_h:
- pos_player_hand [player] ++;
- pos++;
- i++;
- //É distribuída a próxima carta do baralho
- player_cards [player][pos] = VetorCartas [i];
- //Calcula os pontos do jogador que fez hit
- pontos [player] = CalcPontos(player_cards, player, pos_player_hand);
- //Se o jogador tiver mais do que 21 pontos
- if (pontos [player] > MAX_POINTS)
- {
- //O controlo passa para o próximo jogador.
- player++;
- //Se o jogador seguinte ainda estiver a jogar fica com 2 cartas, e a posição da carta é 1
- if (money [player] >= valoraposta)
- {
- pos = 1;
- pos_player_hand [player] = 2;
- }
- }
- break;
- //Se o jogador fizer "New Game" (tecla n)
- case SDLK_n:
- if (newgame == 0)
- {
- //attmoney = 0 permite a atualização do dinheiro na janela
- attmoney = 0;
- //Com newgame a 1, se carregarem na tecla n não acontece nada
- newgame = 1;
- i++;
- NewGame(money, i,VetorCartas,pos_player_hand,&pos_house_hand,player_cards,house_cards,valorinicial,valoraposta); // São distribuidas as cartas aos jogadores
- //É retirado a cada jogador o valor da aposta.
- RetirarDinheiroAposta(money, valoraposta);
- //Avança no baralho, visto que a função NewGame não altera o valor de i (visto ser usada passagem por valor)
- i = i + 9;
- //Quando inicia um novo jogo, o controlo passa para o primeiro jogador e visto que tem duas cartas, a posição da carta (pos) = 1
- pos = 1;
- player = 0;
- jogada++;
- }
- default:
- break;
- }
- //(Quando)/(Se) os pontos da casa forem maiores ou iguais a 17, são calculados os pontos de cada jogador e armazenados, para depois serem comparados com os pontos da casa.
- if (pontoscasa >= MIN_HOUSE_POINTS)
- {
- pontos[0] = CalcPontos(player_cards,0,pos_player_hand);
- pontos[1] = CalcPontos(player_cards,1,pos_player_hand);
- pontos[2] = CalcPontos(player_cards,2,pos_player_hand);
- pontos[3] = CalcPontos(player_cards,3,pos_player_hand);
- }
- }
- //Quando acabar a jogada (newgame == 0) e puder-se atualizar o dinheiro (attmoney == 0)
- if (newgame == 0 && attmoney == 0)
- {
- VerificarPontos(pontos, money, valoraposta, pontoscasa, pos_player_hand, pos_house_hand);//É devolvido o dinheiro a quem tenha ganho
- CalculaGanhosEmpatesPerdidos(pos_house_hand, money, valoraposta, pontoscasa, pontos, ganhos, perdidos, empates, pos_player_hand);//Verifica-se e armazena-se quem ganhou perdeu e empatou
- attmoney = 1;
- }
- //Se fôr a vez da casa e o jogo ainda nao tiver terminado:_
- if (player == 4 && newgame == 1)
- {
- //newgame = 0 (pode-se fazer newgame)
- newgame = 0;
- //Mostra-se a 2ª carta da casa
- pos_house_hand = 2;
- h = 1;
- //Calcula-se os pontos das duas cartas da casa para averiguar se é > 17
- pontoscasa = CalcPontosCasa(pos_house_hand, house_cards);
- //Enquanto os pontos da casa forem menor que 17, a casa retira uma carta do baralho e vai calculando os pontos
- while (pontoscasa < MIN_HOUSE_POINTS)
- {
- i++;
- pos_house_hand++;
- h++;
- house_cards[h] = VetorCartas [i];
- pontoscasa = CalcPontosCasa(pos_house_hand, house_cards);
- }
- //Este "for" percorre as cartas da casa e por cada Às encontrado incrementa o count_ases, que nos dá o número de Ases que a casa tem
- for (softhand_ciclo = 0; softhand_ciclo <= h - 1; softhand_ciclo++)
- {
- switch (house_cards [softhand_ciclo])
- {
- case 12: case 25: case 38: case 52: count_ases++;
- }
- }
- //[SOFTHAND] Se a casa tiver apenas um às e tiver 17 pontos, pede mais uma carta
- if ((count_ases == 1) && (pontoscasa == MIN_HOUSE_POINTS))
- {
- i++;
- pos_house_hand++;
- h++;
- house_cards[h] = VetorCartas [i];
- pontoscasa = CalcPontosCasa(pos_house_hand, house_cards);
- }
- //Quando os pontos da casa forem maiores ou iguais a 17 imprime no terminal os pontos de cada jogador e da casa.
- if (pontoscasa >= MIN_HOUSE_POINTS)
- {
- printf("\n ---------- Final da jogada %d ----------\n", jogada);
- pontos[0] = CalcPontos(player_cards,0,pos_player_hand);
- printf("\nO jogador 1 têm %d pontos \n\n", pontos[0]);
- pontos[1] = CalcPontos(player_cards,1,pos_player_hand);
- printf("O jogador 2 têm %d pontos \n\n", pontos[1]);
- pontos[2] = CalcPontos(player_cards,2,pos_player_hand);
- printf("O jogador 3 têm %d pontos \n\n", pontos[2]);
- pontos[3] = CalcPontos(player_cards,3,pos_player_hand);
- printf("O jogador 4 têm %d pontos \n\n", pontos[3]);
- printf("A casa tem %d pontos\n\n", pontoscasa);
- }
- }
- //Função que calcula quanto dinheiro é que a casa ganhou ou perdeu até ao momento
- saldo_casa = CalcSaldoCasa(valorinicial, money);
- }
- // render game table
- RenderTable(newgame, pontoscasa, money, pontos, player, serif, imgs, renderer);
- // render house cards
- RenderHouseCards(house_cards, pos_house_hand, cards, renderer);
- // render player cards
- RenderPlayerCards(player_cards, pos_player_hand, cards, renderer);
- // render in the screen all changes above
- SDL_RenderPresent(renderer);
- // add a delay
- SDL_Delay( delay );
- }
- // free memory allocated for images and textures and close everything including fonts
- UnLoadCards(cards);
- TTF_CloseFont(serif);
- SDL_FreeSurface(imgs[0]);
- SDL_FreeSurface(imgs[1]);
- SDL_DestroyRenderer(renderer);
- SDL_DestroyWindow(window);
- SDL_Quit();
- return EXIT_SUCCESS;
- }
- //FUNÇÕES CRIADAS POR MIM QUE FORAM UTILIZADAS AO LONGO DO MAIN
- //Obtém e armazena em variáveis o número de baralhos, o dinheiro inicial, e o valor fixo de cada aposta
- void LerParametrosJogo ( int *num_baralhos, int *valor_inicial, int *dinheiro_apostado )
- {
- printf("\t\t****************************************\n");
- printf("\t\t* BEM VINDOS AO BLACKJACK! *\n");
- printf("\t\t****************************************\n");
- puts("\n");
- printf("Digite o número de baralhos com que pretende jogar: ");
- scanf("%d", num_baralhos);
- //O nº de baralhos tem que estar contido entre 1 e 6. Caso contrário informa o utilizador
- if(*num_baralhos < 1 || *num_baralhos > 6)
- {
- printf("\nO número de baralhos tem de estar entre 1 e 6!\n");
- exit(EXIT_FAILURE);
- }
- printf("\nDigite o dinheiro inicial de cada jogador: ");
- scanf("%d", valor_inicial);
- // O dinheiro inicial tem de ser superior a 10 euros. Caso contrário informa o utilizador e termina o processo
- if(*valor_inicial < 10)
- {
- printf("\nO dinheiro inicial tem de ser superior a 10 euros!\n");
- exit(EXIT_FAILURE);
- }
- printf("\nDigite o valor fixo de cada aposta: ");
- scanf("%d",dinheiro_apostado);
- /* O valor da aposta tem de ser, no mínimo, 5 vezes menor do que o dinheiro inicial
- Caso contrário informa o utilizador e termina o processo*/
- if(*dinheiro_apostado > (*valor_inicial/5))
- {
- printf("\nO dinheiro inicial tem de ser 5 vezes maior que o valor de cada aposta!\n");
- exit(EXIT_FAILURE);
- }
- /* O valor da aposta tem de ser igual ou superior a 1 euro
- Caso contrário informa o utilizador e termina o processo */
- if(*dinheiro_apostado < 1)
- {
- printf("\nO valor de cada aposta tem de ser no mínimo 1 euro!\n");
- exit(EXIT_FAILURE);
- }
- }
- /* Função utilizada para inicializar o vetor baralho
- Dependendo do número de baralhos introduzido pelo utilizador, preenche certas posições do baralho, e as não utilizadas preenche com o valor -1 */
- void InicializarBaralho(int num_baralhos, int VetorCartas [])
- {
- int soma = 0, k = 0, i = 0, j = 0;
- do {
- for (i = 0 + soma, j = 0; j < 52; i++, j++)
- {
- VetorCartas [i] = j;
- }
- soma = soma + 52;
- k++;
- } while (k < num_baralhos);
- for (i = soma; i < 311; i++)
- {
- VetorCartas [i] = -1;
- }
- }
- // Baralha o vetor representante das cartas do jogo, no entanto, não mistura as posições que contêm cartas com as que não têm (-1)
- void BaralharCartas ( int vetorcartas [], int num_baralhos )
- {
- int j = 0, a = 0, i = 0, aux = 0;
- srand (time(NULL));
- a = MAX_DECK_SIZE * num_baralhos;
- for (i = a - 1; i > 0; i--) //Algoritmo de Fisher-Yales:
- { //Troca a última posição do vetor por uma posição aleatória
- j = (rand () % i); //Troca a penúltima posição do vetor por uma posição aleatória
- aux = vetorcartas[i]; //Troca a ante-penúltima posição do vetor por uma posição aleatória
- vetorcartas[i] = vetorcartas[j]; //E assim sucessivamente... Resultado: Vetor Baralhado
- vetorcartas[j] = aux;
- }
- }
- //Calcula os pontos de todos os jogadores e armazena esses pontos num vetor cuja 1ª posição (posição 0) refere-se ao 1º jogador e assim sucessivamente
- int CalcPontos (int playercards[][MAX_CARD_HAND], int player, int posicao_player_hand [])
- {
- int cardpoints = 0, pos = 0, valortotal = 0, az=0;
- for (pos = 0; pos <= posicao_player_hand[player]-1; pos++)
- {
- cardpoints = 0;
- //A cada card ID, faz corresponder um número de pontos
- switch (playercards[player][pos])
- {
- case 0: case 13: case 26: case 39: cardpoints = 2; break;
- case 1: case 14: case 27: case 40: cardpoints = 3; break;
- case 2: case 15: case 28: case 41: cardpoints = 4; break;
- case 3: case 16: case 29: case 42: cardpoints = 5; break;
- case 4: case 17: case 30: case 43: cardpoints = 6; break;
- case 5: case 18: case 31: case 44: cardpoints = 7; break;
- case 6: case 19: case 32: case 45: cardpoints = 8; break;
- case 7: case 20: case 33: case 46: cardpoints = 9; break;
- case 8: case 21: case 34: case 47: cardpoints =10; break;
- case 9: case 22: case 35: case 48: cardpoints = 10; break;
- case 10: case 23: case 36: case 49: cardpoints = 10; break;
- case 11: case 24: case 37: case 50: cardpoints = 10; break;
- case 12: case 25: case 38: case 51: cardpoints = 11; break;
- }
- valortotal = valortotal + cardpoints;
- //Se o jogador tiver um ÀS e exceder os 21 pontos, ÀS passa a valer 1 ponto
- if(cardpoints == 11)
- {
- az = 1;
- }
- //Retira os 11 pontos que o ás representava e soma um. (-11 + 1 = -10)
- if((valortotal > 21) && az ==1)
- {
- az = 0;
- valortotal = valortotal - 10;
- }
- }
- return valortotal;
- }
- /* Criação de uma nova função para calcular os PONTOS DA CASA tendo em conta que a outra função tem como parâmetro de entrada
- uma matriz (Array de 2 dimensões), enquanto a variável house_cards é um Vetor (1 dimensão), o que impossibilita o
- seu uso como parâmetro de entrada na função atrás criada, no entanto o processo é muito semelhante */
- int CalcPontosCasa(int pos_house_hand, int house_cards[])
- {
- int pos = 0, valor = 0, cardpoints = 0, az = 0;
- for(pos = 0; pos <= pos_house_hand - 1; pos++)
- {
- //A cada card ID faz corresponder um número de pontos
- switch (house_cards[pos])
- {
- case 0: case 13: case 26: case 39: valor = 2; break;
- case 1: case 14: case 27: case 40: valor = 3; break;
- case 2: case 15: case 28: case 41: valor = 4; break;
- case 3: case 16: case 29: case 42: valor = 5; break;
- case 4: case 17: case 30: case 43: valor = 6; break;
- case 5: case 18: case 31: case 44: valor = 7; break;
- case 6: case 19: case 32: case 45: valor = 8; break;
- case 7: case 20: case 33: case 46: valor = 9; break;
- case 8: case 21: case 34: case 47: valor = 10; break;
- case 9: case 22: case 35: case 48: valor = 10; break;
- case 10: case 23: case 36: case 49: valor = 10; break;
- case 11: case 24: case 37: case 50: valor = 10; break;
- case 12: case 25: case 38: case 51: valor = 11; break;
- }
- cardpoints = cardpoints + valor;
- //Se a casa tiver um ÀS e exceder os 21 pontos, ÀS passa a valer 1 ponto
- if(valor ==11)
- {
- az = 1;
- }
- //Retira os 11 pontos que o ÀS representava e soma um. (-11 + 1 = -10)
- if((cardpoints > 21) && az ==1)
- {
- az = 0;
- cardpoints = cardpoints - 10;
- }
- }
- return cardpoints;
- }
- //Compara os pontos dos jogadores e da casa e devolve dinheiro aos jogadores que ganharam.
- void VerificarPontos (int pontos [], int money [], int valoraposta, int pontoscasa, int pos_player_hand [], int pos_house_hand)
- {
- int player = 0;
- for (player = 0; player < MAX_PLAYERS; player++)
- {
- //Se o jogador já não estiver a jogar
- if (money [player] < valoraposta && pos_player_hand [player] == 0)
- {
- // Não devolve nem retira dinheiro
- }
- // Jogador faz BLACKJACK (2 cartas) e a casa não tem 21 pontos
- // É devolvido o dinheiro apostado mais 1.5 * dinheiro apostado
- else if (((pontos [player] == MAX_POINTS) && (pos_player_hand[player] == 2)) && (pontoscasa != MAX_POINTS))
- {
- money [player] = money [player] + (2*valoraposta) + (valoraposta/2);
- }
- // Jogador faz BLACKJACK (2 cartas) e a casa também faz BLACKJACK -> EMPATE
- // É devolvido o dinheiro apostado
- else if (((pontos [player] == MAX_POINTS) && (pos_player_hand[player] == 2)) && (pontoscasa == MAX_POINTS) && (pos_house_hand == 2))
- {
- money [player] = money [player] + valoraposta;
- }
- // Jogador faz BLACKJACK (2 cartas) e a casa tem 21 pontos, sem BLACKJACK
- // É devolvido o dinheiro apostado mais 1.5 * (valor da aposta)
- else if (((pontos [player] == MAX_POINTS) && (pos_player_hand[player] == 2)) && (pontoscasa == MAX_POINTS) && (pos_house_hand != 2))
- {
- money [player] = money [player] + (1.5 *valoraposta);
- }
- // JOGADOR PERDE: A casa, sem exceder os 21 pontos, tem mais pontos que o jogador
- // Não é devolvido dinheiro ao jogador
- else if ((pontoscasa > pontos[player]) && (pontoscasa <= MAX_POINTS))
- {
- money [player] = money [player]; //
- }
- // JOGADOR GANHA: O jogador, sem exceder os 21 pontos, tem mais pontos que a casa
- // Devolve-se o dobro do dinheiro que o jogador apostou
- else if ((pontoscasa < pontos[player]) && (pontos [player] <= MAX_POINTS))
- {
- money [player] = money [player] + (2 * valoraposta);
- }
- // JOGADOR GANHA: O jogador não excede os 21 pontos, mas a casa excede
- // Devolve-se o dobro do dinheiro que o jogador apostou
- else if ((pontos[player] <= MAX_POINTS) && (pontoscasa > MAX_POINTS))
- {
- money [player] = money [player] + (2 * valoraposta);
- }
- // JOGADOR PERDE: Sempre que o jogador excede os 21 pontos
- // Não é devolvido o dinheiro da aposta ao jogador
- else if (((pontos [player]) > MAX_POINTS))
- {
- money [player] = money [player];
- }
- // JOGADOR EMPATA: Os pontos do jogador são iguais aos pontos da casa
- // É devolvido o dinheiro da aposta ao jogador
- else if ((pontos [player] <= MAX_POINTS) && (pontos [player] == pontoscasa))
- {
- money [player] = money [player] + valoraposta;
- }
- }
- }
- // Inicia uma nova jogada, redistribui a 1st hand
- void NewGame(int money [], int i, int vetorcartas[], int pos_player_hand[], int *pos_house_hand, int player_cards[][MAX_CARD_HAND], int house_cards [], int valorinicial, int valoraposta)
- {
- int h = 0, pos = 0, player = 0;
- for(pos=0; pos<=1; pos++)
- {
- for(player=0; player<MAX_PLAYERS; player++)
- {
- while (money [player] < valoraposta)
- {
- player++;
- }
- player_cards [player][pos] = vetorcartas [i];
- i++;
- }
- house_cards[h] = vetorcartas [i];
- if (h == 0)
- i++;
- h++;
- }
- pos_player_hand[0] = 2;
- pos_player_hand[1] = 2;
- pos_player_hand[2] = 2;
- pos_player_hand[3] = 2;
- *pos_house_hand = 1;
- for (player = 0; player < MAX_PLAYERS; player ++)
- {
- if (money [player] < valoraposta)
- {
- pos_player_hand [player] = 0;
- }
- }
- }
- // Função responsável por calcular e armazenar o número de jogadas ganhas, perdidas, empatadas por cada jogador ao longo do jogo
- void CalculaGanhosEmpatesPerdidos(int pos_house_hand, int money [], int valoraposta, int pontoscasa, int pontos [], int ganhos [], int perdidos [], int empates [], int pos_player_hand [])
- {
- int i = 0;
- for(i=0; i < MAX_PLAYERS; i++)
- {
- // Se o jogador não estiver a jogar por ter perdido, não é alterado o número de jogos ganhos, perdidos e empatados por esse jogador
- if((money [i] < valoraposta) && (pos_player_hand [i] == 0))
- {
- ganhos [i] = ganhos [i];
- perdidos [i] = perdidos [i];
- empates [i] = empates [i];
- }
- // Se o jogador tiver BLACKJACK e a casa tiver 21 pontos sem BLACKJACK incrementa o número de jogos ganhos
- else if ((pontos [i] == MAX_POINTS ) && (pos_player_hand [i] == 2) && (pontoscasa == MAX_POINTS) && (pos_house_hand != 2))
- {
- ganhos [i] ++;
- continue;
- }
- // Se o jogador exceder os 21 pontos incrementa o número de jogos perdidos
- else if (pontos [i] > MAX_POINTS)
- {
- perdidos [i] ++;
- continue;
- }
- // Se o jogador tiver menos pontos que a casa, sem que a casa exceda os 21 pontos, incrementa o número de jogos perdidos
- else if ((pontos [i] < pontoscasa) && (pontoscasa <= MAX_POINTS))
- {
- perdidos [i] ++;
- continue;
- }
- // Se a casa tiver menos pontos que o jogador, sem que o jogador tenha excedido os 21 pontos, incrementa o número de jogos ganhos
- else if ((pontoscasa < pontos [i]) && (pontos [i] <= MAX_POINTS))
- {
- ganhos [i]++;
- continue;
- }
- // Se o jogador não exceder 21 pontos e a casa exceder incrementa o número de jogos ganhos.
- else if ((pontos [i] <= MAX_POINTS) && (pontoscasa > MAX_POINTS))
- {
- ganhos [i]++;
- continue;
- }
- // Se o jogador não exceder os 21 pontos e tiver os mesmos pontos do que a casa incrementa o número de empates
- else if ((pontos[i] <= MAX_POINTS && (pontos [i] == pontoscasa)))
- {
- empates [i]++;
- continue;
- }
- }
- }
- /* Função que retira o dinheiro da aposta no início de cada jogada.
- Nota: -> A função VerificarPontos, atualiza o dinheiro dos jogadores no final de uma jogada consoante os jogadores tenham ganho ou perdido
- -> Na função não é logo retirado o valor da aposta, pois isto só acontece se o jogador carregar na tecla n, para jogar um novo jogo */
- void RetirarDinheiroAposta(int money [], int valoraposta)
- {
- int i=0;
- for (i=0; i < MAX_PLAYERS; i++)
- {
- if (money [i] >= valoraposta)
- {
- money [i] = money [i] - valoraposta;
- }
- else
- {
- money [i] = money [i];
- }
- }
- }
- //Função que calcula a variação do saldo da casa
- int CalcSaldoCasa (int valorinicial, int money [])
- {
- int player = 0, dinheiro = 0, saldo = 0;
- for (player = 0; player < MAX_PLAYERS; player++)
- {
- dinheiro = valorinicial - money [player];
- saldo = saldo + dinheiro;
- }
- return saldo;
- }
- /**
- * RenderTable: Draws the table where the game will be played, namely:
- * - some texture for the background
- * - the right part with the IST logo and the student name and number
- * - squares to define the playing positions of each player
- * - names and the available money for each player
- * \param _money amount of money of each player
- * \param _img surfaces where the table background and IST logo were loaded
- * \param _renderer renderer to handle all rendering in a window
- */
- void RenderTable(int newgame, int pontoscasa, int _money[], int pontos [], int player, TTF_Font *_font, SDL_Surface *_img[], SDL_Renderer* _renderer)
- {
- SDL_Color black = { 0, 0, 0 }; // black
- SDL_Color white = { 255, 255, 255 }; // white
- char name_bust_str[STRING_SIZE];
- SDL_Texture *table_texture;
- SDL_Rect tableSrc, tableDest, playerRect;
- int separatorPos = (int)(0.95f*WIDTH_WINDOW); // seperates the left from the right part of the window
- int height;
- char house_points_str[STRING_SIZE], points_money_str[STRING_SIZE];
- // set color of renderer to some color
- SDL_SetRenderDrawColor( _renderer, 255, 255, 255, 255 );
- // clear the window
- SDL_RenderClear( _renderer );
- tableDest.x = tableSrc.x = 0;
- tableDest.y = tableSrc.y = 0;
- tableSrc.w = _img[0]->w;
- tableSrc.h = _img[0]->h;
- tableDest.w = separatorPos;
- tableDest.h = HEIGHT_WINDOW;
- table_texture = SDL_CreateTextureFromSurface(_renderer, _img[0]);
- SDL_RenderCopy(_renderer, table_texture, &tableSrc, &tableDest);
- // render the IST Logo
- height = RenderLogo(separatorPos, 0, _img[1], _renderer);
- // render the student name
- height += RenderText(separatorPos+3*MARGIN, height, myName, _font, &black, _renderer);
- // this renders the student number
- RenderText(separatorPos+3*MARGIN, height, myNumber, _font, &black, _renderer);
- // renders the areas for each player: names and money too !
- for ( int i = 0; i < MAX_PLAYERS; i++)
- {
- // renders the squares + name for each player
- SDL_SetRenderDrawColor(_renderer, 255, 255, 255, 255 );
- if (player == i)
- {
- SDL_SetRenderDrawColor(_renderer, 0, 0, 200, 0 );
- }
- playerRect.x = i*(separatorPos/4-5)+10;
- playerRect.y = (int) (0.55f*HEIGHT_WINDOW);
- playerRect.w = separatorPos/4-5;
- playerRect.h = (int) (0.42f*HEIGHT_WINDOW);
- // Enquanto os pontos do jogador forem menores do que 21, aparece o nome deles , quando fazem bust, aparece BUST à frente
- if (pontos [i] <= 21)
- {
- sprintf(name_bust_str,"%s", playerNames[i]);
- }
- else
- {
- sprintf(name_bust_str,"%s BUST!", playerNames[i]);
- }
- RenderText(playerRect.x+10, playerRect.y-50, name_bust_str, _font, &white, _renderer);
- SDL_RenderDrawRect(_renderer, &playerRect);
- sprintf(points_money_str, "%d pontos -- %d euros", pontos [i], _money [i]);
- RenderText(playerRect.x + 10, playerRect.y-30, points_money_str, _font, &white, _renderer);
- // Quando a jogada acabar aparecem os pontos da casa
- if (newgame == 0)
- {
- sprintf(house_points_str, "Pontos da casa: %d", pontoscasa);
- RenderText(100, playerRect.y-150, house_points_str, _font, &white, _renderer);
- }
- }
- // destroy everything
- SDL_DestroyTexture(table_texture);
- }
- /**
- * RenderHouseCards: Renders cards of the house
- * \param _house vector with the house cards
- * \param _pos_house_hand position of the vector _house with valid card IDs
- * \param _cards vector with all loaded card images
- * \param _renderer renderer to handle all rendering in a window
- */
- void RenderHouseCards(int _house[], int _pos_house_hand, SDL_Surface **_cards, SDL_Renderer* _renderer)
- {
- int card, x, y;
- int div = WIDTH_WINDOW/CARD_WIDTH;
- // drawing all house cards
- for ( card = 0; card < _pos_house_hand; card++)
- {
- // calculate its position
- x = (div/2-_pos_house_hand/2+card)*CARD_WIDTH + 15;
- y = (int) (0.26f*HEIGHT_WINDOW);
- // render it !
- RenderCard(x, y, _house[card], _cards, _renderer);
- }
- // just one card ?: draw a card face down
- if (_pos_house_hand == 1)
- {
- x = (div/2-_pos_house_hand/2+1)*CARD_WIDTH + 15;
- y = (int) (0.26f*HEIGHT_WINDOW);
- RenderCard(x, y, MAX_DECK_SIZE, _cards, _renderer);
- }
- }
- /**
- * RenderPlayerCards: Renders the hand, i.e. the cards, for each player
- * \param _player_cards 2D array with the player cards, 1st dimension is the player ID
- * \param _pos_player_hand array with the positions of the valid card IDs for each player
- * \param _cards vector with all loaded card images
- * \param _renderer renderer to handle all rendering in a window
- */
- void RenderPlayerCards(int _player_cards[][MAX_CARD_HAND], int _pos_player_hand[], SDL_Surface **_cards, SDL_Renderer* _renderer)
- {
- int pos, x, y, num_player, card;
- // for every card of every player
- for ( num_player = 0; num_player < MAX_PLAYERS; num_player++)
- {
- for ( card = 0; card < _pos_player_hand[num_player]; card++)
- {
- // draw all cards of the player: calculate its position: only 4 positions are available !
- pos = card % 4;
- x = (int) num_player*((0.95f*WIDTH_WINDOW)/4-5)+(card/4)*12+15;
- y = (int) (0.55f*HEIGHT_WINDOW)+10;
- if ( pos == 1 || pos == 3) x += CARD_WIDTH + 30;
- if ( pos == 2 || pos == 3) y += CARD_HEIGHT+ 10;
- // render it !
- RenderCard(x, y, _player_cards[num_player][card], _cards, _renderer);
- }
- }
- }
- /**
- * RenderCard: Draws one card at a certain position of the window, based on the card code
- * \param _x X coordinate of the card position in the window
- * \param _y Y coordinate of the card position in the window
- * \param _num_card card code that identifies each card
- * \param _cards vector with all loaded card images
- * \param _renderer renderer to handle all rendering in a window
- */
- void RenderCard(int _x, int _y, int _num_card, SDL_Surface **_cards, SDL_Renderer* _renderer)
- {
- SDL_Texture *card_text;
- SDL_Rect boardPos;
- // area that will be occupied by each card
- boardPos.x = _x;
- boardPos.y = _y;
- boardPos.w = CARD_WIDTH;
- boardPos.h = CARD_HEIGHT;
- // render it !
- card_text = SDL_CreateTextureFromSurface(_renderer, _cards[_num_card]);
- SDL_RenderCopy(_renderer, card_text, NULL, &boardPos);
- // destroy everything
- SDL_DestroyTexture(card_text);
- }
- /**
- * LoadCards: Loads all images of the cards
- * \param _cards vector with all loaded card images
- */
- void LoadCards(SDL_Surface **_cards)
- {
- int i;
- char filename[STRING_SIZE];
- // loads all cards to an array
- for (i = 0 ; i < MAX_DECK_SIZE; i++ )
- {
- // create the filename !
- sprintf(filename, ".//cartas//carta_%02d.png", i+1);
- // loads the image !
- _cards[i] = IMG_Load(filename);
- // check for errors: deleted files ?
- if (_cards[i] == NULL)
- {
- printf("Unable to load image: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- }
- // loads the card back
- _cards[i] = IMG_Load(".//cartas//carta_back.jpg");
- if (_cards[i] == NULL)
- {
- printf("Unable to load image: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- }
- /**
- * UnLoadCards: unloads all card images of the memory
- * \param _cards vector with all loaded card images
- */
- void UnLoadCards(SDL_Surface **_array_of_cards)
- {
- // unload all cards of the memory: +1 for the card back
- for (int i = 0 ; i < MAX_DECK_SIZE + 1; i++ )
- {
- SDL_FreeSurface(_array_of_cards[i]);
- }
- }
- /**
- * RenderLogo function: Renders the IST Logo on the window screen
- * \param x X coordinate of the Logo
- * \param y Y coordinate of the Logo
- * \param _logoIST surface with the IST logo image to render
- * \param _renderer renderer to handle all rendering in a window
- */
- int RenderLogo(int x, int y, SDL_Surface *_logoIST, SDL_Renderer* _renderer)
- {
- SDL_Texture *text_IST;
- SDL_Rect boardPos;
- // space occupied by the logo
- boardPos.x = x;
- boardPos.y = y;
- boardPos.w = _logoIST->w;
- boardPos.h = _logoIST->h;
- // render it
- text_IST = SDL_CreateTextureFromSurface(_renderer, _logoIST);
- SDL_RenderCopy(_renderer, text_IST, NULL, &boardPos);
- // destroy associated texture !
- SDL_DestroyTexture(text_IST);
- return _logoIST->h;
- }
- /**
- * RenderText function: Renders the IST Logo on the window screen
- * \param x X coordinate of the text
- * \param y Y coordinate of the text
- * \param text string where the text is written
- * \param font TTF font used to render the text
- * \param _renderer renderer to handle all rendering in a window
- */
- int RenderText(int x, int y, const char *text, TTF_Font *_font, SDL_Color *_color, SDL_Renderer* _renderer)
- {
- SDL_Surface *text_surface;
- SDL_Texture *text_texture;
- SDL_Rect solidRect;
- solidRect.x = x;
- solidRect.y = y;
- // create a surface from the string text with a predefined font
- text_surface = TTF_RenderText_Blended(_font,text,*_color);
- if(!text_surface)
- {
- printf("TTF_RenderText_Blended: %s\n", TTF_GetError());
- exit(EXIT_FAILURE);
- }
- // create texture
- text_texture = SDL_CreateTextureFromSurface(_renderer, text_surface);
- // obtain size
- SDL_QueryTexture( text_texture, NULL, NULL, &solidRect.w, &solidRect.h );
- // render it !
- SDL_RenderCopy(_renderer, text_texture, NULL, &solidRect);
- SDL_DestroyTexture(text_texture);
- SDL_FreeSurface(text_surface);
- return solidRect.h;
- }
- /**
- * InitEverything: Initializes the SDL2 library and all graphical components: font, window, renderer
- * \param width width in px of the window
- * \param height height in px of the window
- * \param _img surface to be created with the table background and IST logo
- * \param _window represents the window of the application
- * \param _renderer renderer to handle all rendering in a window
- */
- void InitEverything(int width, int height, TTF_Font **_font, SDL_Surface *_img[], SDL_Window** _window, SDL_Renderer** _renderer)
- {
- InitSDL();
- InitFont();
- *_window = CreateWindow(width, height);
- *_renderer = CreateRenderer(width, height, *_window);
- // load the table texture
- _img[0] = IMG_Load("table_texture.png");
- if (_img[0] == NULL)
- {
- printf("Unable to load image: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- // load IST logo
- _img[1] = SDL_LoadBMP("ist_logo.bmp");
- if (_img[1] == NULL)
- {
- printf("Unable to load bitmap: %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- // this opens (loads) a font file and sets a size
- *_font = TTF_OpenFont("FreeSerif.ttf", 16);
- if(!*_font)
- {
- printf("TTF_OpenFont: %s\n", TTF_GetError());
- exit(EXIT_FAILURE);
- }
- }
- /**
- * InitSDL: Initializes the SDL2 graphic library
- */
- void InitSDL()
- {
- // init SDL library
- if ( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
- {
- printf(" Failed to initialize SDL : %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- }
- /**
- * InitFont: Initializes the SDL2_ttf font library
- */
- void InitFont()
- {
- // Init font library
- if(TTF_Init()==-1)
- {
- printf("TTF_Init: %s\n", TTF_GetError());
- exit(EXIT_FAILURE);
- }
- }
- /**
- * CreateWindow: Creates a window for the application
- * \param width width in px of the window
- * \param height height in px of the window
- * \return pointer to the window created
- */
- SDL_Window* CreateWindow(int width, int height)
- {
- SDL_Window *window;
- // init window
- window = SDL_CreateWindow( "BlackJack", WINDOW_POSX, WINDOW_POSY, width+EXTRASPACE, height, 0 );
- // check for error !
- if ( window == NULL )
- {
- printf("Failed to create window : %s\n", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- return window;
- }
- /**
- * CreateRenderer: Creates a renderer for the application
- * \param width width in px of the window
- * \param height height in px of the window
- * \param _window represents the window for which the renderer is associated
- * \return pointer to the renderer created
- */
- SDL_Renderer* CreateRenderer(int width, int height, SDL_Window *_window)
- {
- SDL_Renderer *renderer;
- // init renderer
- renderer = SDL_CreateRenderer( _window, -1, 0 );
- if ( renderer == NULL )
- {
- printf("Failed to create renderer : %s", SDL_GetError());
- exit(EXIT_FAILURE);
- }
- // set size of renderer to the same as window
- SDL_RenderSetLogicalSize( renderer, width+EXTRASPACE, height );
- return renderer;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement