Juego de BlackJack en C

Iniciado por AlbertoBSD, 24 Abril 2016, 15:58 PM

0 Miembros y 1 Visitante están viendo este tema.

AlbertoBSD

La publicación original la tengo en mi pagina:

http://codigoenc.com/post/33/Juego_de_BlackJack_en_C_paso_a_paso

El juego se puede optimazar si. Se puede perzonalizar si, actualmente juega en automatico.




En este Topic vamos a hacer un juego de blackjack en C, lo vamos a tratar de ser lo mas sencillo posible explicando función por función.


Primero definiremos un Maso de cartas esto es 13 cartas desde el A hasta el K

char *mazo = "A234567890JQK";

Para hacer este juego lo mas escalable posible generaremos dinámicamente un mazo de juego de N bajaras, para eso tenemos la siguiente función:

char *crear_baraja(int n) {
int i = 0,j;
int offset = 0;
char *cartas;
cartas = calloc(sizeof(char)*52+1,n);
while(i < n) {
j = 0;
while(j < 4) {
memcpy(cartas+offset,mazo,13);
offset+=13;
j++;
}
i++;
}
cartas[offset] = '\0'; //Esta instrucción es innecesaria debido a la función calloc pero lo dejamos para aclarar que nuestra condicion de paro es el caracter nulo al final de la cadena
return cartas;
}


La funcion anterior solo nos devuelve un puntero con la memoria asignada mediante Malloc con la cantidad de bajaras que le pedimos.

Ahora si mandamos a llamar esta funcion y mostramos la cadena veremos un mazo ordenado obvio por la forma que se construyo
En este ejemplo usaremos 2 barajas pero tengan en cuenta que puede ser hasta 1000 barajas siempre y cuando este disponible
baraja = crear_baraja(2);
printf("Baraja:\n%s\n",baraja);

salida:

Baraja:
A234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQK


Ahora si bien tenemos que barajar la bajara.

char *barajar(char *baraja) {
int len = strlen(baraja);
char *temp = calloc(len+1,1);
int r;
int i = 0;
/*
Poner su propia funcion random disponible en su sistema
En freeBSD prefiero usar arc4rand
*/
while(i < len) {
r = arc4random_uniform(len);
if(baraja[r] != 0) {
temp[i] = baraja[r];
baraja[r] = 0;
i++;
}
}
free(baraja);
return temp;
}


Esta función nos devuelve un nuevo puntero con la bajara anterior pero ahora en desorden

Mostramos la salida:
baraja = barajar(baraja);
printf("Baraja:\n%s\n",baraja);

Baraja:
9KJ4067Q6A9068Q5A08J3Q3QJ7Q3AK38A6J453762KK0852KA4Q52548753Q234A42K2Q3J7KJ090A62A5J0674KJ702689799989584


Depues de construir las funcoines de evaluar carta y evaluar jugador podemos terminar el juego

/*
Twitter @albertobsd
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*
Maso basico de Cartas para su salida en pantalla.
el 0 vale representa a la carta 10
*/
typedef struct jugador_struct {
int continuar;
int valor;
int offset;
char mano[6];
}jugador;

char *mazo = "A234567890JQK";

char *crear_baraja(int n);
char *barajar(char *baraja);
int juego(char *bajara,int *offset,int m);
void evaluar_jugador(jugador *j);
int evaluar_carta(char c);
void debug(char *p,int l);

int main() {
char *baraja;
int offset = 0;
printf("Juego de BlackJack\n");
printf("Creando bajara...\n");
baraja = crear_baraja(2);
printf("Baraja:\n%s\n",baraja);
printf("Revolver bajara...\n");
baraja = barajar(baraja);
printf("Baraja:\n%s\n",baraja);
juego(baraja,&offset,6); // La casa juega contra 6 Jugadores Solo una ronda, si queremos mas rondas tendremos que agregarlo en un ciclo y controlar el numero de cartas restantes en la baraja
free(baraja);
}

char *crear_baraja(int n) {
int i = 0,j;
int offset = 0;
char *cartas;
cartas = calloc(sizeof(char)*52+1,n);
while(i < n) {
j = 0;
while(j < 4) {
memcpy(cartas+offset,mazo,13);
offset+=13;
j++;
}
i++;
}
cartas[offset] = '\0'; //Esta instruccion es incesaria debido a la funcion calloc
return cartas;
}

char *barajar(char *baraja) {
int len = strlen(baraja);
char *temp = calloc(len+1,1);
int r;
int i = 0;
/*
Poner su propia funcion random disponible en su sistema
En freeBSD prefiero usar arc4random_uniform
*/
while(i < len) {
r = arc4random_uniform(len);
if(baraja[r] != 0) {
temp[i] = baraja[r];
baraja[r] = 0;
i++;
}
}
free(baraja);
return temp;
}

int juego(char *bajara,int *offset,int m) {
int len = strlen(bajara);
int i = offset[0],j = 0,k = 0, n = m+1;
jugador **jugadores;
jugadores = calloc(sizeof(jugador*),n);
//memset(jugadores,0,sizeof(jugador)*2);
/* Generamos n jugadores (m jugadores elegidos por el usuario + la casa jugador 0) */
/* Repartimos Cartas a todos los jugadores*/
while(k < n) {
jugadores[k] = calloc(sizeof(jugador),1);
printf("Memoria asignada para el jugador %i @ 0x%X [%i bytes]\n",k,jugadores[k],sizeof(jugador));
k++;
}
while( j < 2 ) {
k = 0;
while(k < n) {
jugadores[k]->mano[j] = bajara[i];
jugadores[k]->offset++;
i++;
k++;
}
j++;
}
/* Funcion de depuracion
debug(jugadores[0],16);
debug(jugadores[1],16);
*/
/*
Aqui se ve la mano de cada jugador en el proximo printf dentro del ciclo solo es para fines didacticos
posteriormente solo se evaluan las manos;
*/
j = 0;
while( j < n ) {
printf("Jugador: %i\ncartas %s\n",j,jugadores[j]->mano);
evaluar_jugador(jugadores[j]);
printf("Valor actual: %i\n",jugadores[j]->valor);
j++;
}
/*
Despues de repartir las cartas los jugadores juegan y la casa se destapa al final
*/
j = 1;
while( j < n ) {
while(jugadores[j]->continuar) {
jugadores[j]->mano[jugadores[j]->offset] = bajara[i];
//printf("Jugador: %i\ncartas %s\n",j,jugadores[j]->mano);
jugadores[j]->offset++;
evaluar_jugador(jugadores[j]);
i++;
}
j++;
}
/*
Ahora juega la casa.
*/
while(jugadores[0]->continuar) {
jugadores[0]->mano[jugadores[0]->offset] = bajara[i];
jugadores[0]->offset++;
evaluar_jugador(jugadores[0]);
i++;
}
/* Mostramos a todos los resultados*/
j = 1;
while( j < n ) {
printf("Jugador: %i\ncartas %s\n",j,jugadores[j]->mano);
printf("Valor actual: %i\n",jugadores[j]->valor);
if(jugadores[j]->valor > 21) {
printf("Perdio\n");
}
else {
if(jugadores[j]->valor == 21) {
printf("Gano BlackJack\n");
}
else {
if(jugadores[0]->valor > 21) {
printf("Gano\n");
}
else {
if(jugadores[j]->valor > jugadores[0]->valor) {
printf("Gano\n");
}
else {
printf("Perdio\n");
}
}
}
}
j++;
}

/*
Liberamos memoria de los jugadores
*/
while( j < n ) {
free(jugadores[j]);
j++;
}
/*
Retornamos el valor actaul del offset mediante la direccion de memoria del argumento.
y Retornamos el jugador ganador;
*/
offset[0] = i;
return 1;
}

void evaluar_jugador(jugador *j) {
int i = 0;
char v;
j->valor = 0;
while(j->mano[i] != 0) {
v = evaluar_carta(j->mano[i]);
if(v == 1) {
if((j->valor + 11) <= 21 ) {
j->valor += 11;
}
else {
j->valor += v;
}
}
else {
j->valor += v;
}
if(j->valor <= 16) {
j->continuar = 1;
}
else {
j->continuar = 0;
}
i++;
}
}

int evaluar_carta(char c) {
int r = 0;
switch(c) {
case 'A':
r = 1;
break;
case 'K':
case 'Q':
case 'J':
case '0':
r = 10;
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
r = c - '0';
break;
}
return r;
}

void debug(char *p,int l) {
int i = 0;
printf("0x%x\n",p);
while(i < l) {
printf("%.2x",p[i]);
i++;
}
printf("\n");
}


Salida completa

Juego de BlackJack
Creando bajara...
Baraja:
A234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQK
Revolver bajara...
Baraja:
57A6627296K55Q4Q0073Q2K4J6J297A962AK40350J87754369JJ3JJ7AJQ20828A9A5K0528K8549K9Q0AKK69604487Q38843Q33AQ
Memoria asignada para el jugador 0 @ 0x2880D040 [20 bytes]
Memoria asignada para el jugador 1 @ 0x2880D060 [20 bytes]
Memoria asignada para el jugador 2 @ 0x2880D080 [20 bytes]
Memoria asignada para el jugador 3 @ 0x2880D0A0 [20 bytes]
Memoria asignada para el jugador 4 @ 0x2880D0C0 [20 bytes]
Memoria asignada para el jugador 5 @ 0x2880D0E0 [20 bytes]
Memoria asignada para el jugador 6 @ 0x2880D100 [20 bytes]
Jugador: 0
cartas 52
Valor actual: 7
Jugador: 1
cartas 79
Valor actual: 16
Jugador: 2
cartas A6
Valor actual: 17
Jugador: 3
cartas 6K
Valor actual: 16
Jugador: 4
cartas 65
Valor actual: 11
Jugador: 5
cartas 25
Valor actual: 7
Jugador: 6
cartas 7Q
Valor actual: 17
Jugador: 1
cartas 794
Valor actual: 20
Gano
Jugador: 2
cartas A6
Valor actual: 17
Perdio
Jugador: 3
cartas 6KQ
Valor actual: 26
Perdio
Jugador: 4
cartas 650
Valor actual: 21
Gano BlackJack
Jugador: 5
cartas 250
Valor actual: 17
Perdio
Jugador: 6
cartas 7Q
Valor actual: 17
Perdio
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

AlbertoBSD

Original:
http://codigoenc.com/post/33/Juego_de_BlackJack_en_C_paso_a_paso/#msg-41

Otra codigo que podemos aplicar es el estar contando cartas, si alguno ha visto la pelicula de 21 en donde el protagonista es un genio con los numeros y es capas de llevar el conteo de cartas de forma facil, pues el contar cartas para un progragrama de computadoras bien diseñado es simple:

La siguiente funcion asigna valores a las cartas en modo contador para las altas un valor de -1 y para las chicas un valor de +1. lo que quiere decir es que cuando salgan muchas cartas chica, el contador tendra un valor alto, y es cuando mas probabilidades tenemos de que la próxima carta sea una carta de 10 o J,Q,K y  As.

Y dependiendo de la mano que tengamos es posible pedir mas cartas o plantarnos.

int valor_conteo(char c) {
int r = 0;
switch(c) {
case 'A':
case 'K':
case 'Q':
case 'J':
case '0':
r = -1;
break;
case '7':
case '8':
case '9':
r = 0;
break;
case '2':
case '3':
case '4':
case '5':
case '6':
r =1;
break;
}
return r;
}


Ahora para mostrar que funciona vamos a contar toda la baraja y ver la salida

baraja = barajar_baraja(baraja);
len = strlen(baraja);
printf("%s\n",baraja);
i = 0;
while(i < len) {
conteo += valor_conteo(baraja[i]);
printf("%i\n",conteo);
i++;
}


Salida

Creando barja:
A234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQKA234567890JQK
Barajando:
4Q907566846A3J8Q6Q287270A388J2J9KK0J323QK390K98A6428539804723J74A954862KK5JAQ9Q80066233067347AJQ0708K56A49A9686322Q63QJA48AJ5795Q7903JQ87J9J44596K36J06Q3A7794562732AK652AJ6J005QQ0A024A62A8K0409298A62KJ754Q553Q8A59278QK745342Q6782588Q9897K7A9J40JA9407K05K087A623K542Q5K92A3K9K57338KQJQ5K6K3AJJQ35494J20J4Q5K47A0KJ
Conteo:
1
0
0
-1
-1
0
1
2
2
3
4
3
4
3
3
2
3
2
3
3
3
4
4
3
2
3
3
3
2
3
2
2
1
0
-1
-2
-1
0
1
0
-1
0
0
-1
-2
-2
-2
-3
-2
-1
0
0
1
2
2
2
1
2
2
3
4
3
3
4
3
3
4
5
5
6
7
6
5
6
5
4
3
3
2
2
1
0
1
2
3
4
5
4
5
5
6
7
7
6
5
4
3
3
2
2
1
2
3
2
3
3
2
2
3
3
4
5
6
7
6
7
8
7
6
5
6
6
5
4
5
5
5
6
5
5
5
4
5
4
3
3
3
2
2
1
2
3
4
4
5
4
5
6
5
4
5
4
5
4
4
4
4
5
6
7
8
8
9
10
9
8
9
10
11
10
9
10
9
8
7
8
7
6
5
4
3
4
5
4
5
6
5
5
4
3
4
3
3
4
4
4
3
4
5
4
3
3
4
5
4
5
6
7
6
6
5
6
6
7
7
7
6
5
5
6
7
8
9
10
9
10
10
10
11
12
12
12
11
11
11
11
11
10
10
9
9
8
9
8
7
6
6
7
6
6
5
4
5
4
3
3
3
2
3
4
5
4
5
6
7
6
7
6
6
7
6
7
6
6
5
6
6
7
8
8
7
6
5
4
5
4
5
4
5
4
3
2
1
2
3
4
4
5
4
5
4
3
4
3
4
3
4
4
3
2
1
0


En teoria cuando los numeros estan sobre 10 tenemos mas chance de recibir una carta alta, asi que si en nuestra mano tenesmo 10 u 11 podremos ganar, en caso de tener mas de 11 nos arriesgamos a perder, igualemente si tenemos 2 10, podriamos hacer split

El ejemplo anterior se uso con 6 barajas, lo he probado con 1000 barajas y los contadores son mas variables que van desde los -130 hasta los 130
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW