RafaelSobral Posted February 27, 2014 at 07:14 PM Report #546968 Posted February 27, 2014 at 07:14 PM Boa tarde pessoal, estou a fazer o jogo do blackjack que para quem não sabe é um jogo onde saiem várias cartas de cada vez e cada carta tem um valor, o objetivo é fazer 21 pontos certos e não nunca mais, pois se fizer mais que 21 pontos perde. Exemplo : sai a carta 7, 10 e 4 =21 . Ganhou ! Estou com dúvidas numa etapa do programa que é a seguinte : O programa gera várias numeros aleatórios entre 1 e 13 ( o "1" equivale ao ás, o "11" ao valete, "12" a dama, "13" ao rei , e as restantes de "2" até "10" são as cartas normais. Depois do programa gerar esses números coloca-os num array de 52 posições ( pois são 52 cartas no baralho ), como podem ver na seguintes linha de código : int gerar_carta_aleatoria() { #include <time.h> #define MAX 52 srand(time(NULL)); int v[MAX],i, j, numeros; for(i=0;i<MAX;i++){ //Colocar numeros aleatorios no array numeros = rand() % 13 + 1; v[i]=numeros; } for(i=0;i<MAX;i++){ printf("%d ",v[i]); } printf("\n"); system("pause"); } Agora surge a parte mais complicada do programa a meu ver, que é a seguinte : Como só existem 4 naipes, só pode haver 4 cartas do mesmo valor .. 4 cartas com o numero "2" , com o numero "3" , etc , e eu não sei como é que limito a que cada numero que é gerado, não seja gerado mais do que 4 vezes. Já andei a pesquisar aqui no fórum e vi que existe uma maneira que era que cada vez que um numero era gerado ele iria verificar se esse número já existisse e se já existisse colocava no lugar desse numero no array um "1" , caso esse numero não estivesse ocupado ainda , ou seja estaria "0" ele iria aceitar esse numero gerado e então colocaria um "1" nesse lugar , porém ainda não aprendi a fazer isso. Penso que a estratégia é mesmo gerar um numero, verificar se esse numero já está no array mais do que 4 vezes, se estiver , ele gera outro numero, se não estiver ele aceitar o numero gerado, agora escrever isso em código é que está mais complicado .. Cumprimentos.
HappyHippyHippo Posted February 27, 2014 at 07:32 PM Report #546975 Posted February 27, 2014 at 07:32 PM existem vários tópicos no fórum sobre este assunto. a resolução deste problema não passa pela geração de números aleatórios mas sim manter uma lista de cartas (baralho) e baralhar inicialmente os valores dessa lista. exemplo : https://www.portugal-a-programar.pt/topic/64182-ajuda-em-programa/?do=findComment?comment=539666 IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
RafaelSobral Posted February 27, 2014 at 08:07 PM Author Report #546977 Posted February 27, 2014 at 08:07 PM existem vários tópicos no fórum sobre este assunto. a resolução deste problema não passa pela geração de números aleatórios mas sim manter uma lista de cartas (baralho) e baralhar inicialmente os valores dessa lista. exemplo : http://www.portugal-a-programar.pt/topic/64182-ajuda-em-programa/#entry539666 Desde já obrigado pela resposta rápida . Estive a ler o código que mandas-te mas não o entendi muito bem .. o que quiseste dizer foi que devo ter logo um array com as 52 cartas dentro dele, e de seguida ele deve baralhar as posições dos vetores como por exemplo v[2] por v[10] , o v[5] por v[3] , etc .. ?
HappyHippyHippo Posted February 27, 2014 at 08:11 PM Report #546978 Posted February 27, 2014 at 08:11 PM (edited) Desde já obrigado pela resposta rápida . Estive a ler o código que mandas-te mas não o entendi muito bem .. o que quiseste dizer foi que devo ter logo um array com as 52 cartas dentro dele, e de seguida ele deve baralhar as posições dos vetores como por exemplo v[2] por v[10] , o v[5] por v[3] , etc .. ? é isso que o código apresentado faz, somente com um código extra de separar para 4 mãos (jogadores) Edited February 27, 2014 at 08:11 PM by HappyHippyHippo IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
RafaelSobral Posted February 27, 2014 at 08:19 PM Author Report #546979 Posted February 27, 2014 at 08:19 PM (edited) é isso que o código apresentado faz, somente com um código extra de separar para 4 mãos (jogadores) Estou a entender, porem eu não preciso que ele separe em 4 mãos visto que é só 1 jogador a jogar.. só precisava que ele baralhasse as posições do array .. Suponho que precise também de um for para ir correndo o vetor e ir baralhando as posições à medida que ele corre, mas não faço ideia de como fazer isso . Edited February 27, 2014 at 08:19 PM by RafaelSobral
Rui Carlos Posted February 27, 2014 at 08:33 PM Report #546980 Posted February 27, 2014 at 08:33 PM Como já te foi sugerido, começa por inicializar o array baralho que representa o baralho com os 52 números ({1,1,1,1,2,2,2,2,3,...,12,13,13,13,13}). Aqui estás basicamente a criar o baralho de cartas. Depois fazes um ciclo em que a cada iteração geras dois números, i e j, entre 0 e 51, e trocas os elementos baralho e baralho[j] de posição. Repetes este ciclo aí umas 50 vezes. Aqui vais baralhar as cartas. Este último passo pode ser feito de várias formas diferentes (no tópico que o HHH indicou, ele tem lá um código ligeiramente diferente). Mas o essencial é ires trocando cartas de forma mais ou menos aleatórias. Rui Carlos Gonçalves
RafaelSobral Posted February 27, 2014 at 08:46 PM Author Report #546985 Posted February 27, 2014 at 08:46 PM Como já te foi sugerido, começa por inicializar o array baralho que representa o baralho com os 52 números ({1,1,1,1,2,2,2,2,3,...,12,13,13,13,13}). Aqui estás basicamente a criar o baralho de cartas. Depois fazes um ciclo em que a cada iteração geras dois números, i e j, entre 0 e 51, e trocas os elementos baralho e baralho[j] de posição. Repetes este ciclo aí umas 50 vezes. Aqui vais baralhar as cartas. Este último passo pode ser feito de várias formas diferentes (no tópico que o HHH indicou, ele tem lá um código ligeiramente diferente). Mas o essencial é ires trocando cartas de forma mais ou menos aleatórias. int gerar_carta_aleatoria() { #include <time.h> #define MAX 52 srand(time(NULL)); int v[MAX],i, j, numeros; for(i=1;i<50;i++) { numeros = rand() % 53 + 1; v[i]=numeros; } for(i=1;i<50;i++) { printf("%d ",v[i]); } printf("\n"); for(i=1;i<50;i++) for(j=i;j<MAX;j++) { if(v[i]==v[j]) { scanf("%d",&v[i]); } } } system("pause"); } Mais ou menos isto ?
Rui Carlos Posted February 27, 2014 at 08:54 PM Report #546986 Posted February 27, 2014 at 08:54 PM Em que parte estás a inicializar o array com {1,1,1,1,2,2,2,2,3,...,12,13,13,13,13}? Em que parte estás a gerar dois números aleatórios para trocar de posição dois elementos do array? (Já agora, a função devia chamar-se gerar_baralho_aleatorio, ou algo parecido. Adicionalmente, os #includes e os #defines devem aparecer no início do ficheiro, e não dentro de uma função.) Rui Carlos Gonçalves
RafaelSobral Posted February 27, 2014 at 09:12 PM Author Report #546988 Posted February 27, 2014 at 09:12 PM (edited) Em que parte estás a inicializar o array com {1,1,1,1,2,2,2,2,3,...,12,13,13,13,13}? Em que parte estás a gerar dois números aleatórios para trocar de posição dois elementos do array? (Já agora, a função devia chamar-se gerar_baralho_aleatorio, ou algo parecido. Adicionalmente, os #includes e os #defines devem aparecer no início do ficheiro, e não dentro de uma função.) #include <stdio.h> #include <stdlib.h> #include <time.h> int gerar_baralho_aleatoria() { int v[52]={1, 1 , 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13}; int i, j; for(i=0;i<50;i++) { //Campo para trocar os elementos do baralho[i] e baralho[j] } system("pause"); } Penso que agora já está melhor, mas como gero agora as posições para trocar dois elementos ? Edited February 27, 2014 at 09:21 PM by thoga31 GeSHi
Rui Carlos Posted February 27, 2014 at 09:20 PM Report #546992 Posted February 27, 2014 at 09:20 PM Em pseudo-código, naquele comentário precisas de algo como: // gerar dois números aleatórios i = geraNúmeroAleatório(0, 51) // o valor gerado tem que estar no intervalo [0,51] j = geraNúmeroAleatório(0, 51) // o valor gerado tem que estar no intervalo [0,51] // trocar posições do baralho (array) tmp = baralho[i] baralho[i] = baralho[j] baralho[j] = tmp Essencialmente precisas agora de trocar o geraNúmeroAleatório(0, 51) pelo código que gera um número aleatório entre 0 e 51. E precisas de substituir a variável baralho pela variável que estás a usar no teu código. Depois de teres algo deste género a funcionar, poderás melhorá-lo usando uma função (tipicamente chamada de swap) para fazer a troca dos valores do array (vê este link). Rui Carlos Gonçalves
RafaelSobral Posted February 27, 2014 at 09:42 PM Author Report #546998 Posted February 27, 2014 at 09:42 PM Em pseudo-código, naquele comentário precisas de algo como: // gerar dois números aleatórios i = geraNúmeroAleatório(0, 51) // o valor gerado tem que estar no intervalo [0,51] j = geraNúmeroAleatório(0, 51) // o valor gerado tem que estar no intervalo [0,51] // trocar posições do baralho (array) tmp = baralho[i] baralho[i] = baralho[j] baralho[j] = tmp Essencialmente precisas agora de trocar o geraNúmeroAleatório(0, 51) pelo código que gera um número aleatório entre 0 e 51. E precisas de substituir a variável baralho pela variável que estás a usar no teu código. Depois de teres algo deste género a funcionar, poderás melhorá-lo usando uma função (tipicamente chamada de swap) para fazer a troca dos valores do array (vê este link). Pois são essas coisas que ainda não aprendi, nem até mesmo o tmp que usas no código , nunca o usei. Neste momento e com a tua ajuda tenho a função assim , mas não me está a aparecer correto quando a executo . #include <stdio.h> #include <stdlib.h> #include <time.h> int gerar_baralho_aleatoria() { int v[52]={1, 1 , 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13}; int i, j, tmp; for(i=0;i<50;i++) { srand(time(NULL)); i = rand() % 51 + 0; j = rand() & 51 + 0; tmp = v[i]; v[i] = v[j]; v[j] = tmp; } system("pause"); }
HappyHippyHippo Posted February 27, 2014 at 10:02 PM Report #547000 Posted February 27, 2014 at 10:02 PM Estou a entender, porem eu não preciso que ele separe em 4 mãos visto que é só 1 jogador a jogar.. só precisava que ele baralhasse as posições do array .. Suponho que precise também de um for para ir correndo o vetor e ir baralhando as posições à medida que ele corre, mas não faço ideia de como fazer isso . ignorar uma resposta só porque tem um pouco de código a mais não é uma boa opção ... porque razão simplesmente não retiras o que não te interessa ? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define DECK_NSUITS 4 #define DECK_NVALUES 13 #define DECK_SIZE (DECK_NSUITS * DECK_NVALUES) #define card_suit(card) ((card >> 8) & 0xff) #define card_value(card) (card & 0xff) #define card_compose(suit, value) (((suit & 0xff) << 8) | (value & 0xff)) #define card_swap(card1, card2) do { if (*card1 != *card2) { *card1 ^= *card2; *card2 ^= *card1; *card1 ^= *card2; } } while (0) int card_compare(const void * a, const void * b) { return * (short *) a - * (short *) b; } void deck_build(short * deck) { int suit = 0, value = 0; for (suit = 1; suit <= DECK_NSUITS; suit++) for (value = 1; value <= DECK_NVALUES; value++) deck[(suit - 1) * DECK_NVALUES + value - 1] = card_compose(suit, value); } void card_output(short card) { switch (card_suit(card)) { case 1 : printf("%c", 3); break; case 2 : printf("%c", 4); break; case 3 : printf("%c", 5); break; case 4 : printf("%c", 6); break; } switch (card_value(card)) { case 1 : printf("A "); break; case 11 : printf("Q "); break; case 12 : printf("J "); break; case 13 : printf("K "); break; default : printf("%-2d", card_value(card)); } } void deck_shuffle(short * deck) { int i = 0, r = 0; for (i = 0; i < DECK_SIZE; i++) { r = rand() % (DECK_SIZE - i); card_swap(&deck[r], &deck[i + r]); } } int main(int argc, char ** argv) { short deck[DECK_SIZE]; int i; /* start randon number genereation */ srand(time(NULL)); /* deck build and shuffle */ deck_build(deck); deck_shuffle(deck); /* deck presentation */ for (i = 0; i < DECK_SIZE; i++) { printf(" >"); card_output(deck[i]); } printf("\n"); return 0; } IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
Rui Carlos Posted February 27, 2014 at 10:15 PM Report #547006 Posted February 27, 2014 at 10:15 PM Pois são essas coisas que ainda não aprendi, nem até mesmo o tmp que usas no código , nunca o usei. Neste momento e com a tua ajuda tenho a função assim , mas não me está a aparecer correto quando a executo . #include <stdio.h> #include <stdlib.h> #include <time.h> int gerar_baralho_aleatoria() { int v[52]={1, 1 , 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13}; int i, j, tmp; for(i=0;i<50;i++) { srand(time(NULL)); i = rand() % 51 + 0; j = rand() & 51 + 0; tmp = v[i]; v[i] = v[j]; v[j] = tmp; } system("pause"); } O que é que não está a aparecer direito? 🙂 O srand só deve ser executado uma vez. Deverá estar fora do ciclo, ou até na main. rand() % 51 gera-te um número entre 0 e 50 (e não 51). Isto não é propriamente um erro, contudo. Tens um & em vez de um %. Aquele system("pause"); não devia estar ali. Adicionalmente, o array v não sai da função (dizes que a função devolve um int mas não tens nenhum return). Ou seja, estás a criar um baralho que depois não vais conseguir usar em lado nenhum. Assumindo que não sabes usar memória dinâmica, muda a função para algo como: void baralhar(int v[]) { int i, j; // ciclo for para baralhar } int main(void) { // ... int v[52] = {1,1,1,1, ...}; // ... baralhar(v); // ... } HHH, não me leves a mal, mas acho que a tua solução não é apropriada para quem está a começar a aprender C. E o mais provável é alguém nessa situação ficar-se logo pelas macros que usas. Rui Carlos Gonçalves
HappyHippyHippo Posted February 27, 2014 at 10:50 PM Report #547014 Posted February 27, 2014 at 10:50 PM (edited) HHH, não me leves a mal claro que não levo a mal. o uso deste método foi devido ao post originário que requeria a ordenação das cartas, algo que com o método que apresentei é feito facilmente com um qsort e uma mini-função de comparação (parâmetro do qsort). no entanto, o objectivo da apresentação do código seria abrir os horizontes do @RafaelSobral demonstrando que a solução passaria pela geração do baralho. ------------------------------------------------------------------------------------- já que o código anterior pode ser complicado ... este deverá ser mais simples de "ler" #include <stdio.h> #include <stdlib.h> #include <time.h> typedef enum { Espadas = 1, Paus, Copas, Ouros } CartaNaipe; typedef enum { As = 1, Duque, Terno, Quadra, Quina, Sena, Bisca, Oito, Nove, Dez, Valete, Rainha, Rei } CartaValor; #define TAMANHO_BARALHO (Ouros * Rei) struct Carta { CartaValor valor; CartaNaipe naipe; }; void gerar_baralho(struct Carta baralho[]) { int naipe, valor; for(naipe = Espadas; naipe <= Ouros ; ++naipe) { for(valor = As; valor <= Rei ; ++valor) { baralho[(naipe - 1) * Rei + (valor - 1)].naipe = naipe; baralho[(naipe - 1) * Rei + (valor - 1)].valor = valor; } } } void baralhar_cartas(struct Carta cartas[], int quantidade) { int i = 0, r = 0; struct Carta carta; for (i = 0; i < quantidade; i++) { r = rand() % (quantidade - i); carta = cartas[r]; cartas[r] = cartas[i + r]; cartas[i + r] = carta; } } void imprimir_carta(struct Carta carta) { switch (carta.naipe) { #ifdef WIN32 case Espadas : printf("%c", 3); break; case Paus : printf("%c", 4); break; case Copas : printf("%c", 5); break; case Ouros : printf("%c", 6); break; #else case Espadas : printf("E"); break; case Paus : printf("P"); break; case Copas : printf("C"); break; case Ouros : printf("O"); break; #endif } switch (carta.valor) { case 1 : printf("A "); break; case 11 : printf("Q "); break; case 12 : printf("J "); break; case 13 : printf("K "); break; default : printf("%-2d", carta.valor); } } void imprimir_cartas(struct Carta cartas[], int quantidade) { int i = 0; for (i = 0; i < quantidade; ++i) { printf("carta %-2d : ", i); imprimir_carta(cartas[i]); printf("\n"); } } int main(void) { struct Carta baralho[TAMANHO_BARALHO]; srand(time(NULL)); gerar_baralho(baralho); imprimir_cartas(baralho, TAMANHO_BARALHO); printf("----\n"); baralhar_cartas(baralho, TAMANHO_BARALHO); imprimir_cartas(baralho, TAMANHO_BARALHO); return 0; } Edited February 27, 2014 at 11:17 PM by HappyHippyHippo IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
RafaelSobral Posted March 4, 2014 at 05:40 PM Author Report #547511 Posted March 4, 2014 at 05:40 PM Obrigado ao @HappyHippyHippo e ao @Rui Carlos pela ajuda , não consegui responder mais cedo mas agora tive tempo e não me esqueci de vir agradecer, já consegui resolver o problema graça aos códigos que postaram aqui . Agora tenho outra dúvida mas não é sobre o mesmo assunto.. Pretendia "fazer" um histórico das vezes que o utilizador ganhou e perdeu , por exemplo : Ronda 1 - Vitória Ronda 2 - Derrota Ronda 3 - Derrota ... Cada vez que uma ronda acabava , a lista era actualizada automaticamente com o respetivo resultado .. Alguma "ideia" , sugestão que possam dar por onde deva começar ? É que nunca fiz nada do género . Cumprimentos.
HappyHippyHippo Posted March 4, 2014 at 06:10 PM Report #547513 Posted March 4, 2014 at 06:10 PM o que pretendes em termos de persistência ? IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
RafaelSobral Posted March 4, 2014 at 06:23 PM Author Report #547516 Posted March 4, 2014 at 06:23 PM Não percebi muito bem a pergunta mas se estás a referir-te em relação às vezes que a mensagem é mostrada , é consoante as "partidas" que o jogador fizer , se o jogador jogar 5 jogos, e depois ele for ao histórico do programa ver as derrotas e vitórias, têm de estar lá 5 mensagens . Não sei se era a isso que te estavas a referir ..
HappyHippyHippo Posted March 4, 2014 at 06:31 PM Report #547518 Posted March 4, 2014 at 06:31 PM persistência : per·sis·tên·ci·a substantivo feminino 1. Acto de persistir. 2. Qualidade de persistente. 3. Perseverança, constância, firmeza. "persistência", in Dicionário Priberam da Língua Portuguesa [em linha], 2008-2013, http://www.priberam.pt/dlpo/persist%C3%AAncia [consultado em 04-03-2014]. queres que a informação não desapareça quando fechas a aplicação ? IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
RafaelSobral Posted March 4, 2014 at 06:34 PM Author Report #547520 Posted March 4, 2014 at 06:34 PM Quando a aplicação é fechada a informação pode desaparecer , ou seja, o histórico que aparece de jogos, é só os jogos que ocorrem desde a altura que o utilizador abriu o programa até a altura em que ele está a ver . Os jogos que ele fez em outras alturas / antes de ter aberto a aplicação não contam neste caso.
HappyHippyHippo Posted March 4, 2014 at 06:43 PM Report #547522 Posted March 4, 2014 at 06:43 PM basta um array IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now