Hoy te mostraré la solución a un ejercicio propuesto en C que trata sobre hacer el juego de Arqueros en el bosque.
El juego consiste de un bosque representado mediante una cuadrícula, como el que se presenta a continuación (la vista es aérea):
Cuadrícula de bosque para arqueros – Juego programado en C
Donde X representa un árbol. El objetivo del juego consiste en que 2 jugadores (arqueros) ingresan al bosque por extremos opuestos (J1 en 9-A y J2 en 1-I) y cada uno debe de intentar eliminar al otro.
Para ello en cada turno un arquero podrá elegir entre moverse un lugar o disparar un flechazo. Los flechazos se mueven en línea recta, una distancia máxima de 5 metros (asuma cada celda 1 metro).
Por otro lado un jugador no puede moverse a una celda donde hay un árbol y las flechas no pueden traspasarlos. Al recibir un flechazo el jugador pierde el round, las partidas se componen de 3 round y las gana el que gane 2 de ellos.
Veamos entonces cómo hacer este juego en ANSI C, C, C 99 o como le quieras llamar. Obviamente es compatible con C++.
Funcionamiento general del juego
Todo el escenario del juego (el bosque) será una matriz cuadrada. Vamos a tener métodos que recibirán el bosque como argumento.
Las funciones que tendremos son varias, entre ellas las que limpian el bosque, colocan los árboles (generando coordenadas aleatorias) y colocan los jugadores.
Igualmente vamos a tener algunas variables que llevarán la ubicación de los jugadores así como los flechazos recibidos. Lo más interesante será simular el disparo de la flecha y comprobar si no colisiona con un árbol, o si termina su recorrido sin impactar.
Preparando el bosque
Al inicio de todo debemos limpiar el bosque y colocar los árboles así:
voidlimpiar_bosque(char bosque[medidaGlobalBosque][medidaGlobalBosque]){for(int y =0; y < medidaGlobalBosque; y++){for(int x =0; x < medidaGlobalBosque; x++){
bosque[y][x]= ESPACIO_VACIO;}}}voidcolocar_arboles_en_bosque(char bosque[medidaGlobalBosque][medidaGlobalBosque]){int contador =0;while(contador < medidaGlobalBosque){int x =aleatorio_en_rango(0, medidaGlobalBosque -1);int y =aleatorio_en_rango(0, medidaGlobalBosque -1);// Colocar árboles solo si no hay nada (en especial no debemos colocarlos en donde haya jugadores)if(bosque[y][x]== ESPACIO_VACIO){
bosque[y][x]= ARBOL;
contador++;}}}
Como puedes observar, se coloca la misma cantidad de árboles que la medida del tablero. Todos son colocados de manera aleatoria y en espacios vacíos.
Por cierto, tenemos una función que va a imprimir el bosque, imprimiendo encabezados, letras, números, etcétera:
voidimprimir_bosque(char bosque[medidaGlobalBosque][medidaGlobalBosque]){int contador =0;// Un separadorprintf("\n\n");while(contador < medidaGlobalBosque){printf("_____");
contador++;}printf("\n");// Letrasprintf("| ");char c ='A';
contador =0;while(contador < medidaGlobalBosque){printf("| %c ", c);
c++;
contador++;}printf("|\n");for(int y =0; y < medidaGlobalBosque; y++){printf("| %d |", y +1);for(int x =0; x < medidaGlobalBosque; x++){printf(" %c |", bosque[y][x]);}printf("\n");}}
Puedes ver la salida de esa función en la imagen que está al inicio de este post.
Solicitando datos
Solicitar tamaño de tablero, jugador y movimiento – Arqueros en el bosque con C
Veamos las funciones que van a preguntar el tamaño del tablero, solicitar direcciones, dar a elegir entre disparar o moverse, etcétera.
Para solicitar la dirección hacia donde se mueve el personaje usamos un ciclo while hasta que la dirección sea correcta. Este patrón se va a repetir en los siguientes métodos:
charsolicitarMovimientoJugador(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador){char direccion = DIRECCION_IZQUIERDA;while(1){printf("%c - Arriba\n%c - Abajo\n%c - Derecha\n%c - Izquierda\nJugador %c. Ingrese la direccion para moverse: ",
DIRECCION_ARRIBA, DIRECCION_ABAJO, DIRECCION_DERECHA, DIRECCION_IZQUIERDA, jugador);scanf("%c",&direccion);consumir_nueva_linea();if(jugador_puede_moverse(bosque, jugador, direccion)){return direccion;}else{printf("No se puede mover hacia esa direccion. Intente de nuevo\n");}}}
Por ejemplo, para solicitar la dirección del disparo:
charsolicitarDireccionDisparo(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador){char direccion = DIRECCION_IZQUIERDA;while(1){printf("%c - Arriba\n%c - Abajo\n%c - Derecha\n%c - Izquierda\nJugador %c. Ingrese la direccion para disparar: ",
DIRECCION_ARRIBA, DIRECCION_ABAJO, DIRECCION_DERECHA, DIRECCION_IZQUIERDA, jugador);scanf("%c",&direccion);consumir_nueva_linea();if(esDireccionValida(direccion)){return direccion;}else{printf("No puede disparar en esa direccion. Intente de nuevo\n");}}}
La medida del bosque:
intsolicitarMedida(){int medida;while(1){printf("Ingrese la medida del bosque. Puede ser de 5, 7 o 9: ");scanf("%d",&medida);consumir_nueva_linea();if(medida ==5|| medida ==7|| medida ==9){return medida;}else{printf("La medida no es correcta\n");}}}
Por cierto, como puedes ver la medida debe ser de 5, 7 o 9. Técnicamente puede ser de cualquier longitud, ya solo haría falta ajustar las letras para que cuando se llegue a la Z se reinicie o algo así.
Finalmente veamos la que pregunta cuál arquero inicia el juego y también la que pregunta si el jugador desea disparar o moverse.
Iniciar nuevo round cuando el flechazo es acertado
Cada que haya una nueva partida o un nuevo round vamos a reiniciar ciertas variables. Por ejemplo, cuando se inicia un nuevo round, los jugadores se vuelven a colocar en las posiciones iniciales y los árboles se colocan aleatoriamente, pero los contadores de flechazos recibidos no se reinician.
En cambio, cuando se inicia una nueva partida se reinician los contadores de flechazos recibidos.
Mover jugador
Mover jugador en el bosque – Juego programado en C
Veamos uno de las dos funciones más importantes del juego arqueros en el bosque programado en C. En este caso para mover al jugador tenemos dos funciones: una que verifica si puede moverse y otra que mueve al jugador.
Recuerda que en este caso tenemos las coordenadas de manera global en variables separadas, por eso es que las modificamos:
intjugador_puede_moverse(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador,char direccion){int x, y;if(jugador == ARQUERO_J1){
x = coordenada_x_jugador_1;
y = coordenada_y_jugador_1;}else{
x = coordenada_x_jugador_2;
y = coordenada_y_jugador_2;}if(direccion == DIRECCION_ABAJO){
y++;}elseif(direccion == DIRECCION_ARRIBA){
y--;}elseif(direccion == DIRECCION_DERECHA){
x++;}elseif(direccion == DIRECCION_IZQUIERDA){
x--;}else{// Si no es ninguna dirección válida, regresamos falsereturn0;}// Luego de modificar las coordenadas, vemos si son válidas. Comprobamos si están dentro del tableroif(x <0|| x >= medidaGlobalBosque || y <0|| y >= medidaGlobalBosque){printf("Posicion fuera del tablero\n");return0;}// Y comprobamos si no es un árbol u otro jugadorif(bosque[y][x]== ESPACIO_VACIO){return1;}else{printf("Espacio no vacio\n");return0;}}voidmover(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador,char direccion){printf("El jugador %c elige moverse hacia ", jugador);int xOriginal, yOriginal;if(jugador == ARQUERO_J1){
xOriginal = coordenada_x_jugador_1;
yOriginal = coordenada_y_jugador_1;}else{
xOriginal = coordenada_x_jugador_2;
yOriginal = coordenada_y_jugador_2;}int nuevaX = xOriginal, nuevaY = yOriginal;if(direccion == DIRECCION_ABAJO){printf(" abajo\n");
nuevaY++;}elseif(direccion == DIRECCION_ARRIBA){printf(" arriba\n");
nuevaY--;}elseif(direccion == DIRECCION_DERECHA){printf(" la derecha\n");
nuevaX++;}elseif(direccion == DIRECCION_IZQUIERDA){printf(" la izquierda\n");
nuevaX--;}// Limpiamos la posición anterior
bosque[yOriginal][xOriginal]= ESPACIO_VACIO;// Y movemos al personaje
bosque[nuevaY][nuevaX]= jugador;// Guardamos las coordenadasif(jugador == ARQUERO_J1){
coordenada_x_jugador_1 = nuevaX;
coordenada_y_jugador_1 = nuevaY;}else{
coordenada_x_jugador_2 = nuevaX;
coordenada_y_jugador_2 = nuevaY;}}
Disparar
Disparar flecha en el bosque – Cazadores
La otra función de este juego programado en C es la de disparar. Disfruté mucho programando esta función imaginando el recorrido de la flecha en mi mente para identificar si choca con un árbol, una pared, el jugador o termina su recorrido.
intdisparar(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador,char direccion){printf("El jugador %c dispara la flecha ", jugador);int acertado;switch(direccion){case DIRECCION_IZQUIERDA:printf("a la izquierda\n");
acertado =dispararIzquierda(bosque, jugador);break;case DIRECCION_DERECHA:printf("a la derecha\n");
acertado =dispararDerecha(bosque, jugador);break;case DIRECCION_ARRIBA:printf("hacia arriba\n");
acertado =dispararArriba(bosque, jugador);break;case DIRECCION_ABAJO:default:printf("hacia abajo\n");
acertado =dispararAbajo(bosque, jugador);break;}// Si acertó, entonces aumentamos el conteo de flechas recibidas para el oponenteif(acertado){if(oponente_de(jugador)== ARQUERO_J1){
flechazos_recibidos_jugador_1++;}else{
flechazos_recibidos_jugador_2++;}}// Y devolvemos el estado por si nuestro invocador lo requierereturn acertado;}
Por cierto, esta función aumenta el contador de los flechazos dependiendo del oponente. Ya que si dispara el jugador 1 y acierta, es porque le ha disparado al jugador 2 y viceversa.
Juego en C
Iniciar juego de arqueros en el bosque
Una vez que hemos visto las funciones más importantes veamos cómo es el ciclo principal del juego.
Tenemos la función principal que solo debe ser invocada una vez, ahí se pregunta el tamaño del bosque y, cuando se acaba de jugar, pregunta al usuario si quiere iniciar una nueva partida.
voidjugar(){srand(getpid());char eleccion ='s';while(eleccion =='s'){
medidaGlobalBosque =solicitarMedida();iniciar_nueva_partida();printf("Jugar de nuevo? [s/n]: ");scanf("%c",&eleccion);consumir_nueva_linea();}}
Después tenemos la función que inicia una nueva partida en donde solicitamos al jugador el movimiento, el arquero que inicia el juego, etcétera y comenzamos a jugar preguntando las opciones al usuario mientras vamos imprimiendo el bosque.
voidiniciar_nueva_partida(){char bosque[medidaGlobalBosque][medidaGlobalBosque];preparar_nueva_partida(bosque);char jugador =solicitar_jugador();while(1){colocar_jugadores_en_bosque(bosque);imprimir_bosque(bosque);char eleccion =solicitar_eleccion(jugador);if(eleccion == OPCION_DISPARAR){char direccion_del_disparo =solicitarDireccionDisparo(bosque, jugador);int acertado =disparar(bosque, jugador, direccion_del_disparo);// Si ha acertado, marcamos nuevo roundif(acertado){printf("El flechazo es acertado!. Inicia nuevo round\n");imprimir_estados_salud();preparar_nuevo_round(bosque);}}elseif(eleccion == OPCION_MOVER){char direccion_del_movimiento =solicitarMovimientoJugador(bosque, jugador);mover(bosque, jugador, direccion_del_movimiento);}if(es_ganador(jugador)){printf("El jugador %c gana!\n", jugador);// Con el return terminamos el juegoreturn;}
jugador =oponente_de(jugador);}}
La partida termina cuando un jugador ha recibido dos flechazos:
Y así es como funciona este juego de arqueros o cazadores en el bosque programado con puro C.
Poniendo todo junto
Ya te he explicado el funcionamiento general del juego, las funciones más importantes y todo lo demás. Pero ahora te dejo aquí con el código completo.
Recuerda que todos mis programas son configurables así que puedes cambiar tamaños de tablero, rounds, etcétera.
Además, mis juegos están escritos (al menos los de C) pensando en la portabilidad, por lo que puedes ejecutar esto en Dev C++, CLion, compilarlo con GCC, clang, g++, etcétera.
/*
____ _____ _ _ _
| _ \ | __ \ (_) | | |
| |_) |_ _ | |__) |_ _ _ __ _____| |__ _ _| |_ ___
| _ <| | | | | ___/ _` | '__|_ / | '_ \| | | | __/ _ \
| |_) | |_| | | | | (_| | | / /| | |_) | |_| | || __/
|____/ \__, | |_| \__,_|_| /___|_|_.__/ \__, |\__\___|
__/ | __/ |
|___/ |___/
____________________________________
/ Si necesitas ayuda, contáctame en \
\ https://parzibyte.me /
------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Creado por Parzibyte (https://parzibyte.me).
------------------------------------------------------------------------------------------------
| IMPORTANTE |
Si vas a borrar este encabezado, considera:
Seguirme: https://parzibyte.me/blog/sigueme/
Y compartir mi blog con tus amigos
También tengo canal de YouTube: https://www.youtube.com/channel/UCroP4BTWjfM0CkGB6AFUoBg?sub_confirmation=1
Twitter: https://twitter.com/parzibyte
Facebook: https://facebook.com/parzibyte.fanpage
Instagram: https://instagram.com/parzibyte
Hacer una donación vía PayPal: https://paypal.me/LuisCabreraBenito
------------------------------------------------------------------------------------------------
*/#include<stdio.h>#include<stdlib.h>#include<unistd.h>#define ARQUERO_J1 '1'#define ARQUERO_J2 '2'#define ARBOL 'X'#define ESPACIO_VACIO ' '#define DIRECCION_IZQUIERDA 'L'#define DIRECCION_DERECHA 'R'#define DIRECCION_ARRIBA 'U'#define DIRECCION_ABAJO 'D'#define OPCION_MOVER 'm'#define OPCION_DISPARAR 'd'#define DISTANCIA_MAXIMA_DISPARO 5#define ROUNDS_PARA_PERDER 2/*
* Ajustes del juego
* */int medidaGlobalBosque;// La medida del bosque/*
* Datos del juego
* Llevar control de ubicación de arqueros y de los flechazos recibidos
* */int coordenada_y_jugador_1 =0,
coordenada_x_jugador_1 =0,
coordenada_y_jugador_2 =0,
coordenada_x_jugador_2 =0,
flechazos_recibidos_jugador_1 =0,
flechazos_recibidos_jugador_2 =0;/*
* Funciones que componen al juego
* */// Devuelve un número aleatorio entre minimo y maximo, incluyendo a minimo y maximointaleatorio_en_rango(int minimo,int maximo){return minimo +rand()/(RAND_MAX /(maximo - minimo +1)+1);}voidlimpiar_bosque(char bosque[medidaGlobalBosque][medidaGlobalBosque]){for(int y =0; y < medidaGlobalBosque; y++){for(int x =0; x < medidaGlobalBosque; x++){
bosque[y][x]= ESPACIO_VACIO;}}}voidcolocar_arboles_en_bosque(char bosque[medidaGlobalBosque][medidaGlobalBosque]){int contador =0;while(contador < medidaGlobalBosque){int x =aleatorio_en_rango(0, medidaGlobalBosque -1);int y =aleatorio_en_rango(0, medidaGlobalBosque -1);// Colocar árboles solo si no hay nada (en especial no debemos colocarlos en donde haya jugadores)if(bosque[y][x]== ESPACIO_VACIO){
bosque[y][x]= ARBOL;
contador++;}}}voidcolocar_jugadores_en_bosque(char bosque[medidaGlobalBosque][medidaGlobalBosque]){
bosque[coordenada_y_jugador_1][coordenada_x_jugador_1]= ARQUERO_J1;
bosque[coordenada_y_jugador_2][coordenada_x_jugador_2]= ARQUERO_J2;}voidimprimir_bosque(char bosque[medidaGlobalBosque][medidaGlobalBosque]){int contador =0;// Un separadorprintf("\n\n");while(contador < medidaGlobalBosque){printf("_____");
contador++;}printf("\n");// Letrasprintf("| ");char c ='A';
contador =0;while(contador < medidaGlobalBosque){printf("| %c ", c);
c++;
contador++;}printf("|\n");for(int y =0; y < medidaGlobalBosque; y++){printf("| %d |", y +1);for(int x =0; x < medidaGlobalBosque; x++){printf(" %c |", bosque[y][x]);}printf("\n");}}intjugador_puede_moverse(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador,char direccion){int x, y;if(jugador == ARQUERO_J1){
x = coordenada_x_jugador_1;
y = coordenada_y_jugador_1;}else{
x = coordenada_x_jugador_2;
y = coordenada_y_jugador_2;}if(direccion == DIRECCION_ABAJO){
y++;}elseif(direccion == DIRECCION_ARRIBA){
y--;}elseif(direccion == DIRECCION_DERECHA){
x++;}elseif(direccion == DIRECCION_IZQUIERDA){
x--;}else{// Si no es ninguna dirección válida, regresamos falsereturn0;}// Luego de modificar las coordenadas, vemos si son válidas. Comprobamos si están dentro del tableroif(x <0|| x >= medidaGlobalBosque || y <0|| y >= medidaGlobalBosque){printf("Posicion fuera del tablero\n");return0;}// Y comprobamos si no es un árbol u otro jugadorif(bosque[y][x]== ESPACIO_VACIO){return1;}else{printf("Espacio no vacio\n");return0;}}voidmover(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador,char direccion){printf("El jugador %c elige moverse hacia ", jugador);int xOriginal, yOriginal;if(jugador == ARQUERO_J1){
xOriginal = coordenada_x_jugador_1;
yOriginal = coordenada_y_jugador_1;}else{
xOriginal = coordenada_x_jugador_2;
yOriginal = coordenada_y_jugador_2;}int nuevaX = xOriginal, nuevaY = yOriginal;if(direccion == DIRECCION_ABAJO){printf(" abajo\n");
nuevaY++;}elseif(direccion == DIRECCION_ARRIBA){printf(" arriba\n");
nuevaY--;}elseif(direccion == DIRECCION_DERECHA){printf(" la derecha\n");
nuevaX++;}elseif(direccion == DIRECCION_IZQUIERDA){printf(" la izquierda\n");
nuevaX--;}// Limpiamos la posición anterior
bosque[yOriginal][xOriginal]= ESPACIO_VACIO;// Y movemos al personaje
bosque[nuevaY][nuevaX]= jugador;// Guardamos las coordenadasif(jugador == ARQUERO_J1){
coordenada_x_jugador_1 = nuevaX;
coordenada_y_jugador_1 = nuevaY;}else{
coordenada_x_jugador_2 = nuevaX;
coordenada_y_jugador_2 = nuevaY;}}voidconsumir_nueva_linea(void){int c;do{
c =getchar();}while(c !=EOF&& c !='\n');}charsolicitarMovimientoJugador(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador){char direccion = DIRECCION_IZQUIERDA;while(1){printf("%c - Arriba\n%c - Abajo\n%c - Derecha\n%c - Izquierda\nJugador %c. Ingrese la direccion para moverse: ",
DIRECCION_ARRIBA, DIRECCION_ABAJO, DIRECCION_DERECHA, DIRECCION_IZQUIERDA, jugador);scanf("%c",&direccion);consumir_nueva_linea();if(jugador_puede_moverse(bosque, jugador, direccion)){return direccion;}else{printf("No se puede mover hacia esa direccion. Intente de nuevo\n");}}}intesDireccionValida(char direccion){if(direccion == DIRECCION_ARRIBA || direccion == DIRECCION_DERECHA || direccion == DIRECCION_ABAJO ||
direccion == DIRECCION_IZQUIERDA){return1;}return0;}charsolicitarDireccionDisparo(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador){char direccion = DIRECCION_IZQUIERDA;while(1){printf("%c - Arriba\n%c - Abajo\n%c - Derecha\n%c - Izquierda\nJugador %c. Ingrese la direccion para disparar: ",
DIRECCION_ARRIBA, DIRECCION_ABAJO, DIRECCION_DERECHA, DIRECCION_IZQUIERDA, jugador);scanf("%c",&direccion);consumir_nueva_linea();if(esDireccionValida(direccion)){return direccion;}else{printf("No puede disparar en esa direccion. Intente de nuevo\n");}}}charoponente_de(char jugador){if(jugador == ARQUERO_J1){return ARQUERO_J2;}else{return ARQUERO_J1;}}intdispararIzquierda(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador){int x, y;if(jugador == ARQUERO_J1){
x = coordenada_x_jugador_1;
y = coordenada_y_jugador_1;}else{
x = coordenada_x_jugador_2;
y = coordenada_y_jugador_2;}int metrosAvance =0;while(metrosAvance < DISTANCIA_MAXIMA_DISPARO && x >0){
x--;
metrosAvance++;// La flecha impactó con un árbol, así que no llegó al objetivoif(bosque[y][x]== ARBOL){printf("Flecha impacta con un arbol");return0;}elseif(bosque[y][x]==oponente_de(jugador)){// Significa que le ha disparado al oponenteprintf("Flecha impacta al jugador %c\n",oponente_de(jugador));return1;}}// La flecha acabó su recorrido y no chocó con un árbol ni con el oponenteprintf("Flecha ha terminado su recorrido");return0;}intdispararDerecha(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador){int x, y;if(jugador == ARQUERO_J1){
x = coordenada_x_jugador_1;
y = coordenada_y_jugador_1;}else{
x = coordenada_x_jugador_2;
y = coordenada_y_jugador_2;}int metrosAvance =0;while(metrosAvance < DISTANCIA_MAXIMA_DISPARO && x < medidaGlobalBosque -1){
x++;
metrosAvance++;// La flecha impactó con un árbol, así que no llegó al objetivoif(bosque[y][x]== ARBOL){printf("Flecha impacta con un arbol");return0;}elseif(bosque[y][x]==oponente_de(jugador)){// Significa que le ha disparado al oponenteprintf("Flecha impacta al jugador %c\n",oponente_de(jugador));return1;}}// La flecha acabó su recorrido y no chocó con un árbol ni con el oponenteprintf("Flecha ha terminado su recorrido");return0;}intdispararArriba(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador){int x, y;if(jugador == ARQUERO_J1){
x = coordenada_x_jugador_1;
y = coordenada_y_jugador_1;}else{
x = coordenada_x_jugador_2;
y = coordenada_y_jugador_2;}int metrosAvance =0;while(metrosAvance < DISTANCIA_MAXIMA_DISPARO && y >0){
y--;
metrosAvance++;// La flecha impactó con un árbol, así que no llegó al objetivoif(bosque[y][x]== ARBOL){printf("Flecha impacta con un arbol");return0;}elseif(bosque[y][x]==oponente_de(jugador)){// Significa que le ha disparado al oponenteprintf("Flecha impacta al jugador %c\n",oponente_de(jugador));return1;}}// La flecha acabó su recorrido y no chocó con un árbol ni con el oponenteprintf("Flecha ha terminado su recorrido");return0;}intdispararAbajo(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador){int x, y;if(jugador == ARQUERO_J1){
x = coordenada_x_jugador_1;
y = coordenada_y_jugador_1;}else{
x = coordenada_x_jugador_2;
y = coordenada_y_jugador_2;}int metrosAvance =0;while(metrosAvance < DISTANCIA_MAXIMA_DISPARO && y < medidaGlobalBosque -1){
y++;
metrosAvance++;// La flecha impactó con un árbol, así que no llegó al objetivoif(bosque[y][x]== ARBOL){printf("Flecha impacta con un arbol");return0;}elseif(bosque[y][x]==oponente_de(jugador)){// Significa que le ha disparado al oponenteprintf("Flecha impacta al jugador %c\n",oponente_de(jugador));return1;}}// La flecha acabó su recorrido y no chocó con un árbol ni con el oponenteprintf("Flecha ha terminado su recorrido");return0;}intdisparar(char bosque[medidaGlobalBosque][medidaGlobalBosque],char jugador,char direccion){printf("El jugador %c dispara la flecha ", jugador);int acertado;switch(direccion){case DIRECCION_IZQUIERDA:printf("a la izquierda\n");
acertado =dispararIzquierda(bosque, jugador);break;case DIRECCION_DERECHA:printf("a la derecha\n");
acertado =dispararDerecha(bosque, jugador);break;case DIRECCION_ARRIBA:printf("hacia arriba\n");
acertado =dispararArriba(bosque, jugador);break;case DIRECCION_ABAJO:default:printf("hacia abajo\n");
acertado =dispararAbajo(bosque, jugador);break;}// Si acertó, entonces aumentamos el conteo de flechas recibidas para el oponenteif(acertado){if(oponente_de(jugador)== ARQUERO_J1){
flechazos_recibidos_jugador_1++;}else{
flechazos_recibidos_jugador_2++;}}// Y devolvemos el estado por si nuestro invocador lo requierereturn acertado;}intes_ganador(char jugador){if(jugador == ARQUERO_J1){return flechazos_recibidos_jugador_2 >= ROUNDS_PARA_PERDER;}else{return flechazos_recibidos_jugador_1 >= ROUNDS_PARA_PERDER;}}voidreiniciar_posicion_arqueros(){
coordenada_x_jugador_1 =0;
coordenada_y_jugador_1 = medidaGlobalBosque -1;
coordenada_x_jugador_2 = medidaGlobalBosque -1;
coordenada_y_jugador_2 =0;}voidpreparar_nuevo_round(char bosque[medidaGlobalBosque][medidaGlobalBosque]){limpiar_bosque(bosque);reiniciar_posicion_arqueros();colocar_jugadores_en_bosque(bosque);colocar_arboles_en_bosque(bosque);}voidpreparar_nueva_partida(char bosque[medidaGlobalBosque][medidaGlobalBosque]){preparar_nuevo_round(bosque);
flechazos_recibidos_jugador_1 =0;
flechazos_recibidos_jugador_2 =0;}intsolicitarMedida(){int medida;while(1){printf("Ingrese la medida del bosque. Puede ser de 5, 7 o 9: ");scanf("%d",&medida);consumir_nueva_linea();if(medida ==5|| medida ==7|| medida ==9){return medida;}else{printf("La medida no es correcta\n");}}}charsolicitar_jugador(){char jugador = ARQUERO_J1;while(1){printf("%c - Arquero 1\n%c - Arquero 2. Seleccione quien empieza la partida: ", ARQUERO_J1, ARQUERO_J2);scanf("%c",&jugador);consumir_nueva_linea();if(jugador == ARQUERO_J1 || jugador == ARQUERO_J2){return jugador;}else{printf("Jugador incorrecto\n");}}}charsolicitar_eleccion(char jugador){char eleccion =' ';while(1){printf("%c - Mover\n%c - Disparar. Jugador %c seleccione una opcion: ", OPCION_MOVER, OPCION_DISPARAR, jugador);scanf("%c",&eleccion);consumir_nueva_linea();if(eleccion == OPCION_MOVER || eleccion == OPCION_DISPARAR){return eleccion;}else{printf("La opcion no es correcta\n");}}}voidimprimir_estados_salud(){printf("Jugador %c. Flechazos recibidos: %d\n", ARQUERO_J1, flechazos_recibidos_jugador_1);printf("Jugador %c. Flechazos recibidos: %d\n", ARQUERO_J2, flechazos_recibidos_jugador_2);}voidiniciar_nueva_partida(){char bosque[medidaGlobalBosque][medidaGlobalBosque];preparar_nueva_partida(bosque);char jugador =solicitar_jugador();while(1){colocar_jugadores_en_bosque(bosque);imprimir_bosque(bosque);char eleccion =solicitar_eleccion(jugador);if(eleccion == OPCION_DISPARAR){char direccion_del_disparo =solicitarDireccionDisparo(bosque, jugador);int acertado =disparar(bosque, jugador, direccion_del_disparo);// Si ha acertado, marcamos nuevo roundif(acertado){printf("El flechazo es acertado!. Inicia nuevo round\n");imprimir_estados_salud();preparar_nuevo_round(bosque);}}elseif(eleccion == OPCION_MOVER){char direccion_del_movimiento =solicitarMovimientoJugador(bosque, jugador);mover(bosque, jugador, direccion_del_movimiento);}if(es_ganador(jugador)){printf("El jugador %c gana!\n", jugador);// Con el return terminamos el juegoreturn;}
jugador =oponente_de(jugador);}}voidjugar(){srand(getpid());char eleccion ='s';while(eleccion =='s'){
medidaGlobalBosque =solicitarMedida();iniciar_nueva_partida();printf("Jugar de nuevo? [s/n]: ");scanf("%c",&eleccion);consumir_nueva_linea();}}intmain(){jugar();}
Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto
No te pierdas ninguno de mis posts
Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.