Jump to content

Jogo do BlackJack/21


Recommended Posts

Posted

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.

Posted

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
Posted

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 .. ?

Posted (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 by HappyHippyHippo
IRC : sim, é algo que ainda existe >> #p@p
Posted (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 by RafaelSobral
Posted

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.

Posted

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 ?

Posted

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.)

Posted (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 by thoga31
GeSHi
Posted

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).

Posted

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");
}
Posted

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
Posted

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.

Posted (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 by HappyHippyHippo
IRC : sim, é algo que ainda existe >> #p@p
Posted

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.

Posted

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 ..

Posted

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
Posted

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.

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.